From 1337c15d1d5d31e8cf0e3416d1af67abe79b129f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 22 Dec 2015 15:17:31 +0100 Subject: [PATCH 001/825] CPP-1001 Attach to existing local process: debug session tests + obsolete PendingBreakpointsHandler deleted --- .../com/intellij/util/ThrowableFunction.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 platform/util-rt/src/com/intellij/util/ThrowableFunction.java diff --git a/platform/util-rt/src/com/intellij/util/ThrowableFunction.java b/platform/util-rt/src/com/intellij/util/ThrowableFunction.java new file mode 100644 index 000000000000..7e5d14741b34 --- /dev/null +++ b/platform/util-rt/src/com/intellij/util/ThrowableFunction.java @@ -0,0 +1,20 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util; + +public interface ThrowableFunction { + Result fun(Param param) throws E; +} From e4465d4b882a17ff9270540078ffbcd3437d0f39 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 24 Dec 2015 18:06:51 +0100 Subject: [PATCH 002/825] CPP-1001 Attach to existing local process: ProcessInfo API improved --- .../execution/process/IProcessList.java | 2 +- .../execution/process/ProcessInfo.java | 42 +++++++++++++------ .../execution/process/ProcessListWin32.java | 2 +- .../execution/process/ProcessUtils.java | 8 +++- .../attach/PyAttachToProcessAction.java | 9 ++-- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java b/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java index 2d041213371e..07d57512d11e 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java +++ b/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java @@ -30,6 +30,6 @@ package com.intellij.execution.process; * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ -public interface IProcessList { +interface IProcessList { ProcessInfo[] getProcessList(); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index d5a9acf51cda..6b7ecf923b03 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -15,6 +15,9 @@ */ package com.intellij.execution.process; +import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.annotations.NotNull; + /** * @author traff */ @@ -22,34 +25,47 @@ public class ProcessInfo { public static ProcessInfo[] EMPTY_ARRAY = new ProcessInfo[0]; private final int myPid; - private final String myCommand; - private final String myArgs; + @NotNull private final String myExecutable; + @NotNull private final String myCommandLine; - public ProcessInfo(String pidString, String name) { - this(Integer.parseInt(pidString), name); + public ProcessInfo(@NotNull String pidString, @NotNull String commandLine) { + this(Integer.parseInt(pidString), commandLine); } - public ProcessInfo(int pid, String name) { + public ProcessInfo(int pid, @NotNull String commandLine) { myPid = pid; - String[] args = name.split(" "); - myCommand = args.length > 0 ? args[0] : ""; - myArgs = name; + String[] args = commandLine.split(" "); + myExecutable = args.length > 0 ? args[0] : ""; + myCommandLine = commandLine; + } + + public ProcessInfo(int pid, @NotNull String executables, @NotNull String args) { + myPid = pid; + myExecutable = executables; + myCommandLine = executables + " " + args; } public int getPid() { return myPid; } - public String getCommand() { - return myCommand; + @NotNull + public String getExecutable() { + return myExecutable; } - public String getArgs() { - return myArgs; + @NotNull + public String getExecutableName() { + return FileUtil.getNameWithoutExtension(myExecutable); + } + + @NotNull + public String getCommandLine() { + return myCommandLine; } @Override public String toString() { - return String.valueOf(myPid) + " (" + myArgs + ")"; + return String.valueOf(myPid) + " (" + myCommandLine + ")"; } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java index cffabc591f88..df7354278688 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java @@ -100,7 +100,7 @@ class ProcessListWin32 implements IProcessList { String name = line.substring(0, commandLineI).trim(); String commandLine = line.substring(commandLineI, processIdI).trim(); String processId = line.substring(processIdI, line.length()).trim(); - lst.add(new ProcessInfo(Integer.parseInt(processId), name + " " + commandLine)); + lst.add(new ProcessInfo(Integer.parseInt(processId), name, commandLine)); } if (lst.size() == 0) { throw new AssertionError("Error: no processes found"); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java index 072908c9a6dc..7739519a5266 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java @@ -62,7 +62,13 @@ public class ProcessUtils { } - public static IProcessList getProcessList(String helpersRoot) { + @NotNull + public static ProcessInfo[] getProcessList(@NotNull String helpersRoot) { + return getProcessListImpl(helpersRoot).getProcessList(); + } + + @NotNull + private static IProcessList getProcessListImpl(@NotNull String helpersRoot) { if (SystemInfo.isWindows) { return new ProcessListWin32(helpersRoot); } diff --git a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java index 11498dadb580..e43479cc20b1 100644 --- a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java +++ b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java @@ -20,6 +20,7 @@ import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessInfo; +import com.intellij.execution.process.ProcessUtils; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -29,8 +30,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.SelectFromListDialog; +import com.intellij.openapi.util.text.StringUtil; import com.jetbrains.python.PythonHelpersLocator; -import com.intellij.execution.process.ProcessUtils; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -65,7 +66,7 @@ public class PyAttachToProcessAction extends AnAction { public String getToStirng(Object obj) { ProcessInfo info = (ProcessInfo)obj; - return info.getPid() + " " + info.getArgs(); + return info.getPid() + " " + info.getCommandLine(); } }, "Select Python Process", ListSelectionModel.SINGLE_SELECTION); if (selectDialog.showAndGet()) { @@ -85,11 +86,11 @@ public class PyAttachToProcessAction extends AnAction { } private static ProcessInfo[] pythonProcessesList() { - ProcessInfo[] list = ProcessUtils.getProcessList(PythonHelpersLocator.getHelpersRoot().getAbsolutePath()).getProcessList(); + ProcessInfo[] list = ProcessUtils.getProcessList(PythonHelpersLocator.getHelpersRoot().getAbsolutePath()); return FluentIterable.from(Lists.newArrayList(list)).filter(new Predicate() { @Override public boolean apply(ProcessInfo input) { - return input.getCommand().toLowerCase().contains("python"); + return StringUtil.containsIgnoreCase(input.getExecutableName(), "python"); } }).toArray(ProcessInfo.class); } From 70c44de74090dfe3d85edb6dbdf17cc73ad3fa98 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 24 Dec 2015 18:21:45 +0100 Subject: [PATCH 003/825] CPP-1001 Attach to existing local process: general ProcessInfo API used + some refactorings and error better reporting --- .../src/com/intellij/execution/process/ProcessInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index 6b7ecf923b03..13f627637b48 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -16,6 +16,7 @@ package com.intellij.execution.process; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; /** @@ -56,7 +57,7 @@ public class ProcessInfo { @NotNull public String getExecutableName() { - return FileUtil.getNameWithoutExtension(myExecutable); + return FileUtil.getNameWithoutExtension(PathUtil.getFileName(myExecutable)); } @NotNull From e0722d0e7014b252f79111b39cdd5588a116d3c4 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 24 Dec 2015 22:24:37 +0100 Subject: [PATCH 004/825] IDEA-149798 Extensible 'Attach to Local Process' action: initial --- .../src/messages/XDebuggerBundle.properties | 3 + .../src/META-INF/xdebugger.xml | 8 ++ .../attach/XLocalAttachDebugger.java | 30 +++++ .../attach/XLocalAttachDebuggerProvider.java | 30 +++++ .../actions/AttachToLocalProcessAction.java | 127 ++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebugger.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index ca129821f44e..56000030ddd5 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -9,6 +9,9 @@ debugger.hotswap.display.name=HotSwap xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger +xdebugger.attach.toLocal.action=Attach to Local Process... +xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger + xdebugger.remove.line.breakpoint.action.text=Remove breakpoint xdebugger.disable.breakpoint.action.text=Disable breakpoint xdebugger.enable.breakpoint.action.text=Enable breakpoint diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index 511f4f24856b..09309bc53872 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -11,6 +11,7 @@ + @@ -43,4 +44,11 @@ + + + + + + + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebugger.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebugger.java new file mode 100644 index 000000000000..9bb40127bed6 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebugger.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.attach; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.project.Project; +import com.intellij.xdebugger.XDebugSession; +import org.jetbrains.annotations.NotNull; + +public interface XLocalAttachDebugger { + @NotNull + String getDebuggerDisplayName(); + + @NotNull + XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException; +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java new file mode 100644 index 000000000000..dd5700db181a --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.attach; + +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface XLocalAttachDebuggerProvider { + ExtensionPointName EP = ExtensionPointName.create("com.intellij.xdebugger.localAttachDebuggerProvider"); + + @NotNull + List getAvailableDebuggers(@NotNull Project project, @NotNull ProcessInfo processInfo); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java new file mode 100644 index 000000000000..1533eacc30ff --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -0,0 +1,127 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.impl.actions; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessInfo; +import com.intellij.execution.process.ProcessUtils; +import com.intellij.execution.runners.ExecutionUtil; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.attach.XLocalAttachDebugger; +import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +public class AttachToLocalProcessAction extends AnAction { + public AttachToLocalProcessAction() { + super(XDebuggerBundle.message("xdebugger.attach.toLocal.action"), + XDebuggerBundle.message("xdebugger.attach.toLocal.action.description"), null); + } + + @Override + public void update(AnActionEvent e) { + super.update(e); + + Project project = getEventProject(e); + boolean enabled = project != null && Extensions.getExtensions(XLocalAttachDebuggerProvider.EP).length > 0; + e.getPresentation().setEnabledAndVisible(enabled); + } + + @Override + public void actionPerformed(AnActionEvent e) { + final Project project = getEventProject(e); + if (project == null) return; + + List items = collectAttachItems(project); + if (items.isEmpty()) { + // todo show message + } + + JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Attach", items) { + @Override + public boolean isSpeedSearchEnabled() { + return true; + } + + @NotNull + @Override + public String getTextFor(AttachItem value) { + return value.info.getPid() + " " + value.info.getExecutableName(); + } + + @Override + public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { + startDebugSession(project, selectedValue.debuggers.get(0), selectedValue.info); + return super.onChosen(selectedValue, finalChoice); + } + }).showCenteredInCurrentWindow(project); + } + + @NotNull + private static List collectAttachItems(@NotNull Project project) { + List result = new ArrayList(); + + for (ProcessInfo eachInfo : ProcessUtils.getProcessList("")) { + List availableDebuggers = new ArrayList(); + for (XLocalAttachDebuggerProvider eachProvider : Extensions.getExtensions(XLocalAttachDebuggerProvider.EP)) { + availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo)); + } + if (!availableDebuggers.isEmpty()) { + result.add(new AttachItem(eachInfo, availableDebuggers)); + } + } + return result; + } + + private static void startDebugSession(@NotNull Project project, + @NotNull XLocalAttachDebugger debugger, + @NotNull ProcessInfo info) { + try { + debugger.attachDebugSession(project, info); + } + catch (ExecutionException e) { + ExecutionUtil.handleExecutionError(project, ToolWindowId.DEBUG, info.getExecutableName(), e); + } + } + + + public static class AttachItem { + @NotNull private final ProcessInfo info; + @NotNull private final List debuggers; + + public AttachItem(@NotNull ProcessInfo info, @NotNull List debuggers) { + this.info = info; + this.debuggers = debuggers; + } + + @Nullable + public Icon getIcon() { + return null; + } + } +} From ead9ae0c09ecd37f25a0a4b0f8b8a30c550a5f08 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 25 Dec 2015 16:47:22 +0100 Subject: [PATCH 005/825] IDEA-149798 Extensible 'Attach to Local Process' action: initial --- platform/platform-resources/src/META-INF/xdebugger.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index 09309bc53872..88f64126b454 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -48,7 +48,7 @@ - + From 3318275d8042e4f100a23810c17a233ef7fec465 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 25 Dec 2015 18:46:04 +0100 Subject: [PATCH 006/825] IDEA-149798 Extensible Attach to Local Process action: liststask.exe is now in platform --- .../helpers/process => bin/win}/listtasks.exe | Bin .../execution/process/ProcessListWin32.java | 8 +--- .../process/ProcessListWin32Internal.java | 41 +++++++++++------- .../execution/process/ProcessUtils.java | 8 ++-- .../src/messages/XDebuggerBundle.properties | 1 + .../actions/AttachToLocalProcessAction.java | 37 ++++++++-------- .../attach/PyAttachToProcessAction.java | 3 +- 7 files changed, 53 insertions(+), 45 deletions(-) rename {python/helpers/process => bin/win}/listtasks.exe (100%) diff --git a/python/helpers/process/listtasks.exe b/bin/win/listtasks.exe similarity index 100% rename from python/helpers/process/listtasks.exe rename to bin/win/listtasks.exe diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java index df7354278688..cf24db61078a 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java @@ -33,12 +33,6 @@ import java.util.List; class ProcessListWin32 implements IProcessList { private static final Logger LOG = Logger.getInstance(ProcessListWin32.class); - private String myHelpersRoot; - - public ProcessListWin32(String helpersRoot) { - myHelpersRoot = helpersRoot; - } - @Override public ProcessInfo[] getProcessList() { try { @@ -56,7 +50,7 @@ class ProcessListWin32 implements IProcessList { } catch (Exception e) { //Use fallback - return new ProcessListWin32Internal(myHelpersRoot).getProcessList(); + return new ProcessListWin32Internal().getProcessList(); } try { return parseListTasks(p.getInputStream()); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java index 70c3180be776..3ed247016c43 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java @@ -15,6 +15,8 @@ */ package com.intellij.execution.process; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.containers.ContainerUtil; import java.io.*; @@ -26,25 +28,34 @@ import java.util.List; * Use through ProcessUtils. */ class ProcessListWin32Internal implements IProcessList { - private String myHelpersRoot; - - public ProcessListWin32Internal(String helpersRoot) { - myHelpersRoot = helpersRoot; - } + private static final Logger LOG = Logger.getInstance(ProcessListWin32Internal.class); @Override public ProcessInfo[] getProcessList() { + String[] dirs = { + PathManager.getBinPath(), + PathManager.getHomePath() + "/community/bin/win", + PathManager.getBinPath() + "/win"}; + + File listtasks = null; + + for (String each : dirs) { + listtasks = new File(each, "listtasks.exe"); + } + + if (!listtasks.exists()) { + LOG.error("listtasks.exe not found in bin folders"); + return ProcessInfo.EMPTY_ARRAY; + } + try { - File file = new File(myHelpersRoot, "process/listtasks.exe"); - if (file.exists()) { - String[] command = {file.getCanonicalPath()}; - Process p = ProcessUtils.createProcess(command, null, null); - try { - return parseListTasks(p.getInputStream()); - } - finally { - p.destroy(); - } + String[] command = {listtasks.getCanonicalPath()}; + Process p = ProcessUtils.createProcess(command, null, null); + try { + return parseListTasks(p.getInputStream()); + } + finally { + p.destroy(); } } catch (IOException ignored) { } diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java index 7739519a5266..a96be96e96a7 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java @@ -63,14 +63,14 @@ public class ProcessUtils { @NotNull - public static ProcessInfo[] getProcessList(@NotNull String helpersRoot) { - return getProcessListImpl(helpersRoot).getProcessList(); + public static ProcessInfo[] getProcessList() { + return getProcessListImpl().getProcessList(); } @NotNull - private static IProcessList getProcessListImpl(@NotNull String helpersRoot) { + private static IProcessList getProcessListImpl() { if (SystemInfo.isWindows) { - return new ProcessListWin32(helpersRoot); + return new ProcessListWin32(); } if (SystemInfo.isLinux) { return new ProcessListLinux(); diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 56000030ddd5..4813b4380d62 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -9,6 +9,7 @@ debugger.hotswap.display.name=HotSwap xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger +xdebugger.attach.toLocal.popup.title=Attach xdebugger.attach.toLocal.action=Attach to Local Process... xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 1533eacc30ff..7e2d7de3ed0a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -62,31 +62,34 @@ public class AttachToLocalProcessAction extends AnAction { // todo show message } - JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Attach", items) { - @Override - public boolean isSpeedSearchEnabled() { - return true; - } + BaseListPopupStep step = + new BaseListPopupStep(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items) { + @Override + public boolean isSpeedSearchEnabled() { + return true; + } - @NotNull - @Override - public String getTextFor(AttachItem value) { - return value.info.getPid() + " " + value.info.getExecutableName(); - } + @NotNull + @Override + public String getTextFor(AttachItem value) { + return value.info.getPid() + " " + value.info.getExecutableName(); + } - @Override - public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { - startDebugSession(project, selectedValue.debuggers.get(0), selectedValue.info); - return super.onChosen(selectedValue, finalChoice); - } - }).showCenteredInCurrentWindow(project); + @Override + public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { + startDebugSession(project, selectedValue.debuggers.get(0), selectedValue.info); + return super.onChosen(selectedValue, finalChoice); + } + }; + + JBPopupFactory.getInstance().createListPopup(step).showCenteredInCurrentWindow(project); } @NotNull private static List collectAttachItems(@NotNull Project project) { List result = new ArrayList(); - for (ProcessInfo eachInfo : ProcessUtils.getProcessList("")) { + for (ProcessInfo eachInfo : ProcessUtils.getProcessList()) { List availableDebuggers = new ArrayList(); for (XLocalAttachDebuggerProvider eachProvider : Extensions.getExtensions(XLocalAttachDebuggerProvider.EP)) { availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo)); diff --git a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java index e43479cc20b1..5bd3957fa853 100644 --- a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java +++ b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java @@ -31,7 +31,6 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.SelectFromListDialog; import com.intellij.openapi.util.text.StringUtil; -import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -86,7 +85,7 @@ public class PyAttachToProcessAction extends AnAction { } private static ProcessInfo[] pythonProcessesList() { - ProcessInfo[] list = ProcessUtils.getProcessList(PythonHelpersLocator.getHelpersRoot().getAbsolutePath()); + ProcessInfo[] list = ProcessUtils.getProcessList(); return FluentIterable.from(Lists.newArrayList(list)).filter(new Predicate() { @Override public boolean apply(ProcessInfo input) { From 9f8672a6130ba9c9e699f5729228bc68f7b40ae2 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 26 Dec 2015 12:33:38 +0100 Subject: [PATCH 007/825] IDEA-149798 Extensible Attach to Local Process action: select debuggers from submenu + set empty text for the popup in case no process available --- .../openapi/ui/popup/ListPopupStepEx.java | 4 + .../intellij/ui/popup/PopupFactoryImpl.java | 5 + .../intellij/ui/popup/list/ListPopupImpl.java | 6 +- .../src/messages/XDebuggerBundle.properties | 2 + .../actions/AttachToLocalProcessAction.java | 157 +++++++++++++----- 5 files changed, 132 insertions(+), 42 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStepEx.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStepEx.java index 75dd6e84fbe4..c69df8ab895e 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStepEx.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStepEx.java @@ -1,6 +1,8 @@ package com.intellij.openapi.ui.popup; +import com.intellij.util.ui.StatusText; import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.event.InputEvent; @@ -10,4 +12,6 @@ public interface ListPopupStepEx extends ListPopupStep { @Nullable String getTooltipTextFor(T value); + + void setEmptyText(@NotNull StatusText emptyText); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java index 02873b3e8717..16380ca99424 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java @@ -57,6 +57,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.WeakHashMap; import com.intellij.util.ui.EmptyIcon; +import com.intellij.util.ui.StatusText; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -803,6 +804,10 @@ public class PopupFactoryImpl extends JBPopupFactory { return value.getDescription(); } + @Override + public void setEmptyText(@NotNull StatusText emptyText) { + } + @Override public ListSeparator getSeparatorAbove(final ActionItem value) { return value.isPrependWithSeparator() ? new ListSeparator(value.getSeparatorText()) : null; diff --git a/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java index 77d2aaf8f43a..045fe1ee9926 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java @@ -226,11 +226,15 @@ public class ListPopupImpl extends WizardPopup implements ListPopup { myMouseMotionListener = new MyMouseMotionListener(); myMouseListener = new MyMouseListener(); - myListModel = new ListPopupModel(this, getSpeedSearch(), getListStep()); + ListPopupStep step = getListStep(); + myListModel = new ListPopupModel(this, getSpeedSearch(), step); myList = new MyList(); if (myStep.getTitle() != null) { myList.getAccessibleContext().setAccessibleName(myStep.getTitle()); } + if (step instanceof ListPopupStepEx) { + ((ListPopupStepEx)step).setEmptyText(myList.getEmptyText()); + } myList.setSelectionMode(isMultiSelectionEnabled() ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION); myList.setSelectedIndex(0); diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 4813b4380d62..33b31b1530bc 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -10,6 +10,8 @@ xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger xdebugger.attach.toLocal.popup.title=Attach +xdebugger.attach.toLocal.popup.emptyText=No process to attach to +xdebugger.attach.toLocal.popup.selectDebugger.title=Select Debugger xdebugger.attach.toLocal.action=Attach to Local Process... xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 7e2d7de3ed0a..6c9b133b989e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -24,17 +24,24 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopupStepEx; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.StatusText; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.attach.XLocalAttachDebugger; import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.event.InputEvent; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class AttachToLocalProcessAction extends AnAction { @@ -57,31 +64,7 @@ public class AttachToLocalProcessAction extends AnAction { final Project project = getEventProject(e); if (project == null) return; - List items = collectAttachItems(project); - if (items.isEmpty()) { - // todo show message - } - - BaseListPopupStep step = - new BaseListPopupStep(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items) { - @Override - public boolean isSpeedSearchEnabled() { - return true; - } - - @NotNull - @Override - public String getTextFor(AttachItem value) { - return value.info.getPid() + " " + value.info.getExecutableName(); - } - - @Override - public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { - startDebugSession(project, selectedValue.debuggers.get(0), selectedValue.info); - return super.onChosen(selectedValue, finalChoice); - } - }; - + MyPopupStep step = new MyPopupStep(collectAttachItems(project), project); JBPopupFactory.getInstance().createListPopup(step).showCenteredInCurrentWindow(project); } @@ -101,30 +84,122 @@ public class AttachToLocalProcessAction extends AnAction { return result; } - private static void startDebugSession(@NotNull Project project, - @NotNull XLocalAttachDebugger debugger, - @NotNull ProcessInfo info) { - try { - debugger.attachDebugSession(project, info); - } - catch (ExecutionException e) { - ExecutionUtil.handleExecutionError(project, ToolWindowId.DEBUG, info.getExecutableName(), e); - } - } - - public static class AttachItem { - @NotNull private final ProcessInfo info; - @NotNull private final List debuggers; + @NotNull private final ProcessInfo myProcessInfo; + @NotNull private final List myDebuggers; + @NotNull private final List mySubItems; public AttachItem(@NotNull ProcessInfo info, @NotNull List debuggers) { - this.info = info; - this.debuggers = debuggers; + assert !debuggers.isEmpty(); + + this.myProcessInfo = info; + this.myDebuggers = debuggers; + if (debuggers.size() > 1) { + mySubItems = ContainerUtil.map(debuggers, new Function() { + @Override + public AttachItem fun(XLocalAttachDebugger debugger) { + return new AttachItem(myProcessInfo, Collections.singletonList(debugger)); + } + }); + } + else { + mySubItems = Collections.emptyList(); + } } @Nullable public Icon getIcon() { return null; } + + @NotNull + public XLocalAttachDebugger getSelectedDebugger() { + return myDebuggers.get(0); + } + + @NotNull + public List getSubItems() { + return mySubItems; + } + + public void startDebugSession(@NotNull Project project) { + try { + getSelectedDebugger().attachDebugSession(project, myProcessInfo); + } + catch (ExecutionException e) { + ExecutionUtil.handleExecutionError(project, ToolWindowId.DEBUG, myProcessInfo.getExecutableName(), e); + } + } + } + + private static class MyPopupStep extends BaseListPopupStep implements ListPopupStepEx { + private final Project myProject; + + public MyPopupStep(List items, Project project) { + super(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items); + myProject = project; + } + + @Override + public boolean isSpeedSearchEnabled() { + return true; + } + + @NotNull + @Override + public String getTextFor(AttachItem value) { + return value.myProcessInfo.getPid() + " " + value.myProcessInfo.getExecutableName(); + } + + @Override + public boolean hasSubstep(AttachItem selectedValue) { + return !selectedValue.getSubItems().isEmpty(); + } + + @Nullable + @Override + public String getTooltipTextFor(AttachItem value) { + return null; + } + + @Override + public void setEmptyText(@NotNull StatusText emptyText) { + emptyText.setText(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.emptyText")); + } + + @Override + public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { + if (finalChoice) { + selectedValue.startDebugSession(myProject); + return FINAL_CHOICE; + } + + return new BaseListPopupStep(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.selectDebugger.title"), + selectedValue.getSubItems()) { + @Override + public boolean isSpeedSearchEnabled() { + return true; + } + + @NotNull + @Override + public String getTextFor(AttachItem value) { + return value.getSelectedDebugger().getDebuggerDisplayName(); + } + + @Override + public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { + selectedValue.startDebugSession(myProject); + return FINAL_CHOICE; + } + }; + } + + @Override + public PopupStep onChosen(AttachItem selectedValue, + boolean finalChoice, + @MagicConstant(flagsFromClass = InputEvent.class) int eventModifiers) { + return onChosen(selectedValue, finalChoice); + } } } From 296c380a7392f27b9827ea477b12a3019450a7b6 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 26 Dec 2015 14:00:00 +0100 Subject: [PATCH 008/825] IDEA-149798 Extensible Attach to Local Process action: show ad text with currently selected debugger --- .../src/messages/XDebuggerBundle.properties | 1 + .../actions/AttachToLocalProcessAction.java | 44 +++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 33b31b1530bc..7a146d4b6d14 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -11,6 +11,7 @@ xdebugger.debugger.tab.title=Debugger xdebugger.attach.toLocal.popup.title=Attach xdebugger.attach.toLocal.popup.emptyText=No process to attach to +xdebugger.attach.toLocal.popup.adText=Attach with {0} xdebugger.attach.toLocal.popup.selectDebugger.title=Select Debugger xdebugger.attach.toLocal.action=Attach to Local Process... xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 6c9b133b989e..233c0d457806 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -24,10 +24,12 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.ui.popup.ListPopupStepEx; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.StatusText; @@ -39,6 +41,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import java.awt.event.InputEvent; import java.util.ArrayList; import java.util.Collections; @@ -65,7 +69,35 @@ public class AttachToLocalProcessAction extends AnAction { if (project == null) return; MyPopupStep step = new MyPopupStep(collectAttachItems(project), project); - JBPopupFactory.getInstance().createListPopup(step).showCenteredInCurrentWindow(project); + + final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step); + final JList mainList = ((ListPopupImpl)popup).getList(); + + ListSelectionListener listener = new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent event) { + if (event.getValueIsAdjusting()) return; + + Object item = ((JList)event.getSource()).getSelectedValue(); + + // if a sub-list is closed, fallback to the selected value from the main list + if (item == null) { + item = mainList.getSelectedValue(); + } + + if (item instanceof AttachItem) { + popup.setAdText(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.adText", + ((AttachItem)item).getSelectedDebugger().getDebuggerDisplayName()), + SwingConstants.LEADING); + } + } + }; + popup.addListSelectionListener(listener); + + // force first valueChanged event + listener.valueChanged(new ListSelectionEvent(mainList, mainList.getMinSelectionIndex(), mainList.getMaxSelectionIndex(), false)); + + popup.showCenteredInCurrentWindow(project); } @NotNull @@ -133,9 +165,9 @@ public class AttachToLocalProcessAction extends AnAction { } private static class MyPopupStep extends BaseListPopupStep implements ListPopupStepEx { - private final Project myProject; + @NotNull private final Project myProject; - public MyPopupStep(List items, Project project) { + public MyPopupStep(@NotNull List items, @NotNull Project project) { super(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items); myProject = project; } @@ -145,6 +177,11 @@ public class AttachToLocalProcessAction extends AnAction { return true; } + @Override + public boolean isAutoSelectionEnabled() { + return false; + } + @NotNull @Override public String getTextFor(AttachItem value) { @@ -167,6 +204,7 @@ public class AttachToLocalProcessAction extends AnAction { emptyText.setText(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.emptyText")); } + @Override public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { if (finalChoice) { From 0441da00fccb550faae280b4abdea8a5c77f67c1 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 26 Dec 2015 16:21:22 +0100 Subject: [PATCH 009/825] IDEA-149798 Extensible Attach to Local Process action: allow caching calculation result + better executable name --- .../execution/process/ProcessInfo.java | 9 ++++-- .../execution/process/ProcessInfoTest.java | 28 +++++++++++++++++++ .../openapi/util/text/StringUtil.java | 9 +++++- .../attach/XLocalAttachDebuggerProvider.java | 14 +++++++++- .../actions/AttachToLocalProcessAction.java | 6 ++-- 5 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index 13f627637b48..f337829f33a0 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -15,7 +15,7 @@ */ package com.intellij.execution.process; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; @@ -57,7 +57,12 @@ public class ProcessInfo { @NotNull public String getExecutableName() { - return FileUtil.getNameWithoutExtension(PathUtil.getFileName(myExecutable)); + return PathUtil.getFileName(myExecutable); + } + + @NotNull + public String getExecutableDisplayName() { + return StringUtil.trimEnd(getExecutableName(), ".exe", true); } @NotNull diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java new file mode 100644 index 000000000000..32f2147a01fb --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.execution.process; + +import com.intellij.testFramework.UsefulTestCase; + +public class ProcessInfoTest extends UsefulTestCase { + public void testExecutableName() throws Exception { + assertEquals("foo", new ProcessInfo(1, "foo", "bar").getExecutableDisplayName()); + assertEquals("foo", new ProcessInfo(1, "foo.exe", "bar").getExecutableDisplayName()); + assertEquals("foo", new ProcessInfo(1, "foo.EXE", "bar").getExecutableDisplayName()); + assertEquals("foo.bar", new ProcessInfo(1, "foo.bar", "bar").getExecutableDisplayName()); + assertEquals("foo.1.2", new ProcessInfo(1, "foo.1.2", "bar").getExecutableDisplayName()); + } +} \ No newline at end of file diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 04834ccdfd52..ff70bc4d50d6 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1004,7 +1004,14 @@ public class StringUtil extends StringUtilRt { @NotNull @Contract(pure = true) public static String trimEnd(@NotNull String s, @NonNls @NotNull String suffix) { - if (s.endsWith(suffix)) { + return trimEnd(s, suffix, false); + } + + @NotNull + @Contract(pure = true) + public static String trimEnd(@NotNull String s, @NonNls @NotNull String suffix, boolean ignoreCase) { + boolean endsWith = ignoreCase ? endsWithIgnoreCase(s, suffix) : s.endsWith(suffix); + if (endsWith) { return s.substring(0, s.length() - suffix.length()); } return s; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java index dd5700db181a..63cae7c3a2a9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java @@ -18,6 +18,7 @@ package com.intellij.xdebugger.attach; import com.intellij.execution.process.ProcessInfo; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.UserDataHolder; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -25,6 +26,17 @@ import java.util.List; public interface XLocalAttachDebuggerProvider { ExtensionPointName EP = ExtensionPointName.create("com.intellij.xdebugger.localAttachDebuggerProvider"); + /** + * Attach to Local Process action invokes {@link #getAvailableDebuggers} method for every running process. + * {@link XLocalAttachDebuggerProvider} should return a list of the debuggers that can attach and debug a given process. + * + * If there are several debuggers that can attach to a process, the user will have a choice between them. + * + * @param contextHolder use this data holder if you need to store temporary data during debuggers collection. + * Lifetime of the data is restricted by a single Attach to Local Process action invocation. + */ @NotNull - List getAvailableDebuggers(@NotNull Project project, @NotNull ProcessInfo processInfo); + List getAvailableDebuggers(@NotNull Project project, + @NotNull ProcessInfo processInfo, + @NotNull UserDataHolder contextHolder); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 233c0d457806..999126591801 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -28,6 +28,7 @@ import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.ui.popup.ListPopupStepEx; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Function; @@ -104,10 +105,11 @@ public class AttachToLocalProcessAction extends AnAction { private static List collectAttachItems(@NotNull Project project) { List result = new ArrayList(); + UserDataHolderBase dataHolder = new UserDataHolderBase(); for (ProcessInfo eachInfo : ProcessUtils.getProcessList()) { List availableDebuggers = new ArrayList(); for (XLocalAttachDebuggerProvider eachProvider : Extensions.getExtensions(XLocalAttachDebuggerProvider.EP)) { - availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo)); + availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo, dataHolder)); } if (!availableDebuggers.isEmpty()) { result.add(new AttachItem(eachInfo, availableDebuggers)); @@ -185,7 +187,7 @@ public class AttachToLocalProcessAction extends AnAction { @NotNull @Override public String getTextFor(AttachItem value) { - return value.myProcessInfo.getPid() + " " + value.myProcessInfo.getExecutableName(); + return value.myProcessInfo.getPid() + " " + value.myProcessInfo.getExecutableDisplayName(); } @Override From 32f76dc793c58d6c8af9ae484918f110fe1c4e44 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 26 Dec 2015 16:29:26 +0100 Subject: [PATCH 010/825] IDEA-149825 Reuse platform 'Attach to Local Process' action in PyCharm --- python/src/META-INF/python-core.xml | 8 +- .../attach/PyAttachToProcessAction.java | 96 ------------------- .../attach/PyAttachToProcessDebugRunner.java | 10 +- .../attach/PyLocalAttachDebuggerProvider.java | 92 ++++++++++++++++++ 4 files changed, 97 insertions(+), 109 deletions(-) delete mode 100644 python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java create mode 100644 python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml index 58c6d91fa154..b24fafad04a2 100644 --- a/python/src/META-INF/python-core.xml +++ b/python/src/META-INF/python-core.xml @@ -137,6 +137,7 @@ + @@ -782,13 +783,6 @@ - - - - - diff --git a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java deleted file mode 100644 index 5bd3957fa853..000000000000 --- a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessAction.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jetbrains.python.debugger.attach; - -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.Lists; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.process.ProcessUtils; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.SelectFromListDialog; -import com.intellij.openapi.util.text.StringUtil; -import com.jetbrains.python.sdk.PythonSdkType; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -/** - * @author traff - */ -public class PyAttachToProcessAction extends AnAction { - - public PyAttachToProcessAction() { - super("Attach debugger to process"); - } - - @Override - public void update(AnActionEvent e) { - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - Module module = e.getData(LangDataKeys.MODULE); - - e.getPresentation().setEnabled(true); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - Module module = e.getData(LangDataKeys.MODULE); - - Sdk sdk = PythonSdkType.findLocalCPython(module); - - final SelectFromListDialog selectDialog = - new SelectFromListDialog(project, pythonProcessesList(), new SelectFromListDialog.ToStringAspect() { - public String getToStirng(Object obj) { - ProcessInfo info = (ProcessInfo)obj; - - return info.getPid() + " " + info.getCommandLine(); - } - }, "Select Python Process", ListSelectionModel.SINGLE_SELECTION); - if (selectDialog.showAndGet()) { - ProcessInfo process = (ProcessInfo)selectDialog.getSelection()[0]; - - PyAttachToProcessDebugRunner runner = - new PyAttachToProcessDebugRunner(project, process.getPid(), sdk.getHomePath()); - - try { - runner.launch(); - } - catch (ExecutionException e1) { - Messages.showErrorDialog(project, e1.getMessage(), "Error Attaching Debugger"); - } - ; - } - } - - private static ProcessInfo[] pythonProcessesList() { - ProcessInfo[] list = ProcessUtils.getProcessList(); - return FluentIterable.from(Lists.newArrayList(list)).filter(new Predicate() { - @Override - public boolean apply(ProcessInfo input) { - return StringUtil.containsIgnoreCase(input.getExecutableName(), "python"); - } - }).toArray(ProcessInfo.class); - } -} diff --git a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessDebugRunner.java b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessDebugRunner.java index afd16ca532d2..6e6c321e9005 100644 --- a/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessDebugRunner.java +++ b/python/src/com/jetbrains/python/debugger/attach/PyAttachToProcessDebugRunner.java @@ -46,13 +46,13 @@ public class PyAttachToProcessDebugRunner extends PyDebugRunner { mySdkPath = sdkPath; } - public void launch() throws ExecutionException { + public XDebugSession launch() throws ExecutionException { FileDocumentManager.getInstance().saveAllDocuments(); - int port = launchRemoteDebugServer(); + return launchRemoteDebugServer(); } - private int launchRemoteDebugServer() throws ExecutionException { + private XDebugSession launchRemoteDebugServer() throws ExecutionException { final ServerSocket serverSocket; try { //noinspection SocketOpenedButNotSafelyClosed @@ -68,7 +68,7 @@ public class PyAttachToProcessDebugRunner extends PyDebugRunner { final ExecutionResult result = state.execute(state.getEnvironment().getExecutor(), this); //start remote debug server - final XDebugSession session = XDebuggerManager.getInstance(myProject). + return XDebuggerManager.getInstance(myProject). startSessionAndShowTab(String.valueOf(myPid), null, new XDebugProcessStarter() { @org.jetbrains.annotations.NotNull public XDebugProcess start(@NotNull final XDebugSession session) { @@ -97,7 +97,5 @@ public class PyAttachToProcessDebugRunner extends PyDebugRunner { return pyDebugProcess; } }); - - return serverSocket.getLocalPort(); } } diff --git a/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java new file mode 100644 index 000000000000..6b022927dd73 --- /dev/null +++ b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java @@ -0,0 +1,92 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.debugger.attach; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.attach.XLocalAttachDebugger; +import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import com.jetbrains.python.sdk.PythonSdkType; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class PyLocalAttachDebuggerProvider implements XLocalAttachDebuggerProvider { + private static final Key> DEBUGGERS_KEY = Key.create("PyLocalAttachDebuggerProvider.DEBUGGERS"); + + @NotNull + @Override + public List getAvailableDebuggers(@NotNull Project project, + @NotNull ProcessInfo processInfo, + @NotNull UserDataHolder contextHolder) { + if (StringUtil.containsIgnoreCase(processInfo.getExecutableName(), "python")) { + List result = contextHolder.getUserData(DEBUGGERS_KEY); + if (result != null) return result; + + result = ContainerUtil.map(PythonSdkType.getAllSdks(), new Function() { + @Override + public XLocalAttachDebugger fun(Sdk sdk) { + return new PyLocalAttachDebugger(sdk); + } + }); + + // most recent python version goes first + Collections.sort(result, new Comparator() { + @Override + public int compare(XLocalAttachDebugger a, XLocalAttachDebugger b) { + return -a.getDebuggerDisplayName().compareToIgnoreCase(b.getDebuggerDisplayName()); + } + }); + + contextHolder.putUserData(DEBUGGERS_KEY, Collections.unmodifiableList(result)); + return result; + } + return Collections.emptyList(); + } + + private static class PyLocalAttachDebugger implements XLocalAttachDebugger { + @NotNull private final Sdk mySdk; + @NotNull private final String myName; + + public PyLocalAttachDebugger(@NotNull Sdk sdk) { + mySdk = sdk; + myName = PythonSdkType.getInstance().getVersionString(mySdk) + " Debugger"; + } + + @NotNull + @Override + public String getDebuggerDisplayName() { + return myName; + } + + @NotNull + @Override + public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException { + PyAttachToProcessDebugRunner runner = new PyAttachToProcessDebugRunner(project, processInfo.getPid(), mySdk.getHomePath()); + return runner.launch(); + } + } +} From a89b0b442f0cc420e354e5991846eb8d3a4e6ed0 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 30 Dec 2015 15:23:16 +0100 Subject: [PATCH 011/825] CPP-1001 Attach to existing local process: unnecessary API class replaced with an existing one --- .../com/intellij/util/ThrowableFunction.java | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 platform/util-rt/src/com/intellij/util/ThrowableFunction.java diff --git a/platform/util-rt/src/com/intellij/util/ThrowableFunction.java b/platform/util-rt/src/com/intellij/util/ThrowableFunction.java deleted file mode 100644 index 7e5d14741b34..000000000000 --- a/platform/util-rt/src/com/intellij/util/ThrowableFunction.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.util; - -public interface ThrowableFunction { - Result fun(Param param) throws E; -} From 40fa35231d2911fcfddc7ceb70943887caf4b463 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 14:56:48 +0100 Subject: [PATCH 012/825] IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths: Linux + OS X --- .../execution/process/IProcessList.java | 35 ---- .../execution/process/ProcessInfo.java | 80 ++++++++- .../execution/process/ProcessListLinux.java | 166 +++++++++++------- .../execution/process/ProcessListMac.java | 74 -------- .../execution/process/ProcessListWin32.java | 7 +- .../process/ProcessListWin32Internal.java | 5 +- .../execution/process/ProcessUtils.java | 60 +------ .../execution/process/ProcessUtilsTest.java | 126 +++++++++++++ 8 files changed, 308 insertions(+), 245 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/IProcessList.java delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/ProcessListMac.java create mode 100644 platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java diff --git a/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java b/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java deleted file mode 100644 index 07d57512d11e..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/IProcessList.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 (c) 2000, 2010 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ -package com.intellij.execution.process; - -/** - * @noextend This interface is not intended to be extended by clients. - * @noimplement This interface is not intended to be implemented by clients. - */ -interface IProcessList { - ProcessInfo[] getProcessList(); -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index f337829f33a0..056582711d8c 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -18,16 +18,18 @@ package com.intellij.execution.process; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + -/** - * @author traff - */ public class ProcessInfo { public static ProcessInfo[] EMPTY_ARRAY = new ProcessInfo[0]; private final int myPid; @NotNull private final String myExecutable; + @NotNull private final String myArgs; @NotNull private final String myCommandLine; + @Nullable private final String myUser; + @Nullable private final String myState; public ProcessInfo(@NotNull String pidString, @NotNull String commandLine) { this(Integer.parseInt(pidString), commandLine); @@ -35,15 +37,32 @@ public class ProcessInfo { public ProcessInfo(int pid, @NotNull String commandLine) { myPid = pid; - String[] args = commandLine.split(" "); - myExecutable = args.length > 0 ? args[0] : ""; + int space = commandLine.indexOf(" "); + if (space > 0) { + myExecutable = commandLine.substring(0, space); + myArgs = commandLine.substring(space + 1); + } + else { + myExecutable = commandLine; + myArgs = ""; + } + myCommandLine = commandLine; + myUser = null; + myState = null; } - public ProcessInfo(int pid, @NotNull String executables, @NotNull String args) { + public ProcessInfo(int pid, @NotNull String executable, @NotNull String args) { + this(pid, executable, args, null, null); + } + + public ProcessInfo(int pid, @NotNull String executable, @NotNull String args, @Nullable String user, @Nullable String state) { myPid = pid; - myExecutable = executables; - myCommandLine = executables + " " + args; + myExecutable = executable; + myArgs = args; + myCommandLine = executable + (args.isEmpty() ? "" : (" " + args)); + myState = state; + myUser = user; } public int getPid() { @@ -65,13 +84,56 @@ public class ProcessInfo { return StringUtil.trimEnd(getExecutableName(), ".exe", true); } + @NotNull + public String getArgs() { + return myArgs; + } + @NotNull public String getCommandLine() { return myCommandLine; } + @Nullable + public String getUser() { + return myUser; + } + + @Nullable + public String getState() { + return myState; + } + @Override public String toString() { - return String.valueOf(myPid) + " (" + myCommandLine + ")"; + return myPid + " '" + myExecutable + "' '" + myArgs + "' '" + myUser + "' '" + myState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ProcessInfo info = (ProcessInfo)o; + + if (myPid != info.myPid) return false; + if (!myExecutable.equals(info.myExecutable)) return false; + if (!myArgs.equals(info.myArgs)) return false; + if (!myCommandLine.equals(info.myCommandLine)) return false; + if (myUser != null ? !myUser.equals(info.myUser) : info.myUser != null) return false; + if (myState != null ? !myState.equals(info.myState) : info.myState != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myPid; + result = 31 * result + myExecutable.hashCode(); + result = 31 * result + myArgs.hashCode(); + result = 31 * result + myCommandLine.hashCode(); + result = 31 * result + (myUser != null ? myUser.hashCode() : 0); + result = 31 * result + (myState != null ? myState.hashCode() : 0); + return result; } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java index 3d9268ad4ee1..70370831584a 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -14,82 +14,116 @@ * limitations under the License. */ -/******************************************************************************* - * Copyright (c) 2000, 2010 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ package com.intellij.execution.process; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.util.ExecUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; +import java.util.List; -/** - * Use through ProcessUtils. - */ -class ProcessListLinux implements IProcessList { - - ProcessInfo[] empty = new ProcessInfo[0]; - - public ProcessListLinux() { +class ProcessListLinux { + @NotNull + public static ProcessInfo[] getProcessList(boolean isMac) { + String output; + try { + output = ExecUtil.execAndGetOutput(new GeneralCommandLine("/bin/ps", "-a", "-x", "-o", "pid,state,user,command")).getStdout(); + } + catch (ExecutionException ignore) { + return ProcessInfo.EMPTY_ARRAY; + } + return parseOutput(isMac, output); } - /** - * Insert the method's description here. - * - * @see IProcessList#getProcessList - */ - public ProcessInfo[] getProcessList() { - File proc = new File("/proc"); //$NON-NLS-1$ - File[] pidFiles = null; + @NotNull + public static ProcessInfo[] parseOutput(boolean isMac, @NotNull String output) { + List result = ContainerUtil.newArrayList(); + String[] lines = StringUtil.splitByLinesDontTrim(output); + if (lines.length < 2) return ProcessInfo.EMPTY_ARRAY; - // We are only interested in the pid so filter the rest out. - try { - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - boolean isPID = false; - try { - Integer.parseInt(name); - isPID = true; - } - catch (NumberFormatException e) { - } - return isPID; - } - }; - pidFiles = proc.listFiles(filter); - } - catch (SecurityException e) { - } + String header = lines[0]; + if (header != null) { + int pidStart = header.indexOf("PID"); + if (pidStart == -1) return ProcessInfo.EMPTY_ARRAY; - ProcessInfo[] processInfo = empty; - if (pidFiles != null) { - processInfo = new ProcessInfo[pidFiles.length]; - for (int i = 0; i < pidFiles.length; i++) { - File cmdLine = new File(pidFiles[i], "cmdline"); //$NON-NLS-1$ - String name; - try { - name = new String(ProcessUtils.loadFileText(cmdLine, null)).replace('\0', ' '); - } - catch (IOException e) { - name = ""; - } - if (name.length() == 0) { - name = "Unknown"; //$NON-NLS-1$ - } - processInfo[i] = new ProcessInfo(pidFiles[i].getName(), name); + int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); + if (statStart == -1) return ProcessInfo.EMPTY_ARRAY; + + int userStart = header.indexOf("USER", statStart); + if (userStart == -1) return ProcessInfo.EMPTY_ARRAY; + + int commandStart = header.indexOf("COMMAND", userStart); + if (commandStart == -1) return ProcessInfo.EMPTY_ARRAY; + + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; + + int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1); + if (pid == -1) continue; + + String state = line.substring(statStart, userStart).trim(); + if (state.contains("Z")) continue; // zombie + + String user = line.substring(userStart, commandStart).trim(); + String commandLine = line.substring(commandStart).trim(); + + String executablePath = determineExecutable(commandLine); + if (executablePath == null) continue; + + String args = commandLine.substring(executablePath.length()).trim(); + result.add(new ProcessInfo(pid, executablePath, args, user, state)); } } - else { - pidFiles = new File[0]; + + return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); + } + + + @Nullable + private static String determineExecutable(String commandLine) { + // Since there is no way on Linux to get the path to the executable, we have to heuristically determine it + // by finding the longest existing file path from the beginning of the command line. + // There is a possibility to find the wrong path in ambiguous cases like the following: + // * "/path/to/executable with spaces" - file name with spaces + // * "/path/to/executable" "with spaces" - file name + arguments + // Though probability of such a situation is negligible + + String executablePath = commandLine; + + found: + while (!new File(executablePath).exists()) { + int separator = executablePath.lastIndexOf("/"); + if (separator == -1) return null; + + String parentPath = executablePath.substring(0, separator); + + if (new File(parentPath).exists()) { + String name = executablePath.substring(separator + 1); + int space = name.lastIndexOf(" "); + + while (true) { + String namePart = name.substring(0, space == -1 ? name.length() : space); + if (new File(parentPath, namePart).exists()) { + executablePath = parentPath + "/" + namePart; + break found; + } + + if (space == -1) break; + space = name.lastIndexOf(" ", space - 1); + } + } + separator = parentPath.lastIndexOf(" "); + if (separator == -1) return null; + executablePath = parentPath.substring(0, separator); } - return processInfo; + + assert commandLine.startsWith(executablePath) : "Executable incorrectly found: " + executablePath + " in: " + commandLine; + return executablePath; } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListMac.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListMac.java deleted file mode 100644 index e79972535084..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListMac.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.execution.process; - -import com.intellij.util.containers.ContainerUtil; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.List; - -/** - * Use through ProcessUtils. - */ -class ProcessListMac implements IProcessList { - public ProcessListMac() { } - - @Override - public ProcessInfo[] getProcessList() { - Process ps; - try { - String[] command = {"/bin/ps", "-a", "-x", "-o", "pid,command"}; - ps = ProcessUtils.createProcess(command, null, null); - } - catch (Exception e) { - return ProcessInfo.EMPTY_ARRAY; - } - - //Read the output and parse it into an array list - List procInfo = ContainerUtil.newArrayList(); - - try { - BufferedReader psOutput = new BufferedReader(new InputStreamReader(ps.getInputStream())); - try { - String line; - while ((line = psOutput.readLine()) != null) { - //The format of the output should be - //PID space name - line = line.trim(); - int index = line.indexOf(' '); - if (index != -1) { - String pidString = line.substring(0, index).trim(); - try { - int pid = Integer.parseInt(pidString); - String arg = line.substring(index + 1); - procInfo.add(new ProcessInfo(pid, arg)); - } - catch (NumberFormatException ignored) { } - } - } - } - finally { - psOutput.close(); - } - } - catch (Exception ignored) { } - - ps.destroy(); - - return procInfo.isEmpty() ? ProcessInfo.EMPTY_ARRAY : procInfo.toArray(new ProcessInfo[procInfo.size()]); - } -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java index cf24db61078a..200f6bf21e23 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java @@ -30,11 +30,10 @@ import java.util.List; * * Use through ProcessUtils. */ -class ProcessListWin32 implements IProcessList { +class ProcessListWin32 { private static final Logger LOG = Logger.getInstance(ProcessListWin32.class); - @Override - public ProcessInfo[] getProcessList() { + public static ProcessInfo[] getProcessList() { try { return createFromWMIC(); } @@ -50,7 +49,7 @@ class ProcessListWin32 implements IProcessList { } catch (Exception e) { //Use fallback - return new ProcessListWin32Internal().getProcessList(); + return ProcessListWin32Internal.getProcessList(); } try { return parseListTasks(p.getInputStream()); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java index 3ed247016c43..bde2bda64a5a 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java @@ -27,11 +27,10 @@ import java.util.List; * * Use through ProcessUtils. */ -class ProcessListWin32Internal implements IProcessList { +class ProcessListWin32Internal { private static final Logger LOG = Logger.getInstance(ProcessListWin32Internal.class); - @Override - public ProcessInfo[] getProcessList() { + public static ProcessInfo[] getProcessList() { String[] dirs = { PathManager.getBinPath(), PathManager.getHomePath() + "/community/bin/win", diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java index a96be96e96a7..3c918e685e08 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java @@ -30,9 +30,9 @@ package com.intellij.execution.process; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; public class ProcessUtils { @@ -64,61 +64,13 @@ public class ProcessUtils { @NotNull public static ProcessInfo[] getProcessList() { - return getProcessListImpl().getProcessList(); - } - - @NotNull - private static IProcessList getProcessListImpl() { if (SystemInfo.isWindows) { - return new ProcessListWin32(); + return ProcessListWin32.getProcessList(); } - if (SystemInfo.isLinux) { - return new ProcessListLinux(); + if (SystemInfo.isLinux || SystemInfo.isMac) { + return ProcessListLinux.getProcessList(SystemInfo.isMac); } - if (SystemInfo.isMac) { - return new ProcessListMac(); - } - LOG.error("Unexpected platform. Unable to list processes."); - return new IProcessList() { - - @Override - public ProcessInfo[] getProcessList() { - return new ProcessInfo[0]; - } - }; - } - - @NotNull - public static char[] loadFileText(@NotNull File file, @Nullable String encoding) throws IOException { - InputStream stream = new FileInputStream(file); - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - Reader reader = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding); - try { - return loadText(reader); - } - finally { - reader.close(); - } - } - - @NotNull - public static char[] loadText(@NotNull Reader reader) throws IOException { - //fill a buffer with the contents - int BUFFER_SIZE = 2 * 1024; - - char[] readBuffer = new char[BUFFER_SIZE]; - int n = reader.read(readBuffer); - - int DEFAULT_FILE_SIZE = 8 * BUFFER_SIZE; - - StringBuffer buffer = new StringBuffer(DEFAULT_FILE_SIZE); - - while (n > 0) { - buffer.append(readBuffer, 0, n); - n = reader.read(readBuffer); - } - - return buffer.toString().toCharArray(); + return new ProcessInfo[0]; } } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java new file mode 100644 index 000000000000..6235e72bd972 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java @@ -0,0 +1,126 @@ +/* + * 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. + */ +package com.intellij.execution.process; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.IoTestUtil; +import com.intellij.testFramework.UsefulTestCase; + +import java.io.File; +import java.util.Arrays; + +public class ProcessUtilsTest extends UsefulTestCase { + private File myDir; + + @Override + public void setUp() throws Exception { + super.setUp(); + myDir = IoTestUtil.createTestDir("test"); + new File(myDir, "dir/file").mkdirs(); + new File(myDir, "dir/dir/file").mkdirs(); + new File(myDir, "dir/dir/file with spaces").mkdirs(); + } + + @Override + public void tearDown() throws Exception { + FileUtil.delete(myDir); + super.tearDown(); + } + + public void testProcessList_WorksOnAllPlatforms() throws Exception { + assertNotEmpty(Arrays.asList(ProcessUtils.getProcessList())); + } + + public void testProcessListOnLinux_DetermineExecutable() throws Exception { + ProcessInfo[] infos = ProcessListLinux.parseOutput( + false, + " PID S USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + + " 2 S user " + myDir + "/dir/dir/file\n" + + " 3 S user " + myDir + "/dir/dir/file param param\n" + + " 4 S user " + myDir + "/dir/dir/file with\n" + + " 5 S user " + myDir + "/dir/dir/file with spaces\n" + + " 6 S user " + myDir + "/dir/dir/file with spaces param param\n" + + " 7 S user " + myDir + "/dir/dir/file with spaces/foo\n" + + " 8 S user " + myDir + "/dir/dir/file/\n" + + " 9 S user " + myDir + "/dir/dir/file with spaces/\n" + + " 10 S user " + myDir + "/dir/dir\n" + + " 11 S user " + myDir + "/dir/dir/file/unknown\n" + + " 12 S user " + myDir + "/dir/dir/unknown\n" + + " 13 S user " + myDir + "/dir/dir/file_unknown\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), + new ProcessInfo(2, myDir + "/dir/dir/file", "", "user", "S"), + new ProcessInfo(3, myDir + "/dir/dir/file", "param param", "user", "S"), + new ProcessInfo(4, myDir + "/dir/dir/file", "with", "user", "S"), + new ProcessInfo(5, myDir + "/dir/dir/file with spaces", "", "user", "S"), + new ProcessInfo(6, myDir + "/dir/dir/file with spaces", "param param", "user", "S"), + new ProcessInfo(7, myDir + "/dir/dir/file", "with spaces/foo", "user", "S"), + new ProcessInfo(8, myDir + "/dir/dir/file/", "", "user", "S"), + new ProcessInfo(9, myDir + "/dir/dir/file with spaces/", "", "user", "S"), + new ProcessInfo(10, myDir + "/dir/dir", "", "user", "S")); + } + + public void testProcessListOnLinux_DetermineExecutableWithExtraSlashes() throws Exception { + ProcessInfo[] infos = ProcessListLinux.parseOutput( + false, + " PID S USER COMMAND\n\n" + + " 1 S user //" + myDir + "//dir//file//\n" + + " 2 S user //" + myDir + "//dir//file// aaa bbb\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, "//" + myDir + "//dir//file//", "", "user", "S"), + new ProcessInfo(2, "//" + myDir + "//dir//file//", "aaa bbb", "user", "S")); + } + + public void testProcessListOnMac() throws Exception { + ProcessInfo[] infos = ProcessListLinux.parseOutput( + true, + " PID STAT USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + + " 2 S user " + myDir + "/dir/dir/file\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), + new ProcessInfo(2, myDir + "/dir/dir/file", "", "user", "S")); + } + + public void testProcessListOnMac_DoNotIncludeZombies() throws Exception { + ProcessInfo[] infos = ProcessListLinux.parseOutput( + true, + " PID STAT USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + + " 2 Z user " + myDir + "/dir/file\n" + + " 3 SZ user " + myDir + "/dir/file\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, myDir + "/dir/file", "", "user", "S")); + } + + public void testProcessListOnLinuxMac_VariousFormsPidStatUser() throws Exception { + ProcessInfo[] infos = ProcessListLinux.parseOutput( + true, + " PID STAT USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + + " 101 Ss user_name " + myDir + "/dir/file\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), + new ProcessInfo(101, myDir + "/dir/file", "", "user_name", "Ss")); + } + +} \ No newline at end of file From 95e9cd9064b4022ce3cd62e5dd4a37ac50981602 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 17:49:25 +0100 Subject: [PATCH 013/825] IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths: Windows --- bin/win/listtasks.exe | Bin 102400 -> 0 bytes .../execution/process/ProcessInfo.java | 49 +---- .../execution/process/ProcessListLinux.java | 44 ++--- .../execution/process/ProcessListWin32.java | 187 +++++++++--------- .../process/ProcessListWin32Internal.java | 92 --------- .../execution/process/ProcessUtils.java | 28 --- .../execution/process/ProcessUtilsTest.java | 115 +++++++++++ 7 files changed, 237 insertions(+), 278 deletions(-) delete mode 100644 bin/win/listtasks.exe delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java diff --git a/bin/win/listtasks.exe b/bin/win/listtasks.exe deleted file mode 100644 index a31d3b20967f7739a92b80918d7da86d071c9b89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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

6#N0cM(#AUl97PSaysJ`} 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 0) { - myExecutable = commandLine.substring(0, space); - myArgs = commandLine.substring(space + 1); - } - else { - myExecutable = commandLine; - myArgs = ""; - } - - myCommandLine = commandLine; - myUser = null; - myState = null; + public ProcessInfo(int pid, @NotNull String executable) { + this(pid, executable, ""); } public ProcessInfo(int pid, @NotNull String executable, @NotNull String args) { @@ -58,9 +40,8 @@ public class ProcessInfo { public ProcessInfo(int pid, @NotNull String executable, @NotNull String args, @Nullable String user, @Nullable String state) { myPid = pid; - myExecutable = executable; + myExecutableName = PathUtil.getFileName(executable); myArgs = args; - myCommandLine = executable + (args.isEmpty() ? "" : (" " + args)); myState = state; myUser = user; } @@ -69,19 +50,14 @@ public class ProcessInfo { return myPid; } - @NotNull - public String getExecutable() { - return myExecutable; - } - @NotNull public String getExecutableName() { - return PathUtil.getFileName(myExecutable); + return myExecutableName; } @NotNull public String getExecutableDisplayName() { - return StringUtil.trimEnd(getExecutableName(), ".exe", true); + return StringUtil.trimEnd(myExecutableName, ".exe", true); } @NotNull @@ -89,11 +65,6 @@ public class ProcessInfo { return myArgs; } - @NotNull - public String getCommandLine() { - return myCommandLine; - } - @Nullable public String getUser() { return myUser; @@ -106,7 +77,7 @@ public class ProcessInfo { @Override public String toString() { - return myPid + " '" + myExecutable + "' '" + myArgs + "' '" + myUser + "' '" + myState; + return myPid + " '" + myExecutableName + "' '" + myArgs + "' '" + myUser + "' '" + myState; } @Override @@ -117,9 +88,8 @@ public class ProcessInfo { ProcessInfo info = (ProcessInfo)o; if (myPid != info.myPid) return false; - if (!myExecutable.equals(info.myExecutable)) return false; + if (!myExecutableName.equals(info.myExecutableName)) return false; if (!myArgs.equals(info.myArgs)) return false; - if (!myCommandLine.equals(info.myCommandLine)) return false; if (myUser != null ? !myUser.equals(info.myUser) : info.myUser != null) return false; if (myState != null ? !myState.equals(info.myState) : info.myState != null) return false; @@ -129,9 +99,8 @@ public class ProcessInfo { @Override public int hashCode() { int result = myPid; - result = 31 * result + myExecutable.hashCode(); + result = 31 * result + myExecutableName.hashCode(); result = 31 * result + myArgs.hashCode(); - result = 31 * result + myCommandLine.hashCode(); result = 31 * result + (myUser != null ? myUser.hashCode() : 0); result = 31 * result + (myState != null ? myState.hashCode() : 0); return result; diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java index 70370831584a..40deb0a42d56 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java @@ -42,43 +42,41 @@ class ProcessListLinux { } @NotNull - public static ProcessInfo[] parseOutput(boolean isMac, @NotNull String output) { + static ProcessInfo[] parseOutput(boolean isMac, @NotNull String output) { List result = ContainerUtil.newArrayList(); String[] lines = StringUtil.splitByLinesDontTrim(output); if (lines.length < 2) return ProcessInfo.EMPTY_ARRAY; String header = lines[0]; - if (header != null) { - int pidStart = header.indexOf("PID"); - if (pidStart == -1) return ProcessInfo.EMPTY_ARRAY; + int pidStart = header.indexOf("PID"); + if (pidStart == -1) return ProcessInfo.EMPTY_ARRAY; - int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); - if (statStart == -1) return ProcessInfo.EMPTY_ARRAY; + int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); + if (statStart == -1) return ProcessInfo.EMPTY_ARRAY; - int userStart = header.indexOf("USER", statStart); - if (userStart == -1) return ProcessInfo.EMPTY_ARRAY; + int userStart = header.indexOf("USER", statStart); + if (userStart == -1) return ProcessInfo.EMPTY_ARRAY; - int commandStart = header.indexOf("COMMAND", userStart); - if (commandStart == -1) return ProcessInfo.EMPTY_ARRAY; + int commandStart = header.indexOf("COMMAND", userStart); + if (commandStart == -1) return ProcessInfo.EMPTY_ARRAY; - for (int i = 1; i < lines.length; i++) { - String line = lines[i]; + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; - int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1); - if (pid == -1) continue; + int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1); + if (pid == -1) continue; - String state = line.substring(statStart, userStart).trim(); - if (state.contains("Z")) continue; // zombie + String state = line.substring(statStart, userStart).trim(); + if (state.contains("Z")) continue; // zombie - String user = line.substring(userStart, commandStart).trim(); - String commandLine = line.substring(commandStart).trim(); + String user = line.substring(userStart, commandStart).trim(); + String commandLine = line.substring(commandStart).trim(); - String executablePath = determineExecutable(commandLine); - if (executablePath == null) continue; + String executablePath = determineExecutable(commandLine); + if (executablePath == null) continue; - String args = commandLine.substring(executablePath.length()).trim(); - result.add(new ProcessInfo(pid, executablePath, args, user, state)); - } + String args = commandLine.substring(executablePath.length()).trim(); + result.add(new ProcessInfo(pid, executablePath, args, user, state)); } return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java index 200f6bf21e23..f2e46686271a 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java @@ -15,125 +15,122 @@ */ package com.intellij.execution.process; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.util.ExecUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; +import java.io.StringReader; import java.util.List; -/** - * This implementation uses the tasklist.exe from windows (must be on the path). - * - * Use through ProcessUtils. - */ class ProcessListWin32 { - private static final Logger LOG = Logger.getInstance(ProcessListWin32.class); - + @NotNull public static ProcessInfo[] getProcessList() { - try { - return createFromWMIC(); - } - catch (Exception e) { - //Keep on going for other alternatives - } + ProcessInfo[] result; - try { - Process p; - try { - String[] command = {"tasklist.exe", "/fo", "csv", "/nh", "/v"}; - p = ProcessUtils.createProcess(command, null, null); - } - catch (Exception e) { - //Use fallback - return ProcessListWin32Internal.getProcessList(); - } - try { - return parseListTasks(p.getInputStream()); - } - finally { - p.destroy(); - } - } - catch (IOException ignored) { } + result = getProcessListFromWMIC(); + if (result != null) return result; + + result = getProcessListFromTaskList(); + if (result != null) return result; return ProcessInfo.EMPTY_ARRAY; } - private static ProcessInfo[] createFromWMIC() throws Exception { - @SuppressWarnings("SpellCheckingInspection") String[] command = {"wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline"}; - Process p = ProcessUtils.createProcess(command, null, null); - - List lst = new ArrayList(); - BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); + @Nullable + static ProcessInfo[] getProcessListFromWMIC() { + String output; try { - String line = br.readLine(); - //We should have something as: Caption CommandLine ProcessId - //From this we get the number of characters for each column - int commandLineI = line.indexOf("CommandLine"); - int processIdI = line.indexOf("ProcessId"); - if (commandLineI == -1) { - throw new AssertionError("Could not find CommandLine in: " + line); - } - if (processIdI == -1) { - throw new AssertionError("Could not find ProcessId in: " + line); - } - - while (true) { - line = br.readLine(); - if (line == null) { - break; - } - if (line.trim().length() == 0) { - continue; - } - String name = line.substring(0, commandLineI).trim(); - String commandLine = line.substring(commandLineI, processIdI).trim(); - String processId = line.substring(processIdI, line.length()).trim(); - lst.add(new ProcessInfo(Integer.parseInt(processId), name, commandLine)); - } - if (lst.size() == 0) { - throw new AssertionError("Error: no processes found"); - } - return lst.toArray(new ProcessInfo[lst.size()]); + GeneralCommandLine cl = new GeneralCommandLine("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline"); + output = ExecUtil.execAndGetOutput(cl).getStdout(); } - catch (Exception e) { - LOG.error(e); - throw e; - } - finally { - br.close(); + catch (ExecutionException ignore) { + return null; } + return parseWMICOutput(output); } - private static ProcessInfo[] parseListTasks(InputStream stream) throws IOException { - List processList = ContainerUtil.newArrayList(); + @Nullable + static ProcessInfo[] parseWMICOutput(@NotNull String output) { + List result = ContainerUtil.newArrayList(); + String[] lines = StringUtil.splitByLinesDontTrim(output); + if (lines.length < 1) return null; - CSVReader reader = new CSVReader(new BufferedReader(new InputStreamReader(stream))); + String header = lines[0]; + int commandLineI = header.indexOf("CommandLine"); + if (commandLineI == -1) return null; + int processIdI = header.indexOf("ProcessId"); + if (processIdI == -1) return null; + + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; + + int pid = StringUtil.parseInt(line.substring(processIdI, line.length()).trim(), -1); + if (pid == -1 || pid == 0) continue; + + String name = line.substring(0, commandLineI).trim(); + if (name.isEmpty()) continue; + + String commandLine = line.substring(commandLineI, processIdI).trim(); + String args = ""; + + int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0); + if (nameIndex != -1) { + args = commandLine.substring(nameIndex + name.length()).trim(); + } + + result.add(new ProcessInfo(pid, name, args)); + } + return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); + } + + @Nullable + static ProcessInfo[] getProcessListFromTaskList() { + String output; + try { + GeneralCommandLine cl = new GeneralCommandLine("tasklist.exe", "/fo", "csv", "/nh", "/v"); + output = ExecUtil.execAndGetOutput(cl).getStdout(); + } + catch (ExecutionException ignore) { + return null; + } + return parseListTasksOutput(output); + } + + @Nullable + static ProcessInfo[] parseListTasksOutput(@NotNull String output) { + List result = ContainerUtil.newArrayList(); + + CSVReader reader = new CSVReader(new StringReader(output)); try { String[] next; - do { - try { - next = reader.readNext(); - if (next != null) { - int pid = Integer.parseInt(next[1]); - String name = next[0] + " - " + next[next.length - 1]; - processList.add(new ProcessInfo(pid, name)); - } - } - catch (IOException e) { - break; - } + while ((next = reader.readNext()) != null) { + if (next.length < 2) continue; + + int pid = StringUtil.parseInt(next[1], -1); + if (pid == -1) continue; + + String name = next[0]; + if (name.isEmpty()) continue; + + result.add(new ProcessInfo(pid, name, "")); } - while (next != null); + } + catch (IOException ignore) { + return null; } finally { - reader.close(); + try { + reader.close(); + } + catch (IOException ignore) { + } } - return processList.isEmpty() ? ProcessInfo.EMPTY_ARRAY : processList.toArray(new ProcessInfo[processList.size()]); + return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java deleted file mode 100644 index bde2bda64a5a..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32Internal.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.execution.process; - -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.util.containers.ContainerUtil; - -import java.io.*; -import java.util.List; - -/** - * This implementation uses a listtasks which is shipped together (so, it should always work on windows). - * - * Use through ProcessUtils. - */ -class ProcessListWin32Internal { - private static final Logger LOG = Logger.getInstance(ProcessListWin32Internal.class); - - public static ProcessInfo[] getProcessList() { - String[] dirs = { - PathManager.getBinPath(), - PathManager.getHomePath() + "/community/bin/win", - PathManager.getBinPath() + "/win"}; - - File listtasks = null; - - for (String each : dirs) { - listtasks = new File(each, "listtasks.exe"); - } - - if (!listtasks.exists()) { - LOG.error("listtasks.exe not found in bin folders"); - return ProcessInfo.EMPTY_ARRAY; - } - - try { - String[] command = {listtasks.getCanonicalPath()}; - Process p = ProcessUtils.createProcess(command, null, null); - try { - return parseListTasks(p.getInputStream()); - } - finally { - p.destroy(); - } - } - catch (IOException ignored) { } - - return ProcessInfo.EMPTY_ARRAY; - } - - private static ProcessInfo[] parseListTasks(InputStream stream) throws IOException { - List processList = ContainerUtil.newArrayList(); - - BufferedReader br = new BufferedReader(new InputStreamReader(stream)); - try { - String line; - while ((line = br.readLine()) != null) { - int tab = line.indexOf('\t'); - if (tab != -1) { - String proc = line.substring(0, tab).trim(); - String name = line.substring(tab).trim(); - if (proc.length() > 0 && name.length() > 0) { - try { - int pid = Integer.parseInt(proc); - processList.add(new ProcessInfo(pid, name)); - } - catch (NumberFormatException ignored) { } - } - } - } - } - finally { - br.close(); - } - - return processList.isEmpty() ? ProcessInfo.EMPTY_ARRAY : processList.toArray(new ProcessInfo[processList.size()]); - } -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java index 3c918e685e08..a45015d0a5e0 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java @@ -31,37 +31,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import org.jetbrains.annotations.NotNull; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; - public class ProcessUtils { private static final Logger LOG = Logger.getInstance(ProcessUtils.class); - /** - * Passes the commands directly to Runtime.exec (with the passed envp) - */ - public static Process createProcess(String[] cmdarray, String[] envp, File workingDir) throws IOException { - return Runtime.getRuntime().exec(getWithoutEmptyParams(cmdarray), getWithoutEmptyParams(envp), workingDir); - } - - /** - * @return a new array without any null/empty elements originally contained in the array. - */ - private static String[] getWithoutEmptyParams(String[] cmdarray) { - if (cmdarray == null) { - return null; - } - ArrayList list = new ArrayList(); - for (String string : cmdarray) { - if (string != null && string.length() > 0) { - list.add(string); - } - } - return list.toArray(new String[list.size()]); - } - - @NotNull public static ProcessInfo[] getProcessList() { if (SystemInfo.isWindows) { diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java index 6235e72bd972..6f073123ddaa 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java @@ -87,6 +87,49 @@ public class ProcessUtilsTest extends UsefulTestCase { new ProcessInfo(2, "//" + myDir + "//dir//file//", "aaa bbb", "user", "S")); } + public void testProcessListOnLinuxMac_WrongFormat() throws Exception { + assertEmpty(ProcessListLinux.parseOutput( + false, + "" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + "wrong format")); + assertEmpty(ProcessListLinux.parseOutput( + false, + " PID S USER COMMAND\n\n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " PID S USER COMMAND\n\n" + + " \n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " 1 S user " + myDir + "/dir/file\n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " PID S USER XXX\n\n" + + " 1 S user " + myDir + "/dir/file\n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " PID S XXX COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " PID X USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + )); + assertEmpty(ProcessListLinux.parseOutput( + false, + " XXX S USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + )); + } + public void testProcessListOnMac() throws Exception { ProcessInfo[] infos = ProcessListLinux.parseOutput( true, @@ -123,4 +166,76 @@ public class ProcessUtilsTest extends UsefulTestCase { new ProcessInfo(101, myDir + "/dir/file", "", "user_name", "Ss")); } + public void testWindows_WMIC() throws Exception { + ProcessInfo[] infos = ProcessListWin32.parseWMICOutput( + "Caption CommandLine ProcessId \n" + + "smss.exe 304 \n" + + "sihost.exe sihost.exe 3052 \n" + + "taskhostw.exe taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E} 3068 \n" + + "explorer.exe C:\\WINDOWS\\Explorer.EXE 3164 \n" + + "TPAutoConnect.exe TPAutoConnect.exe -q -i vmware -a COM1 -F 30 3336 \n" + + "conhost.exe \\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4 3348 \n"); + assertOrderedEquals(infos, + new ProcessInfo(304, "smss.exe", "", null, null), + new ProcessInfo(3052, "sihost.exe", "", null, null), + new ProcessInfo(3068, "taskhostw.exe", "{222A245B-E637-4AE9-A93F-A59CA119A75E}", null, null), + new ProcessInfo(3164, "explorer.exe", "", null, null), + new ProcessInfo(3336, "TPAutoConnect.exe", "-q -i vmware -a COM1 -F 30", null, null), + new ProcessInfo(3348, "conhost.exe", "0x4", null, null)); + } + + public void testOnWindows_WMIC_DoNotIncludeSystemIdleProcess() throws Exception { + ProcessInfo[] infos = ProcessListWin32.parseWMICOutput( + "Caption CommandLine ProcessId \n" + + "System Idle Process 0 \n" + + "System 4 \n" + + "smss.exe 304 \n"); + assertOrderedEquals(infos, + new ProcessInfo(4, "System", "", null, null), + new ProcessInfo(304, "smss.exe", "", null, null)); + } + + public void testWindows_WMIC_WrongFormat() throws Exception { + assertNull(ProcessListWin32.parseWMICOutput( + "")); + assertNull(ProcessListWin32.parseWMICOutput( + "wrong format")); + assertEmpty(ProcessListWin32.parseWMICOutput( + "Caption CommandLine ProcessId \n")); + assertNull(ProcessListWin32.parseWMICOutput( + "smss.exe 304 \n")); + + assertNull(ProcessListWin32.parseWMICOutput( + "Caption XXX ProcessId \n" + + "smss.exe 304 \n")); + assertNull(ProcessListWin32.parseWMICOutput( + "Caption CommandLine XXX \n" + + "smss.exe 304 \n")); + assertEmpty(ProcessListWin32.parseWMICOutput( + "Caption CommandLine ProcessId \n" + + " \n")); + } + + public void testWindows_TaskList() throws Exception { + ProcessInfo[] infos = ProcessListWin32.parseListTasksOutput( + "\"smss.exe\",\"304\",\"Services\",\"0\",\"224 K\",\"Unknown\",\"N/A\",\"0:00:00\",\"N/A\"\n" + + "\"sihost.exe\",\"3052\",\"Console\",\"1\",\"10,924 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:02\",\"N/A\"\n" + + "\"taskhostw.exe\",\"3068\",\"Console\",\"1\",\"5,860 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:00\",\"Task Host Window\"\n" + + "\"explorer.exe\",\"3164\",\"Console\",\"1\",\"30,964 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:04\",\"N/A\"\n" + + "\"TPAutoConnect.exe\",\"3336\",\"Console\",\"1\",\"5,508 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:04\",\"HiddenTPAutoConnectWindow\"\n" + + "\"conhost.exe\",\"3348\",\"Console\",\"1\",\"1,172 K\",\"Unknown\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:00\",\"N/A\"\n"); + assertOrderedEquals(infos, + new ProcessInfo(304, "smss.exe", "", null, null), + new ProcessInfo(3052, "sihost.exe", "", null, null), + new ProcessInfo(3068, "taskhostw.exe", "", null, null), + new ProcessInfo(3164, "explorer.exe", "", null, null), + new ProcessInfo(3336, "TPAutoConnect.exe", "", null, null), + new ProcessInfo(3348, "conhost.exe", "", null, null)); + } + + public void testWindows_TaskList_WrongFormat() throws Exception { + assertEmpty(ProcessListWin32.parseListTasksOutput("")); + assertEmpty(ProcessListWin32.parseListTasksOutput("wrong format")); + assertEmpty(ProcessListWin32.parseListTasksOutput("\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"\n")); + } } \ No newline at end of file From ea9ff4c3701e29a9a50a8e51cd677b0abe6af413 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 17:55:00 +0100 Subject: [PATCH 014/825] IDEA-149798 Extensible Attach to Local Process action: Process list API moved to OSProcessManager (part1) --- .../execution/process/ProcessUtils.java | 48 ------------------- .../process/{ => impl}/CSVReader.java | 4 +- .../process/impl/OSProcessManagerImpl.java | 13 +++++ .../process/{ => impl}/ProcessListLinux.java | 3 +- .../process/{ => impl}/ProcessListWin32.java | 5 +- .../ProcessListTest.java} | 7 +-- .../actions/AttachToLocalProcessAction.java | 4 +- 7 files changed, 26 insertions(+), 58 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java rename platform/platform-impl/src/com/intellij/execution/process/{ => impl}/CSVReader.java (98%) rename platform/platform-impl/src/com/intellij/execution/process/{ => impl}/ProcessListLinux.java (97%) rename platform/platform-impl/src/com/intellij/execution/process/{ => impl}/ProcessListWin32.java (96%) rename platform/platform-tests/testSrc/com/intellij/execution/process/{ProcessUtilsTest.java => impl/ProcessListTest.java} (98%) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java deleted file mode 100644 index a45015d0a5e0..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 (C) 2013 Fabio Zadrozny - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Fabio Zadrozny - initial API and implementation - ******************************************************************************/ -package com.intellij.execution.process; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.SystemInfo; -import org.jetbrains.annotations.NotNull; - -public class ProcessUtils { - private static final Logger LOG = Logger.getInstance(ProcessUtils.class); - - @NotNull - public static ProcessInfo[] getProcessList() { - if (SystemInfo.isWindows) { - return ProcessListWin32.getProcessList(); - } - if (SystemInfo.isLinux || SystemInfo.isMac) { - return ProcessListLinux.getProcessList(SystemInfo.isMac); - } - LOG.error("Unexpected platform. Unable to list processes."); - return new ProcessInfo[0]; - } -} diff --git a/platform/platform-impl/src/com/intellij/execution/process/CSVReader.java b/platform/platform-impl/src/com/intellij/execution/process/impl/CSVReader.java similarity index 98% rename from platform/platform-impl/src/com/intellij/execution/process/CSVReader.java rename to platform/platform-impl/src/com/intellij/execution/process/impl/CSVReader.java index a78e63b52189..3aaed8ac1765 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/CSVReader.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/CSVReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -16,7 +16,7 @@ // From: http://www.halley.cc/code/?java/CSVReader.java -package com.intellij.execution.process; +package com.intellij.execution.process.impl; import java.io.BufferedReader; import java.io.IOException; diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java index ed3a8dcb9dc9..27fb5d8b716e 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java @@ -16,6 +16,7 @@ package com.intellij.execution.process.impl; import com.intellij.execution.process.OSProcessManager; +import com.intellij.execution.process.ProcessInfo; import com.intellij.execution.process.RunnerWinProcess; import com.intellij.execution.process.UnixProcessManager; import com.intellij.openapi.diagnostic.Logger; @@ -39,6 +40,18 @@ import java.util.List; public class OSProcessManagerImpl extends OSProcessManager { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.impl.OSProcessManagerImpl"); + @NotNull + public static ProcessInfo[] getProcessList() { + if (SystemInfo.isWindows) { + return ProcessListWin32.getProcessList(); + } + if (SystemInfo.isLinux || SystemInfo.isMac) { + return ProcessListLinux.getProcessList(SystemInfo.isMac); + } + LOG.error("Unexpected platform. Unable to list processes."); + return new ProcessInfo[0]; + } + @Override public boolean killProcessTree(@NotNull Process process) { if (SystemInfo.isWindows) { diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java similarity index 97% rename from platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java rename to platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java index 40deb0a42d56..ee57696f7293 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListLinux.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.intellij.execution.process; +package com.intellij.execution.process.impl; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessInfo; import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java similarity index 96% rename from platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java rename to platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java index f2e46686271a..d96629c4721e 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessListWin32.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.execution.process; +package com.intellij.execution.process.impl; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessInfo; import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java similarity index 98% rename from platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java rename to platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index 6f073123ddaa..f731c3053f77 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessUtilsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.execution.process; +package com.intellij.execution.process.impl; +import com.intellij.execution.process.ProcessInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.IoTestUtil; import com.intellij.testFramework.UsefulTestCase; @@ -22,7 +23,7 @@ import com.intellij.testFramework.UsefulTestCase; import java.io.File; import java.util.Arrays; -public class ProcessUtilsTest extends UsefulTestCase { +public class ProcessListTest extends UsefulTestCase { private File myDir; @Override @@ -41,7 +42,7 @@ public class ProcessUtilsTest extends UsefulTestCase { } public void testProcessList_WorksOnAllPlatforms() throws Exception { - assertNotEmpty(Arrays.asList(ProcessUtils.getProcessList())); + assertNotEmpty(Arrays.asList(OSProcessManagerImpl.getProcessList())); } public void testProcessListOnLinux_DetermineExecutable() throws Exception { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 999126591801..6a568ea672b5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -17,7 +17,7 @@ package com.intellij.xdebugger.impl.actions; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.process.ProcessUtils; +import com.intellij.execution.process.impl.OSProcessManagerImpl; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -106,7 +106,7 @@ public class AttachToLocalProcessAction extends AnAction { List result = new ArrayList(); UserDataHolderBase dataHolder = new UserDataHolderBase(); - for (ProcessInfo eachInfo : ProcessUtils.getProcessList()) { + for (ProcessInfo eachInfo : OSProcessManagerImpl.getProcessList()) { List availableDebuggers = new ArrayList(); for (XLocalAttachDebuggerProvider eachProvider : Extensions.getExtensions(XLocalAttachDebuggerProvider.EP)) { availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo, dataHolder)); From aef4010840deb0747f2908e9445a8aa9b379db2a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 18:20:57 +0100 Subject: [PATCH 015/825] Process list API moved to OSProcessManager and generalized reference: IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths IDEA-149798 Extensible Attach to Local Process action --- .../process/impl/OSProcessManagerImpl.java | 9 +- .../process/impl/ProcessListLinux.java | 128 -------- .../process/impl/ProcessListUtil.java | 273 ++++++++++++++++++ .../process/impl/ProcessListWin32.java | 137 --------- .../process/impl/ProcessListTest.java | 109 ++++--- 5 files changed, 335 insertions(+), 321 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java create mode 100644 platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java delete mode 100644 platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java index 27fb5d8b716e..3ce17b7d3ac9 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java @@ -42,14 +42,7 @@ public class OSProcessManagerImpl extends OSProcessManager { @NotNull public static ProcessInfo[] getProcessList() { - if (SystemInfo.isWindows) { - return ProcessListWin32.getProcessList(); - } - if (SystemInfo.isLinux || SystemInfo.isMac) { - return ProcessListLinux.getProcessList(SystemInfo.isMac); - } - LOG.error("Unexpected platform. Unable to list processes."); - return new ProcessInfo[0]; + return ProcessListUtil.getProcessList(); } @Override diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java deleted file mode 100644 index ee57696f7293..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListLinux.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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. - */ - -package com.intellij.execution.process.impl; - -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.util.ExecUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.List; - - -class ProcessListLinux { - @NotNull - public static ProcessInfo[] getProcessList(boolean isMac) { - String output; - try { - output = ExecUtil.execAndGetOutput(new GeneralCommandLine("/bin/ps", "-a", "-x", "-o", "pid,state,user,command")).getStdout(); - } - catch (ExecutionException ignore) { - return ProcessInfo.EMPTY_ARRAY; - } - return parseOutput(isMac, output); - } - - @NotNull - static ProcessInfo[] parseOutput(boolean isMac, @NotNull String output) { - List result = ContainerUtil.newArrayList(); - String[] lines = StringUtil.splitByLinesDontTrim(output); - if (lines.length < 2) return ProcessInfo.EMPTY_ARRAY; - - String header = lines[0]; - int pidStart = header.indexOf("PID"); - if (pidStart == -1) return ProcessInfo.EMPTY_ARRAY; - - int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); - if (statStart == -1) return ProcessInfo.EMPTY_ARRAY; - - int userStart = header.indexOf("USER", statStart); - if (userStart == -1) return ProcessInfo.EMPTY_ARRAY; - - int commandStart = header.indexOf("COMMAND", userStart); - if (commandStart == -1) return ProcessInfo.EMPTY_ARRAY; - - for (int i = 1; i < lines.length; i++) { - String line = lines[i]; - - int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1); - if (pid == -1) continue; - - String state = line.substring(statStart, userStart).trim(); - if (state.contains("Z")) continue; // zombie - - String user = line.substring(userStart, commandStart).trim(); - String commandLine = line.substring(commandStart).trim(); - - String executablePath = determineExecutable(commandLine); - if (executablePath == null) continue; - - String args = commandLine.substring(executablePath.length()).trim(); - result.add(new ProcessInfo(pid, executablePath, args, user, state)); - } - - return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); - } - - - @Nullable - private static String determineExecutable(String commandLine) { - // Since there is no way on Linux to get the path to the executable, we have to heuristically determine it - // by finding the longest existing file path from the beginning of the command line. - // There is a possibility to find the wrong path in ambiguous cases like the following: - // * "/path/to/executable with spaces" - file name with spaces - // * "/path/to/executable" "with spaces" - file name + arguments - // Though probability of such a situation is negligible - - String executablePath = commandLine; - - found: - while (!new File(executablePath).exists()) { - int separator = executablePath.lastIndexOf("/"); - if (separator == -1) return null; - - String parentPath = executablePath.substring(0, separator); - - if (new File(parentPath).exists()) { - String name = executablePath.substring(separator + 1); - int space = name.lastIndexOf(" "); - - while (true) { - String namePart = name.substring(0, space == -1 ? name.length() : space); - if (new File(parentPath, namePart).exists()) { - executablePath = parentPath + "/" + namePart; - break found; - } - - if (space == -1) break; - space = name.lastIndexOf(" ", space - 1); - } - } - separator = parentPath.lastIndexOf(" "); - if (separator == -1) return null; - executablePath = parentPath.substring(0, separator); - } - - assert commandLine.startsWith(executablePath) : "Executable incorrectly found: " + executablePath + " in: " + commandLine; - return executablePath; - } -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java new file mode 100644 index 000000000000..28effcaf6331 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -0,0 +1,273 @@ +/* + * 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. + */ + +package com.intellij.execution.process.impl; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.process.ProcessInfo; +import com.intellij.execution.util.ExecUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +class ProcessListUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.impl.ProcessListUtil"); + + @NotNull + static ProcessInfo[] getProcessList() { + List result = doGetProcessList(); + return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); + } + + @NotNull + private static List doGetProcessList() { + List result; + if (SystemInfo.isWindows) { + + result = getProcessList_WindowsWMIC(); + if (result != null) return result; + + LOG.info("Cannot get process list via wmic, fallback to tasklist"); + result = getProcessList_WindowsTaskList(); + if (result != null) return result; + + LOG.error("Cannot get process list via wmic and tasklist"); + } + else if (SystemInfo.isLinux || SystemInfo.isMac) { + result = getProcessList_Unix(SystemInfo.isMac); + if (result != null) return result; + + LOG.error("Cannot get process list"); + } + else { + LOG.error("Unexpected platform. Unable to list processes."); + } + return Collections.emptyList(); + } + + @Nullable + private static List parseCommandOutput(@NotNull List command, + @NotNull NullableFunction> parser) { + String output; + try { + output = ExecUtil.execAndGetOutput(new GeneralCommandLine(command)).getStdout(); + } + catch (ExecutionException ignore) { + return null; + } + return parser.fun(output); + } + + @Nullable + private static List getProcessList_Unix(final boolean isMac) { + return parseCommandOutput(Arrays.asList("/bin/ps", "-a", "-x", "-o", "pid,state,user,command"), + new NullableFunction>() { + @Nullable + @Override + public List fun(String output) { + return parseUnixOutput(isMac, output); + } + }); + } + + @Nullable + static List parseUnixOutput(boolean isMac, @NotNull String output) { + List result = ContainerUtil.newArrayList(); + String[] lines = StringUtil.splitByLinesDontTrim(output); + if (lines.length == 0) return null; + + String header = lines[0]; + int pidStart = header.indexOf("PID"); + if (pidStart == -1) return null; + + int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); + if (statStart == -1) return null; + + int userStart = header.indexOf("USER", statStart); + if (userStart == -1) return null; + + int commandStart = header.indexOf("COMMAND", userStart); + if (commandStart == -1) return null; + + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; + + int pid = StringUtil.parseInt(line.substring(0, statStart).trim(), -1); + if (pid == -1) continue; + + String state = line.substring(statStart, userStart).trim(); + if (state.contains("Z")) continue; // zombie + + String user = line.substring(userStart, commandStart).trim(); + String commandLine = line.substring(commandStart).trim(); + + String executablePath = determineExecutable(commandLine); + if (executablePath == null) continue; + + String args = commandLine.substring(executablePath.length()).trim(); + result.add(new ProcessInfo(pid, executablePath, args, user, state)); + } + + return result; + } + + @Nullable + private static String determineExecutable(String commandLine) { + // Since there is no way on Linux to get the path to the executable, we have to heuristically determine it + // by finding the longest existing file path from the beginning of the command line. + // There is a possibility to find the wrong path in ambiguous cases like the following: + // * "/path/to/executable with spaces" - file name with spaces + // * "/path/to/executable" "with spaces" - file name + arguments + // Though probability of such a situation is negligible + + String executablePath = commandLine; + + found: + while (!new File(executablePath).exists()) { + int separator = executablePath.lastIndexOf("/"); + if (separator == -1) return null; + + String parentPath = executablePath.substring(0, separator); + + if (new File(parentPath).exists()) { + String name = executablePath.substring(separator + 1); + int space = name.lastIndexOf(" "); + + while (true) { + String namePart = name.substring(0, space == -1 ? name.length() : space); + if (new File(parentPath, namePart).exists()) { + executablePath = parentPath + "/" + namePart; + break found; + } + + if (space == -1) break; + space = name.lastIndexOf(" ", space - 1); + } + } + separator = parentPath.lastIndexOf(" "); + if (separator == -1) return null; + executablePath = parentPath.substring(0, separator); + } + + assert commandLine.startsWith(executablePath) : "Executable incorrectly found: " + executablePath + " in: " + commandLine; + return executablePath; + } + + @Nullable + static List getProcessList_WindowsWMIC() { + return parseCommandOutput(Arrays.asList("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline"), + new NullableFunction>() { + @Nullable + @Override + public List fun(String output) { + return parseWMICOutput(output); + } + }); + } + + @Nullable + static List parseWMICOutput(@NotNull String output) { + List result = ContainerUtil.newArrayList(); + String[] lines = StringUtil.splitByLinesDontTrim(output); + if (lines.length == 0) return null; + + String header = lines[0]; + int commandLineStart = header.indexOf("CommandLine"); + if (commandLineStart == -1) return null; + + int pidStart = header.indexOf("ProcessId"); + if (pidStart == -1) return null; + + for (int i = 1; i < lines.length; i++) { + String line = lines[i]; + + int pid = StringUtil.parseInt(line.substring(pidStart, line.length()).trim(), -1); + if (pid == -1 || pid == 0) continue; + + String name = line.substring(0, commandLineStart).trim(); + if (name.isEmpty()) continue; + + String commandLine = line.substring(commandLineStart, pidStart).trim(); + String args = ""; + + int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0); + if (nameIndex != -1) { + args = commandLine.substring(nameIndex + name.length()).trim(); + } + + result.add(new ProcessInfo(pid, name, args)); + } + return result; + } + + @Nullable + static List getProcessList_WindowsTaskList() { + return parseCommandOutput(Arrays.asList("tasklist.exe", "/fo", "csv", "/nh", "/v"), + new NullableFunction>() { + @Nullable + @Override + public List fun(String output) { + return parseListTasksOutput(output); + } + }); + } + + @Nullable + static List parseListTasksOutput(@NotNull String output) { + List result = ContainerUtil.newArrayList(); + + CSVReader reader = new CSVReader(new StringReader(output)); + try { + String[] next; + while ((next = reader.readNext()) != null) { + if (next.length < 2) return null; + + int pid = StringUtil.parseInt(next[1], -1); + if (pid == -1) continue; + + String name = next[0]; + if (name.isEmpty()) continue; + + result.add(new ProcessInfo(pid, name, "")); + } + } + catch (IOException ignore) { + return null; + } + finally { + try { + reader.close(); + } + catch (IOException ignore) { + } + } + + return result; + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java deleted file mode 100644 index d96629c4721e..000000000000 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListWin32.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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. - */ -package com.intellij.execution.process.impl; - -import com.intellij.execution.ExecutionException; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.util.ExecUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.io.StringReader; -import java.util.List; - -class ProcessListWin32 { - @NotNull - public static ProcessInfo[] getProcessList() { - ProcessInfo[] result; - - result = getProcessListFromWMIC(); - if (result != null) return result; - - result = getProcessListFromTaskList(); - if (result != null) return result; - - return ProcessInfo.EMPTY_ARRAY; - } - - @Nullable - static ProcessInfo[] getProcessListFromWMIC() { - String output; - try { - GeneralCommandLine cl = new GeneralCommandLine("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline"); - output = ExecUtil.execAndGetOutput(cl).getStdout(); - } - catch (ExecutionException ignore) { - return null; - } - return parseWMICOutput(output); - } - - @Nullable - static ProcessInfo[] parseWMICOutput(@NotNull String output) { - List result = ContainerUtil.newArrayList(); - String[] lines = StringUtil.splitByLinesDontTrim(output); - if (lines.length < 1) return null; - - String header = lines[0]; - int commandLineI = header.indexOf("CommandLine"); - if (commandLineI == -1) return null; - int processIdI = header.indexOf("ProcessId"); - if (processIdI == -1) return null; - - for (int i = 1; i < lines.length; i++) { - String line = lines[i]; - - int pid = StringUtil.parseInt(line.substring(processIdI, line.length()).trim(), -1); - if (pid == -1 || pid == 0) continue; - - String name = line.substring(0, commandLineI).trim(); - if (name.isEmpty()) continue; - - String commandLine = line.substring(commandLineI, processIdI).trim(); - String args = ""; - - int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0); - if (nameIndex != -1) { - args = commandLine.substring(nameIndex + name.length()).trim(); - } - - result.add(new ProcessInfo(pid, name, args)); - } - return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); - } - - @Nullable - static ProcessInfo[] getProcessListFromTaskList() { - String output; - try { - GeneralCommandLine cl = new GeneralCommandLine("tasklist.exe", "/fo", "csv", "/nh", "/v"); - output = ExecUtil.execAndGetOutput(cl).getStdout(); - } - catch (ExecutionException ignore) { - return null; - } - return parseListTasksOutput(output); - } - - @Nullable - static ProcessInfo[] parseListTasksOutput(@NotNull String output) { - List result = ContainerUtil.newArrayList(); - - CSVReader reader = new CSVReader(new StringReader(output)); - try { - String[] next; - while ((next = reader.readNext()) != null) { - if (next.length < 2) continue; - - int pid = StringUtil.parseInt(next[1], -1); - if (pid == -1) continue; - - String name = next[0]; - if (name.isEmpty()) continue; - - result.add(new ProcessInfo(pid, name, "")); - } - } - catch (IOException ignore) { - return null; - } - finally { - try { - reader.close(); - } - catch (IOException ignore) { - } - } - - return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); - } -} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index f731c3053f77..7905777d59b6 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -16,16 +16,19 @@ package com.intellij.execution.process.impl; import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.IoTestUtil; import com.intellij.testFramework.UsefulTestCase; import java.io.File; import java.util.Arrays; +import java.util.List; public class ProcessListTest extends UsefulTestCase { private File myDir; + @SuppressWarnings("ResultOfMethodCallIgnored") @Override public void setUp() throws Exception { super.setUp(); @@ -37,16 +40,25 @@ public class ProcessListTest extends UsefulTestCase { @Override public void tearDown() throws Exception { - FileUtil.delete(myDir); - super.tearDown(); + try { + FileUtil.delete(myDir); + } + finally { + super.tearDown(); + } } - public void testProcessList_WorksOnAllPlatforms() throws Exception { + public void testWorksOnAllPlatforms() throws Exception { assertNotEmpty(Arrays.asList(OSProcessManagerImpl.getProcessList())); + + if (SystemInfo.isWindows) { + assertNotEmpty(Arrays.asList(ProcessListUtil.getProcessList_WindowsTaskList())); + assertNotEmpty(Arrays.asList(ProcessListUtil.getProcessList_WindowsWMIC())); + } } - - public void testProcessListOnLinux_DetermineExecutable() throws Exception { - ProcessInfo[] infos = ProcessListLinux.parseOutput( + + public void testUnix_DetermineExecutable() throws Exception { + List infos = ProcessListUtil.parseUnixOutput( false, " PID S USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + @@ -75,9 +87,9 @@ public class ProcessListTest extends UsefulTestCase { new ProcessInfo(9, myDir + "/dir/dir/file with spaces/", "", "user", "S"), new ProcessInfo(10, myDir + "/dir/dir", "", "user", "S")); } - - public void testProcessListOnLinux_DetermineExecutableWithExtraSlashes() throws Exception { - ProcessInfo[] infos = ProcessListLinux.parseOutput( + + public void testUnix_DetermineExecutableWithExtraSlashes() throws Exception { + List infos = ProcessListUtil.parseUnixOutput( false, " PID S USER COMMAND\n\n" + " 1 S user //" + myDir + "//dir//file//\n" + @@ -88,51 +100,63 @@ public class ProcessListTest extends UsefulTestCase { new ProcessInfo(2, "//" + myDir + "//dir//file//", "aaa bbb", "user", "S")); } - public void testProcessListOnLinuxMac_WrongFormat() throws Exception { - assertEmpty(ProcessListLinux.parseOutput( + public void testUnix_VariousFormsPidStatUser() throws Exception { + List infos = ProcessListUtil.parseUnixOutput( + true, + " PID STAT USER COMMAND\n\n" + + " 1 S user " + myDir + "/dir/file\n" + + " 101 Ss user_name " + myDir + "/dir/file\n" + ); + assertOrderedEquals(infos, + new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), + new ProcessInfo(101, myDir + "/dir/file", "", "user_name", "Ss")); + } + + public void testUnix_WrongFormat() throws Exception { + assertNull(ProcessListUtil.parseUnixOutput( false, "" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, "wrong format")); - assertEmpty(ProcessListLinux.parseOutput( + assertEmpty(ProcessListUtil.parseUnixOutput( false, " PID S USER COMMAND\n\n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertEmpty(ProcessListUtil.parseUnixOutput( false, " PID S USER COMMAND\n\n" + " \n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, " 1 S user " + myDir + "/dir/file\n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, " PID S USER XXX\n\n" + " 1 S user " + myDir + "/dir/file\n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, " PID S XXX COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, " PID X USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); - assertEmpty(ProcessListLinux.parseOutput( + assertNull(ProcessListUtil.parseUnixOutput( false, " XXX S USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); } - public void testProcessListOnMac() throws Exception { - ProcessInfo[] infos = ProcessListLinux.parseOutput( + public void testMac() throws Exception { + List infos = ProcessListUtil.parseUnixOutput( true, " PID STAT USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + @@ -143,8 +167,8 @@ public class ProcessListTest extends UsefulTestCase { new ProcessInfo(2, myDir + "/dir/dir/file", "", "user", "S")); } - public void testProcessListOnMac_DoNotIncludeZombies() throws Exception { - ProcessInfo[] infos = ProcessListLinux.parseOutput( + public void testMac_DoNotIncludeZombies() throws Exception { + List infos = ProcessListUtil.parseUnixOutput( true, " PID STAT USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + @@ -155,20 +179,8 @@ public class ProcessListTest extends UsefulTestCase { new ProcessInfo(1, myDir + "/dir/file", "", "user", "S")); } - public void testProcessListOnLinuxMac_VariousFormsPidStatUser() throws Exception { - ProcessInfo[] infos = ProcessListLinux.parseOutput( - true, - " PID STAT USER COMMAND\n\n" + - " 1 S user " + myDir + "/dir/file\n" + - " 101 Ss user_name " + myDir + "/dir/file\n" - ); - assertOrderedEquals(infos, - new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), - new ProcessInfo(101, myDir + "/dir/file", "", "user_name", "Ss")); - } - public void testWindows_WMIC() throws Exception { - ProcessInfo[] infos = ProcessListWin32.parseWMICOutput( + List infos = ProcessListUtil.parseWMICOutput( "Caption CommandLine ProcessId \n" + "smss.exe 304 \n" + "sihost.exe sihost.exe 3052 \n" + @@ -186,7 +198,7 @@ public class ProcessListTest extends UsefulTestCase { } public void testOnWindows_WMIC_DoNotIncludeSystemIdleProcess() throws Exception { - ProcessInfo[] infos = ProcessListWin32.parseWMICOutput( + List infos = ProcessListUtil.parseWMICOutput( "Caption CommandLine ProcessId \n" + "System Idle Process 0 \n" + "System 4 \n" + @@ -197,28 +209,28 @@ public class ProcessListTest extends UsefulTestCase { } public void testWindows_WMIC_WrongFormat() throws Exception { - assertNull(ProcessListWin32.parseWMICOutput( + assertNull(ProcessListUtil.parseWMICOutput( "")); - assertNull(ProcessListWin32.parseWMICOutput( + assertNull(ProcessListUtil.parseWMICOutput( "wrong format")); - assertEmpty(ProcessListWin32.parseWMICOutput( + assertEmpty(ProcessListUtil.parseWMICOutput( "Caption CommandLine ProcessId \n")); - assertNull(ProcessListWin32.parseWMICOutput( + assertNull(ProcessListUtil.parseWMICOutput( "smss.exe 304 \n")); - assertNull(ProcessListWin32.parseWMICOutput( + assertNull(ProcessListUtil.parseWMICOutput( "Caption XXX ProcessId \n" + "smss.exe 304 \n")); - assertNull(ProcessListWin32.parseWMICOutput( + assertNull(ProcessListUtil.parseWMICOutput( "Caption CommandLine XXX \n" + "smss.exe 304 \n")); - assertEmpty(ProcessListWin32.parseWMICOutput( + assertEmpty(ProcessListUtil.parseWMICOutput( "Caption CommandLine ProcessId \n" + " \n")); } public void testWindows_TaskList() throws Exception { - ProcessInfo[] infos = ProcessListWin32.parseListTasksOutput( + List infos = ProcessListUtil.parseListTasksOutput( "\"smss.exe\",\"304\",\"Services\",\"0\",\"224 K\",\"Unknown\",\"N/A\",\"0:00:00\",\"N/A\"\n" + "\"sihost.exe\",\"3052\",\"Console\",\"1\",\"10,924 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:02\",\"N/A\"\n" + "\"taskhostw.exe\",\"3068\",\"Console\",\"1\",\"5,860 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:00\",\"Task Host Window\"\n" + @@ -235,8 +247,9 @@ public class ProcessListTest extends UsefulTestCase { } public void testWindows_TaskList_WrongFormat() throws Exception { - assertEmpty(ProcessListWin32.parseListTasksOutput("")); - assertEmpty(ProcessListWin32.parseListTasksOutput("wrong format")); - assertEmpty(ProcessListWin32.parseListTasksOutput("\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"\n")); + assertEmpty(ProcessListUtil.parseListTasksOutput("")); + assertNull(ProcessListUtil.parseListTasksOutput("wrong format")); + assertNull(ProcessListUtil.parseListTasksOutput("\"\"")); + assertEmpty(ProcessListUtil.parseListTasksOutput("\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"\n")); } } \ No newline at end of file From a2f3a90110064399726390cb26e8bbcf31a4bfaf Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 18:53:52 +0100 Subject: [PATCH 016/825] ProcessInfo.getCommandLine API + OSProcessManager.getCommandLinesOfRunningProcesses utilizes new getProcessList API reference: IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths IDEA-149798 Extensible Attach to Local Process action --- .../execution/process/ProcessInfo.java | 29 +++++---- .../process/impl/OSProcessManagerImpl.java | 57 ++--------------- .../process/impl/ProcessListUtil.java | 22 ++++--- .../execution/process/ProcessInfoTest.java | 10 +-- .../process/impl/ProcessListTest.java | 62 +++++++++---------- .../openapi/util/text/StringUtil.java | 8 +++ .../intellij/util/text/StringUtilTest.java | 18 ++++++ 7 files changed, 99 insertions(+), 107 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index 7bdf322f21dd..4563c607d4d8 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -16,7 +16,6 @@ package com.intellij.execution.process; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,22 +24,21 @@ public class ProcessInfo { public static ProcessInfo[] EMPTY_ARRAY = new ProcessInfo[0]; private final int myPid; + @NotNull private final String myCommandLine; @NotNull private final String myExecutableName; @NotNull private final String myArgs; @Nullable private final String myUser; @Nullable private final String myState; - public ProcessInfo(int pid, @NotNull String executable) { - this(pid, executable, ""); - } - - public ProcessInfo(int pid, @NotNull String executable, @NotNull String args) { - this(pid, executable, args, null, null); - } - - public ProcessInfo(int pid, @NotNull String executable, @NotNull String args, @Nullable String user, @Nullable String state) { + public ProcessInfo(int pid, + @NotNull String commandLine, + @NotNull String executableName, + @NotNull String args, + @Nullable String user, + @Nullable String state) { myPid = pid; - myExecutableName = PathUtil.getFileName(executable); + myCommandLine = commandLine; + myExecutableName = executableName; myArgs = args; myState = state; myUser = user; @@ -50,6 +48,11 @@ public class ProcessInfo { return myPid; } + @NotNull + public String getCommandLine() { + return myCommandLine; + } + @NotNull public String getExecutableName() { return myExecutableName; @@ -77,7 +80,7 @@ public class ProcessInfo { @Override public String toString() { - return myPid + " '" + myExecutableName + "' '" + myArgs + "' '" + myUser + "' '" + myState; + return myPid + " '" + myCommandLine + "' '" + myExecutableName + "' '" + myArgs + "' '" + myUser + "' '" + myState; } @Override @@ -90,6 +93,7 @@ public class ProcessInfo { if (myPid != info.myPid) return false; if (!myExecutableName.equals(info.myExecutableName)) return false; if (!myArgs.equals(info.myArgs)) return false; + if (!myCommandLine.equals(info.myCommandLine)) return false; if (myUser != null ? !myUser.equals(info.myUser) : info.myUser != null) return false; if (myState != null ? !myState.equals(info.myState) : info.myState != null) return false; @@ -101,6 +105,7 @@ public class ProcessInfo { int result = myPid; result = 31 * result + myExecutableName.hashCode(); result = 31 * result + myArgs.hashCode(); + result = 31 * result + myCommandLine.hashCode(); result = 31 * result + (myUser != null ? myUser.hashCode() : 0); result = 31 * result + (myState != null ? myState.hashCode() : 0); return result; diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java index 3ce17b7d3ac9..80b32a154dfe 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java @@ -21,17 +21,11 @@ import com.intellij.execution.process.RunnerWinProcess; import com.intellij.execution.process.UnixProcessManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jvnet.winp.WinProcess; -import org.jvnet.winp.WinpException; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -103,51 +97,10 @@ public class OSProcessManagerImpl extends OSProcessManager { @Override public List getCommandLinesOfRunningProcesses() { - try { - if (SystemInfo.isWindows) { - List commandLines = new ArrayList(); - for (WinProcess process : WinProcess.all()) { - try { - commandLines.add(process.getCommandLine()); - } - catch (WinpException ignored) { } - } - return commandLines; - } - else { - String[] cmd = UnixProcessManager.getPSCmd(true); - Process process = Runtime.getRuntime().exec(cmd); - List outputLines = readLines(process.getInputStream(), false); - List errorLines = readLines(process.getErrorStream(), false); - if (!errorLines.isEmpty()) { - throw new IOException(Arrays.toString(cmd) + " failed: " + StringUtil.join(errorLines, "\n")); - } - - //trim 'ps' output header - return outputLines.subList(1, outputLines.size()); - } - } - catch (Throwable e) { - LOG.info("Cannot collect command lines"); - LOG.info(e); - return null; - } - } - - private static List readLines(@NotNull InputStream inputStream, boolean includeEmpty) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - try { - List lines = new ArrayList(); - String line; - while ((line = reader.readLine()) != null) { - if (includeEmpty || !line.isEmpty()) { - lines.add(line); - } - } - return lines; - } - finally { - reader.close(); + List result = new ArrayList(); + for (ProcessInfo each : getProcessList()) { + result.add(each.getCommandLine()); } + return Collections.unmodifiableList(result); } } diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index 28effcaf6331..af890df91447 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.NullableFunction; +import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -131,7 +132,9 @@ class ProcessListUtil { if (executablePath == null) continue; String args = commandLine.substring(executablePath.length()).trim(); - result.add(new ProcessInfo(pid, executablePath, args, user, state)); + + String name = PathUtil.getFileName(StringUtil.trimTrailing(executablePath, '/')); + result.add(new ProcessInfo(pid, commandLine, name, args, user, state)); } return result; @@ -200,7 +203,7 @@ class ProcessListUtil { String header = lines[0]; int commandLineStart = header.indexOf("CommandLine"); if (commandLineStart == -1) return null; - + int pidStart = header.indexOf("ProcessId"); if (pidStart == -1) return null; @@ -216,12 +219,17 @@ class ProcessListUtil { String commandLine = line.substring(commandLineStart, pidStart).trim(); String args = ""; - int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0); - if (nameIndex != -1) { - args = commandLine.substring(nameIndex + name.length()).trim(); + if (commandLine.isEmpty()) { + commandLine = name; + } + else { + int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0); + if (nameIndex != -1) { + args = commandLine.substring(nameIndex + name.length()).trim(); + } } - result.add(new ProcessInfo(pid, name, args)); + result.add(new ProcessInfo(pid, commandLine, name, args, null, null)); } return result; } @@ -254,7 +262,7 @@ class ProcessListUtil { String name = next[0]; if (name.isEmpty()) continue; - result.add(new ProcessInfo(pid, name, "")); + result.add(new ProcessInfo(pid, name, name, "", null, null)); } } catch (IOException ignore) { diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java index 32f2147a01fb..ef5ce631dc92 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/ProcessInfoTest.java @@ -19,10 +19,10 @@ import com.intellij.testFramework.UsefulTestCase; public class ProcessInfoTest extends UsefulTestCase { public void testExecutableName() throws Exception { - assertEquals("foo", new ProcessInfo(1, "foo", "bar").getExecutableDisplayName()); - assertEquals("foo", new ProcessInfo(1, "foo.exe", "bar").getExecutableDisplayName()); - assertEquals("foo", new ProcessInfo(1, "foo.EXE", "bar").getExecutableDisplayName()); - assertEquals("foo.bar", new ProcessInfo(1, "foo.bar", "bar").getExecutableDisplayName()); - assertEquals("foo.1.2", new ProcessInfo(1, "foo.1.2", "bar").getExecutableDisplayName()); + assertEquals("foo", new ProcessInfo(1, "", "foo", "", null, null).getExecutableDisplayName()); + assertEquals("foo", new ProcessInfo(1, "", "foo.exe", "", null, null).getExecutableDisplayName()); + assertEquals("foo", new ProcessInfo(1, "", "foo.EXE", "", null, null).getExecutableDisplayName()); + assertEquals("foo.bar", new ProcessInfo(1, "", "foo.bar", "", null, null).getExecutableDisplayName()); + assertEquals("foo.1.2", new ProcessInfo(1, "", "foo.1.2", "", null, null).getExecutableDisplayName()); } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index 7905777d59b6..8aa7f9daff93 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -76,16 +76,16 @@ public class ProcessListTest extends UsefulTestCase { " 13 S user " + myDir + "/dir/dir/file_unknown\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), - new ProcessInfo(2, myDir + "/dir/dir/file", "", "user", "S"), - new ProcessInfo(3, myDir + "/dir/dir/file", "param param", "user", "S"), - new ProcessInfo(4, myDir + "/dir/dir/file", "with", "user", "S"), - new ProcessInfo(5, myDir + "/dir/dir/file with spaces", "", "user", "S"), - new ProcessInfo(6, myDir + "/dir/dir/file with spaces", "param param", "user", "S"), - new ProcessInfo(7, myDir + "/dir/dir/file", "with spaces/foo", "user", "S"), - new ProcessInfo(8, myDir + "/dir/dir/file/", "", "user", "S"), - new ProcessInfo(9, myDir + "/dir/dir/file with spaces/", "", "user", "S"), - new ProcessInfo(10, myDir + "/dir/dir", "", "user", "S")); + new ProcessInfo(1, myDir + "/dir/file", "file", "", "user", "S"), + new ProcessInfo(2, myDir + "/dir/dir/file", "file", "", "user", "S"), + new ProcessInfo(3, myDir + "/dir/dir/file param param", "file", "param param", "user", "S"), + new ProcessInfo(4, myDir + "/dir/dir/file with", "file", "with", "user", "S"), + new ProcessInfo(5, myDir + "/dir/dir/file with spaces", "file with spaces", "", "user", "S"), + new ProcessInfo(6, myDir + "/dir/dir/file with spaces param param", "file with spaces", "param param", "user", "S"), + new ProcessInfo(7, myDir + "/dir/dir/file with spaces/foo", "file", "with spaces/foo", "user", "S"), + new ProcessInfo(8, myDir + "/dir/dir/file/", "file", "", "user", "S"), + new ProcessInfo(9, myDir + "/dir/dir/file with spaces/", "file with spaces", "", "user", "S"), + new ProcessInfo(10, myDir + "/dir/dir", "dir", "", "user", "S")); } public void testUnix_DetermineExecutableWithExtraSlashes() throws Exception { @@ -96,8 +96,8 @@ public class ProcessListTest extends UsefulTestCase { " 2 S user //" + myDir + "//dir//file// aaa bbb\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, "//" + myDir + "//dir//file//", "", "user", "S"), - new ProcessInfo(2, "//" + myDir + "//dir//file//", "aaa bbb", "user", "S")); + new ProcessInfo(1, "//" + myDir + "//dir//file//", "file", "", "user", "S"), + new ProcessInfo(2, "//" + myDir + "//dir//file// aaa bbb", "file", "aaa bbb", "user", "S")); } public void testUnix_VariousFormsPidStatUser() throws Exception { @@ -108,8 +108,8 @@ public class ProcessListTest extends UsefulTestCase { " 101 Ss user_name " + myDir + "/dir/file\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), - new ProcessInfo(101, myDir + "/dir/file", "", "user_name", "Ss")); + new ProcessInfo(1, myDir + "/dir/file", "file", "", "user", "S"), + new ProcessInfo(101, myDir + "/dir/file", "file", "", "user_name", "Ss")); } public void testUnix_WrongFormat() throws Exception { @@ -163,8 +163,8 @@ public class ProcessListTest extends UsefulTestCase { " 2 S user " + myDir + "/dir/dir/file\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, myDir + "/dir/file", "", "user", "S"), - new ProcessInfo(2, myDir + "/dir/dir/file", "", "user", "S")); + new ProcessInfo(1, myDir + "/dir/file", "file", "", "user", "S"), + new ProcessInfo(2, myDir + "/dir/dir/file", "file", "", "user", "S")); } public void testMac_DoNotIncludeZombies() throws Exception { @@ -176,7 +176,7 @@ public class ProcessListTest extends UsefulTestCase { " 3 SZ user " + myDir + "/dir/file\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, myDir + "/dir/file", "", "user", "S")); + new ProcessInfo(1, myDir + "/dir/file", "file", "", "user", "S")); } public void testWindows_WMIC() throws Exception { @@ -189,12 +189,12 @@ public class ProcessListTest extends UsefulTestCase { "TPAutoConnect.exe TPAutoConnect.exe -q -i vmware -a COM1 -F 30 3336 \n" + "conhost.exe \\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4 3348 \n"); assertOrderedEquals(infos, - new ProcessInfo(304, "smss.exe", "", null, null), - new ProcessInfo(3052, "sihost.exe", "", null, null), - new ProcessInfo(3068, "taskhostw.exe", "{222A245B-E637-4AE9-A93F-A59CA119A75E}", null, null), - new ProcessInfo(3164, "explorer.exe", "", null, null), - new ProcessInfo(3336, "TPAutoConnect.exe", "-q -i vmware -a COM1 -F 30", null, null), - new ProcessInfo(3348, "conhost.exe", "0x4", null, null)); + new ProcessInfo(304, "smss.exe", "smss.exe", "", null, null), + new ProcessInfo(3052, "sihost.exe", "sihost.exe", "", null, null), + new ProcessInfo(3068, "taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E}", "taskhostw.exe", "{222A245B-E637-4AE9-A93F-A59CA119A75E}", null, null), + new ProcessInfo(3164, "C:\\WINDOWS\\Explorer.EXE", "explorer.exe", "", null, null), + new ProcessInfo(3336, "TPAutoConnect.exe -q -i vmware -a COM1 -F 30", "TPAutoConnect.exe", "-q -i vmware -a COM1 -F 30", null, null), + new ProcessInfo(3348, "\\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4", "conhost.exe", "0x4", null, null)); } public void testOnWindows_WMIC_DoNotIncludeSystemIdleProcess() throws Exception { @@ -204,8 +204,8 @@ public class ProcessListTest extends UsefulTestCase { "System 4 \n" + "smss.exe 304 \n"); assertOrderedEquals(infos, - new ProcessInfo(4, "System", "", null, null), - new ProcessInfo(304, "smss.exe", "", null, null)); + new ProcessInfo(4, "System", "System", "", null, null), + new ProcessInfo(304, "smss.exe", "smss.exe", "", null, null)); } public void testWindows_WMIC_WrongFormat() throws Exception { @@ -238,12 +238,12 @@ public class ProcessListTest extends UsefulTestCase { "\"TPAutoConnect.exe\",\"3336\",\"Console\",\"1\",\"5,508 K\",\"Running\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:04\",\"HiddenTPAutoConnectWindow\"\n" + "\"conhost.exe\",\"3348\",\"Console\",\"1\",\"1,172 K\",\"Unknown\",\"VM-WINDOWS\\Anton Makeev\",\"0:00:00\",\"N/A\"\n"); assertOrderedEquals(infos, - new ProcessInfo(304, "smss.exe", "", null, null), - new ProcessInfo(3052, "sihost.exe", "", null, null), - new ProcessInfo(3068, "taskhostw.exe", "", null, null), - new ProcessInfo(3164, "explorer.exe", "", null, null), - new ProcessInfo(3336, "TPAutoConnect.exe", "", null, null), - new ProcessInfo(3348, "conhost.exe", "", null, null)); + new ProcessInfo(304, "smss.exe", "smss.exe", "", null, null), + new ProcessInfo(3052, "sihost.exe", "sihost.exe", "", null, null), + new ProcessInfo(3068, "taskhostw.exe", "taskhostw.exe", "", null, null), + new ProcessInfo(3164, "explorer.exe", "explorer.exe", "", null, null), + new ProcessInfo(3336, "TPAutoConnect.exe", "TPAutoConnect.exe", "", null, null), + new ProcessInfo(3348, "conhost.exe", "conhost.exe", "", null, null)); } public void testWindows_TaskList_WrongFormat() throws Exception { diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index de7b2213aecb..cc973cb81b49 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1070,6 +1070,14 @@ public class StringUtil extends StringUtilRt { return string.subSequence(0, index + 1); } + @NotNull + @Contract(pure = true) + public static String trimTrailing(@NotNull String string, char symbol) { + int index = string.length() - 1; + while (index >= 0 && string.charAt(index) == symbol) index--; + return string.substring(0, index + 1); + } + @Contract(pure = true) public static boolean startsWithChar(@Nullable CharSequence s, char prefix) { return s != null && s.length() != 0 && s.charAt(0) == prefix; diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 7b0e078eeecb..06030156f4f3 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -31,6 +31,24 @@ import static org.junit.Assert.*; * @since Dec 22, 2006 */ public class StringUtilTest { + @Test + public void testTrimLeadingChar() throws Exception { + assertEquals("", StringUtil.trimLeading("", ' ')); + assertEquals("", StringUtil.trimLeading(" ", ' ')); + assertEquals("", StringUtil.trimLeading(" ", ' ')); + assertEquals("a ", StringUtil.trimLeading("a ", ' ')); + assertEquals("a ", StringUtil.trimLeading(" a ", ' ')); + } + + @Test + public void testTrimTrailingChar() throws Exception { + assertEquals("", StringUtil.trimTrailing("", ' ')); + assertEquals("", StringUtil.trimTrailing(" ", ' ')); + assertEquals("", StringUtil.trimTrailing(" ", ' ')); + assertEquals(" a", StringUtil.trimTrailing(" a", ' ')); + assertEquals(" a", StringUtil.trimTrailing(" a ", ' ')); + } + @Test public void testToUpperCase() { assertEquals('/', StringUtil.toUpperCase('/')); From fb6f94dda013cbc5e7602e6455d112bc31ef09ab Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 21:05:33 +0100 Subject: [PATCH 017/825] IDEA-149798 Extensible Attach to Local Process action: group process, show icons, + tests --- .../attach/XDefaultLocalAttachGroup.java | 53 +++ .../attach/XLocalAttachDebuggerProvider.java | 8 + .../xdebugger/attach/XLocalAttachGroup.java | 39 ++ .../actions/AttachToLocalProcessAction.java | 113 ++++-- .../AttachToLocalProcessActionTest.java | 367 ++++++++++++++++++ 5 files changed, 556 insertions(+), 24 deletions(-) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XDefaultLocalAttachGroup.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachGroup.java create mode 100644 platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XDefaultLocalAttachGroup.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XDefaultLocalAttachGroup.java new file mode 100644 index 000000000000..d3bbeacb6d6f --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XDefaultLocalAttachGroup.java @@ -0,0 +1,53 @@ +/* + * 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. + */ +package com.intellij.xdebugger.attach; + +import com.intellij.execution.process.ProcessInfo; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public class XDefaultLocalAttachGroup implements XLocalAttachGroup { + @Override + public int getOrder() { + return 0; + } + + @NotNull + @Override + public String getGroupName() { + return ""; + } + + @NotNull + @Override + public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info) { + return AllIcons.RunConfigurations.Application; + } + + @NotNull + @Override + public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) { + return info.getExecutableDisplayName(); + } + + @Override + public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) { + return a.getPid() - b.getPid(); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java index 63cae7c3a2a9..6989c9329039 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachDebuggerProvider.java @@ -26,6 +26,14 @@ import java.util.List; public interface XLocalAttachDebuggerProvider { ExtensionPointName EP = ExtensionPointName.create("com.intellij.xdebugger.localAttachDebuggerProvider"); + /** + * @return a group in which the supported processes should be visually organized. + * Return XLocalAttachGroup.DEFAULT for a common group. + * + */ + @NotNull + XLocalAttachGroup getAttachGroup(); + /** * Attach to Local Process action invokes {@link #getAvailableDebuggers} method for every running process. * {@link XLocalAttachDebuggerProvider} should return a list of the debuggers that can attach and debug a given process. diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachGroup.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachGroup.java new file mode 100644 index 000000000000..937a5743ce45 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/attach/XLocalAttachGroup.java @@ -0,0 +1,39 @@ +/* + * 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. + */ +package com.intellij.xdebugger.attach; + +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public interface XLocalAttachGroup { + int getOrder(); + + @NotNull + String getGroupName(); + + @NotNull + Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info); + + @NotNull + String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info); + + int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b); + + XLocalAttachGroup DEFAULT = new XDefaultLocalAttachGroup(); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 6a568ea672b5..e66b3c20eb8e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -23,20 +23,20 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.ui.popup.ListPopup; -import com.intellij.openapi.ui.popup.ListPopupStepEx; -import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.StatusText; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.attach.XLocalAttachDebugger; import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import com.intellij.xdebugger.attach.XLocalAttachGroup; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,9 +45,7 @@ import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.event.InputEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; public class AttachToLocalProcessAction extends AnAction { public AttachToLocalProcessAction() { @@ -69,7 +67,10 @@ public class AttachToLocalProcessAction extends AnAction { final Project project = getEventProject(e); if (project == null) return; - MyPopupStep step = new MyPopupStep(collectAttachItems(project), project); + ProcessInfo[] processList = OSProcessManagerImpl.getProcessList(); + XLocalAttachDebuggerProvider[] providers = Extensions.getExtensions(XLocalAttachDebuggerProvider.EP); + + MyPopupStep step = new MyPopupStep(collectAttachItems(project, processList, providers), project); final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step); final JList mainList = ((ListPopupImpl)popup).getList(); @@ -102,37 +103,79 @@ public class AttachToLocalProcessAction extends AnAction { } @NotNull - private static List collectAttachItems(@NotNull Project project) { - List result = new ArrayList(); - + public static List collectAttachItems(@NotNull final Project project, + @NotNull ProcessInfo[] processList, + @NotNull XLocalAttachDebuggerProvider... providers) { + MultiMap>> groupWithItems + = new MultiMap>>(); + UserDataHolderBase dataHolder = new UserDataHolderBase(); - for (ProcessInfo eachInfo : OSProcessManagerImpl.getProcessList()) { - List availableDebuggers = new ArrayList(); - for (XLocalAttachDebuggerProvider eachProvider : Extensions.getExtensions(XLocalAttachDebuggerProvider.EP)) { - availableDebuggers.addAll(eachProvider.getAvailableDebuggers(project, eachInfo, dataHolder)); + for (ProcessInfo eachInfo : processList) { + + MultiMap groupsWithDebuggers = new MultiMap(); + for (XLocalAttachDebuggerProvider eachProvider : providers) { + groupsWithDebuggers.putValues(eachProvider.getAttachGroup(), eachProvider.getAvailableDebuggers(project, eachInfo, dataHolder)); } - if (!availableDebuggers.isEmpty()) { - result.add(new AttachItem(eachInfo, availableDebuggers)); + + for (XLocalAttachGroup eachGroup : groupsWithDebuggers.keySet()) { + Collection debuggers = groupsWithDebuggers.get(eachGroup); + if (!debuggers.isEmpty()) { + groupWithItems.putValue(eachGroup, Pair.create(eachInfo, new ArrayList(debuggers))); + } } } + + ArrayList sortedGroups = new ArrayList(groupWithItems.keySet()); + Collections.sort(sortedGroups, new Comparator() { + @Override + public int compare(XLocalAttachGroup a, XLocalAttachGroup b) { + return a.getOrder() - b.getOrder(); + } + }); + + List result = new ArrayList(); + for (final XLocalAttachGroup eachGroup : sortedGroups) { + List>> sortedItems + = new ArrayList>>(groupWithItems.get(eachGroup)); + Collections.sort(sortedItems, new Comparator>>() { + @Override + public int compare(Pair> a, Pair> b) { + return eachGroup.compare(project, a.first, b.first); + } + }); + + boolean first = true; + for (Pair> eachItem : sortedItems) { + result.add(new AttachItem(eachGroup, first, eachItem.first, eachItem.second)); + first = false; + } + } + return result; } public static class AttachItem { + @NotNull private final XLocalAttachGroup myGroup; + private final boolean myIsFirstInGroup; @NotNull private final ProcessInfo myProcessInfo; @NotNull private final List myDebuggers; @NotNull private final List mySubItems; - public AttachItem(@NotNull ProcessInfo info, @NotNull List debuggers) { + public AttachItem(@NotNull XLocalAttachGroup group, + boolean isFirstInGroup, + @NotNull ProcessInfo info, + @NotNull List debuggers) { assert !debuggers.isEmpty(); - this.myProcessInfo = info; - this.myDebuggers = debuggers; + myGroup = group; + myIsFirstInGroup = isFirstInGroup; + myProcessInfo = info; + myDebuggers = debuggers; if (debuggers.size() > 1) { mySubItems = ContainerUtil.map(debuggers, new Function() { @Override public AttachItem fun(XLocalAttachDebugger debugger) { - return new AttachItem(myProcessInfo, Collections.singletonList(debugger)); + return new AttachItem(myGroup, false, myProcessInfo, Collections.singletonList(debugger)); } }); } @@ -142,8 +185,18 @@ public class AttachToLocalProcessAction extends AnAction { } @Nullable - public Icon getIcon() { - return null; + public String getSeparatorTitle() { + return myIsFirstInGroup ? myGroup.getGroupName() : null; + } + + @Nullable + public Icon getIcon(@NotNull Project project) { + return myGroup.getProcessIcon(project, myProcessInfo); + } + + @NotNull + public String getText(@NotNull Project project) { + return myProcessInfo.getPid() + " " + myGroup.getProcessDisplayText(project, myProcessInfo); } @NotNull @@ -184,10 +237,22 @@ public class AttachToLocalProcessAction extends AnAction { return false; } + @Nullable + @Override + public ListSeparator getSeparatorAbove(AttachItem value) { + String separatorTitle = value.getSeparatorTitle(); + return separatorTitle == null ? null : new ListSeparator(separatorTitle); + } + + @Override + public Icon getIconFor(AttachItem value) { + return value.getIcon(myProject); + } + @NotNull @Override public String getTextFor(AttachItem value) { - return value.myProcessInfo.getPid() + " " + value.myProcessInfo.getExecutableDisplayName(); + return value.getText(myProject); } @Override diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java new file mode 100644 index 000000000000..097850b69360 --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java @@ -0,0 +1,367 @@ +/* + * 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. + */ +package com.intellij.xdebugger.impl.actions; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.UserDataHolder; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.attach.XDefaultLocalAttachGroup; +import com.intellij.xdebugger.attach.XLocalAttachDebugger; +import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import com.intellij.xdebugger.attach.XLocalAttachGroup; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.intellij.xdebugger.impl.actions.AttachToLocalProcessAction.AttachItem; +import static com.intellij.xdebugger.impl.actions.AttachToLocalProcessAction.collectAttachItems; + +public class AttachToLocalProcessActionTest extends PlatformTestCase { + public void testCollectingAttachItems_Empty() throws Exception { + // no providers + assertItems(""); + + // no provided debuggers + assertItems("", new TestDebuggerProvider(), new TestDebuggerProvider()); + } + + public void testCollectingAttachItems_OneDebugger() throws Exception { + Project project = ProjectManager.getInstance().getDefaultProject(); + + assertItems("--------\n" + + "1 exec1: dbg\n" + + "2 exec2: dbg\n", + new TestDebuggerProvider("dbg")); + } + + public void testCollectingAttachItems_DebuggerPerProcess() throws Exception { + // from one provider + assertItems("--------\n" + + "1 exec1: dbg1\n" + + "2 exec2: dbg2\n", + new TestDebuggerProvider("dbg1") { + @NotNull + @Override + public List getAvailableDebuggers(@NotNull Project project, + @NotNull ProcessInfo processInfo, + @NotNull UserDataHolder contextHolder) { + if (processInfo.getPid() != 1) return Collections.emptyList(); + return super.getAvailableDebuggers(project, processInfo, contextHolder); + } + }, + new TestDebuggerProvider("dbg2") { + @NotNull + @Override + public List getAvailableDebuggers(@NotNull Project project, + @NotNull ProcessInfo processInfo, + @NotNull UserDataHolder contextHolder) { + if (processInfo.getPid() != 2) return Collections.emptyList(); + return super.getAvailableDebuggers(project, processInfo, contextHolder); + } + }); + } + + public void testCollectingAttachItems_SeveralDebuggers() throws Exception { + // from one provider + assertItems("--------\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + " dbg3\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + " dbg3\n", + new TestDebuggerProvider("dbg1", "dbg2", "dbg3")); + + // from several providers + assertItems("--------\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + " dbg3\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + " dbg3\n", + new TestDebuggerProvider("dbg1"), + new TestDebuggerProvider("dbg2", "dbg3")); + + // keep order + assertItems("--------\n" + + "1 exec1: dbg3\n" + + " dbg3\n" + + " dbg2\n" + + " dbg1\n" + + "2 exec2: dbg3\n" + + " dbg3\n" + + " dbg2\n" + + " dbg1\n", + new TestDebuggerProvider("dbg3"), + new TestDebuggerProvider("dbg2", "dbg1")); + + // several debuggers with same display name + assertItems("--------\n" + + "1 exec1: dbg\n" + + " dbg\n" + + " dbg\n" + + " dbg\n" + + "2 exec2: dbg\n" + + " dbg\n" + + " dbg\n" + + " dbg\n", + new TestDebuggerProvider("dbg", "dbg"), + new TestDebuggerProvider("dbg")); + } + + public void testCollectingAttachItems_Groups() throws Exception { + // one group + assertItems("----group----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(new TestAttachGroup("group", 0), "dbg1", "dbg2")); + + // merging same group + TestAttachGroup group = new TestAttachGroup("group", 0); + assertItems("----group----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(group, "dbg1"), + new TestDebuggerProvider(group, "dbg2")); + + assertItems("--------\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "--------\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(XLocalAttachGroup.DEFAULT, "dbg1", "dbg2"), + new TestDebuggerProvider(new TestAttachGroup("", 1), "dbg1", "dbg2")); + } + + public void testCollectingAttachItems_Groups_SortingGroups() throws Exception { + assertItems("----group1----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "----group2----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(new TestAttachGroup("group1", 1), "dbg1", "dbg2"), + new TestDebuggerProvider(new TestAttachGroup("group2", 2), "dbg1", "dbg2")); + assertItems("----group2----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "----group1----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(new TestAttachGroup("group1", 2), "dbg1", "dbg2"), + new TestDebuggerProvider(new TestAttachGroup("group2", 1), "dbg1", "dbg2")); + + // sorting with default group + assertItems("----group2----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "--------\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "----group1----\n" + + "1 exec1: dbg1\n" + + " dbg1\n" + + " dbg2\n" + + "2 exec2: dbg1\n" + + " dbg1\n" + + " dbg2\n", + new TestDebuggerProvider(XLocalAttachGroup.DEFAULT, "dbg1", "dbg2"), + new TestDebuggerProvider(new TestAttachGroup("group1", 1), "dbg1", "dbg2"), + new TestDebuggerProvider(new TestAttachGroup("group2", -1), "dbg1", "dbg2")); + } + + public void testCollectingAttachItems_Groups_SortingItems() throws Exception { + assertItems("----group----\n" + + "1 exec1: dbg1\n" + + "2 exec2: dbg1\n", + new TestDebuggerProvider(new TestAttachGroup("group", 0) { + @Override + public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) { + return a.getPid() - b.getPid(); + } + }, "dbg1")); + assertItems("----group----\n" + + "2 exec2: dbg1\n" + + "1 exec1: dbg1\n", + new TestDebuggerProvider(new TestAttachGroup("group", 0) { + @Override + public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) { + return b.getPid() - a.getPid(); + } + }, "dbg1")); + } + + public void testCollectingAttachItems_Groups_CustomItemTitles() throws Exception { + assertItems("----group----\n" + + "1 custom: dbg1\n" + + "2 custom: dbg1\n", + new TestDebuggerProvider(new TestAttachGroup("group", 0) { + @NotNull + @Override + public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) { + return "custom"; + } + }, "dbg1")); + } + + private static void assertItems(String expected, @NotNull XLocalAttachDebuggerProvider... providers) { + Project project = ProjectManager.getInstance().getDefaultProject(); + assertEquals(expected, printItems(project, collectAttachItems(project, getProcessList(), providers))); + } + + private static String printItems(Project project, List items) { + StringBuilder builder = new StringBuilder(); + + for (AttachItem each : items) { + String title = each.getSeparatorTitle(); + if (title != null) builder.append("----").append(title).append("----\n"); + builder.append(each.getText(project)).append(": ").append(each.getSelectedDebugger().getDebuggerDisplayName()).append("\n"); + for (AttachItem eachSubItem : each.getSubItems()) { + builder.append(" ").append(eachSubItem.getSelectedDebugger().getDebuggerDisplayName()).append("\n"); + } + } + + return builder.toString(); + } + + private static ProcessInfo[] getProcessList() { + return new ProcessInfo[]{ + new ProcessInfo(1, "command line 1", "exec1", "args1", null, null), + new ProcessInfo(2, "command line 2", "exec2", "args2", null, null), + }; + } + + private static class TestAttachGroup extends XDefaultLocalAttachGroup { + @Nullable String myName; + @Nullable Integer myOrder; + + public TestAttachGroup(@Nullable String name, @Nullable Integer order) { + myName = name; + myOrder = order; + } + + @Override + public int getOrder() { + return myOrder != null ? myOrder : super.getOrder(); + } + + @NotNull + @Override + public String getGroupName() { + return myName != null ? myName : super.getGroupName(); + } + } + + private static class TestDebuggerProvider implements XLocalAttachDebuggerProvider { + XLocalAttachGroup myGroup; + List myNames; + + public TestDebuggerProvider(XLocalAttachGroup group, String... names) { + myGroup = group; + myNames = Arrays.asList(names); + } + + public TestDebuggerProvider(String... names) { + this(XLocalAttachGroup.DEFAULT, names); + } + + @NotNull + @Override + public XLocalAttachGroup getAttachGroup() { + return myGroup; + } + + @NotNull + @Override + public List getAvailableDebuggers(@NotNull Project project, + @NotNull ProcessInfo processInfo, + @NotNull UserDataHolder contextHolder) { + return ContainerUtil.map(myNames, new Function() { + @Override + public XLocalAttachDebugger fun(final String s) { + return new XLocalAttachDebugger() { + @NotNull + @Override + public String getDebuggerDisplayName() { + return s; + } + + @NotNull + @Override + public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException { + return null; + } + }; + } + }); + } + } +} \ No newline at end of file From 513d7a0dd21ef2acbd8384c511a153aa00fb4cbb Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 1 Jan 2016 22:01:13 +0100 Subject: [PATCH 018/825] IDEA-149798 Extensible Attach to Local Process action: group process, show icons, + tests + IDEA-149825 Reuse platform 'Attach to Local Process' action in PyCharm --- .../attach/PyLocalAttachDebuggerProvider.java | 7 +++ .../debugger/attach/PyLocalAttachGroup.java | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 python/src/com/jetbrains/python/debugger/attach/PyLocalAttachGroup.java diff --git a/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java index 6b022927dd73..7f0cabb2b9c2 100644 --- a/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java +++ b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachDebuggerProvider.java @@ -27,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.attach.XLocalAttachDebugger; import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider; +import com.intellij.xdebugger.attach.XLocalAttachGroup; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -37,6 +38,12 @@ import java.util.List; public class PyLocalAttachDebuggerProvider implements XLocalAttachDebuggerProvider { private static final Key> DEBUGGERS_KEY = Key.create("PyLocalAttachDebuggerProvider.DEBUGGERS"); + @NotNull + @Override + public XLocalAttachGroup getAttachGroup() { + return PyLocalAttachGroup.INSTANCE; + } + @NotNull @Override public List getAvailableDebuggers(@NotNull Project project, diff --git a/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachGroup.java b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachGroup.java new file mode 100644 index 000000000000..bc54877a44fb --- /dev/null +++ b/python/src/com/jetbrains/python/debugger/attach/PyLocalAttachGroup.java @@ -0,0 +1,58 @@ +/* + * 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. + */ +package com.jetbrains.python.debugger.attach; + +import com.intellij.execution.process.ProcessInfo; +import com.intellij.openapi.project.Project; +import com.intellij.xdebugger.attach.XLocalAttachGroup; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +class PyLocalAttachGroup implements XLocalAttachGroup { + public static final PyLocalAttachGroup INSTANCE = new PyLocalAttachGroup(); + + private PyLocalAttachGroup() { + } + + @Override + public int getOrder() { + return XLocalAttachGroup.DEFAULT.getOrder() - 10; + } + + @NotNull + @Override + public String getGroupName() { + return "Python"; + } + + @NotNull + @Override + public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info) { + return icons.PythonIcons.Python.Python; + } + + @NotNull + @Override + public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) { + return info.getArgs(); + } + + @Override + public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) { + return XLocalAttachGroup.DEFAULT.compare(project, a, b); + } +} From 95685cfe93a6c1f05fd138cda5d9861ed6580d69 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Sat, 2 Jan 2016 13:47:09 +0100 Subject: [PATCH 019/825] IDEA-149798 Extensible Attach to Local Process action: usage stats --- .../impl/actions/AttachToLocalProcessAction.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index e66b3c20eb8e..f7ce3047ce7c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -19,6 +19,8 @@ import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessInfo; import com.intellij.execution.process.impl.OSProcessManagerImpl; import com.intellij.execution.runners.ExecutionUtil; +import com.intellij.internal.statistic.UsageTrigger; +import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.extensions.Extensions; @@ -210,8 +212,12 @@ public class AttachToLocalProcessAction extends AnAction { } public void startDebugSession(@NotNull Project project) { + XLocalAttachDebugger debugger = getSelectedDebugger(); + UsageTrigger.trigger(ConvertUsagesUtil.ensureProperKey("debugger.attach.local")); + UsageTrigger.trigger(ConvertUsagesUtil.ensureProperKey("debugger.attach.local." + debugger.getDebuggerDisplayName())); + try { - getSelectedDebugger().attachDebugSession(project, myProcessInfo); + debugger.attachDebugSession(project, myProcessInfo); } catch (ExecutionException e) { ExecutionUtil.handleExecutionError(project, ToolWindowId.DEBUG, myProcessInfo.getExecutableName(), e); From d5a0732d7f930fc5a02c05fc88dda406563140c1 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 8 Jan 2016 18:03:34 +0100 Subject: [PATCH 020/825] IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths: unified unix-part --- .../com/intellij/execution/process/impl/ProcessListUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index af890df91447..e259b19b0605 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -60,7 +60,7 @@ class ProcessListUtil { LOG.error("Cannot get process list via wmic and tasklist"); } - else if (SystemInfo.isLinux || SystemInfo.isMac) { + else if (SystemInfo.isUnix) { result = getProcessList_Unix(SystemInfo.isMac); if (result != null) return result; From 6dad86a9564efab94bd9be2f63198c1f2ee1c6a9 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 8 Jan 2016 18:03:34 +0100 Subject: [PATCH 021/825] IDEA-149017 Process list implementation does not provide correct executable names for applications with spaces in their paths: unified unix-part --- .../execution/process/impl/ProcessListUtil.java | 10 +++++----- .../execution/process/impl/ProcessListTest.java | 14 -------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index e259b19b0605..d70acd77c201 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -61,7 +61,7 @@ class ProcessListUtil { LOG.error("Cannot get process list via wmic and tasklist"); } else if (SystemInfo.isUnix) { - result = getProcessList_Unix(SystemInfo.isMac); + result = getProcessList_Unix(); if (result != null) return result; LOG.error("Cannot get process list"); @@ -86,19 +86,19 @@ class ProcessListUtil { } @Nullable - private static List getProcessList_Unix(final boolean isMac) { + private static List getProcessList_Unix() { return parseCommandOutput(Arrays.asList("/bin/ps", "-a", "-x", "-o", "pid,state,user,command"), new NullableFunction>() { @Nullable @Override public List fun(String output) { - return parseUnixOutput(isMac, output); + return parseUnixOutput(output); } }); } @Nullable - static List parseUnixOutput(boolean isMac, @NotNull String output) { + static List parseUnixOutput(@NotNull String output) { List result = ContainerUtil.newArrayList(); String[] lines = StringUtil.splitByLinesDontTrim(output); if (lines.length == 0) return null; @@ -107,7 +107,7 @@ class ProcessListUtil { int pidStart = header.indexOf("PID"); if (pidStart == -1) return null; - int statStart = header.indexOf(isMac ? "STAT" : "S", pidStart); + int statStart = header.indexOf("S", pidStart); if (statStart == -1) return null; int userStart = header.indexOf("USER", statStart); diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index 8aa7f9daff93..6773c6d08be5 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -59,7 +59,6 @@ public class ProcessListTest extends UsefulTestCase { public void testUnix_DetermineExecutable() throws Exception { List infos = ProcessListUtil.parseUnixOutput( - false, " PID S USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + " 2 S user " + myDir + "/dir/dir/file\n" + @@ -90,7 +89,6 @@ public class ProcessListTest extends UsefulTestCase { public void testUnix_DetermineExecutableWithExtraSlashes() throws Exception { List infos = ProcessListUtil.parseUnixOutput( - false, " PID S USER COMMAND\n\n" + " 1 S user //" + myDir + "//dir//file//\n" + " 2 S user //" + myDir + "//dir//file// aaa bbb\n" @@ -102,7 +100,6 @@ public class ProcessListTest extends UsefulTestCase { public void testUnix_VariousFormsPidStatUser() throws Exception { List infos = ProcessListUtil.parseUnixOutput( - true, " PID STAT USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + " 101 Ss user_name " + myDir + "/dir/file\n" @@ -114,42 +111,33 @@ public class ProcessListTest extends UsefulTestCase { public void testUnix_WrongFormat() throws Exception { assertNull(ProcessListUtil.parseUnixOutput( - false, "" )); assertNull(ProcessListUtil.parseUnixOutput( - false, "wrong format")); assertEmpty(ProcessListUtil.parseUnixOutput( - false, " PID S USER COMMAND\n\n" )); assertEmpty(ProcessListUtil.parseUnixOutput( - false, " PID S USER COMMAND\n\n" + " \n" )); assertNull(ProcessListUtil.parseUnixOutput( - false, " 1 S user " + myDir + "/dir/file\n" )); assertNull(ProcessListUtil.parseUnixOutput( - false, " PID S USER XXX\n\n" + " 1 S user " + myDir + "/dir/file\n" )); assertNull(ProcessListUtil.parseUnixOutput( - false, " PID S XXX COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); assertNull(ProcessListUtil.parseUnixOutput( - false, " PID X USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); assertNull(ProcessListUtil.parseUnixOutput( - false, " XXX S USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" )); @@ -157,7 +145,6 @@ public class ProcessListTest extends UsefulTestCase { public void testMac() throws Exception { List infos = ProcessListUtil.parseUnixOutput( - true, " PID STAT USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + " 2 S user " + myDir + "/dir/dir/file\n" @@ -169,7 +156,6 @@ public class ProcessListTest extends UsefulTestCase { public void testMac_DoNotIncludeZombies() throws Exception { List infos = ProcessListUtil.parseUnixOutput( - true, " PID STAT USER COMMAND\n\n" + " 1 S user " + myDir + "/dir/file\n" + " 2 Z user " + myDir + "/dir/file\n" + From db0fadef37c94434811a0734dc3bdeedf906607f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 11 Jan 2016 15:25:17 +0100 Subject: [PATCH 022/825] IDEA-149798 Extensible Attach to Local Process action: history --- .../actions/AttachToLocalProcessAction.java | 161 ++++++++++++++---- .../AttachToLocalProcessActionTest.java | 115 ++++++++++--- 2 files changed, 219 insertions(+), 57 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index f7ce3047ce7c..3cebd488f2fe 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -27,6 +27,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.wm.ToolWindowId; @@ -34,6 +35,7 @@ import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.ui.StatusText; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.attach.XLocalAttachDebugger; @@ -50,6 +52,8 @@ import java.awt.event.InputEvent; import java.util.*; public class AttachToLocalProcessAction extends AnAction { + private static final Key> HISTORY_KEY = Key.create("AttachToLocalProcessAction.HISTORY_KEY"); + public AttachToLocalProcessAction() { super(XDebuggerBundle.message("xdebugger.attach.toLocal.action"), XDebuggerBundle.message("xdebugger.attach.toLocal.action.description"), null); @@ -71,8 +75,8 @@ public class AttachToLocalProcessAction extends AnAction { ProcessInfo[] processList = OSProcessManagerImpl.getProcessList(); XLocalAttachDebuggerProvider[] providers = Extensions.getExtensions(XLocalAttachDebuggerProvider.EP); - - MyPopupStep step = new MyPopupStep(collectAttachItems(project, processList, providers), project); + + ProcessListStep step = new ProcessListStep(collectAttachItems(project, processList, providers), project); final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step); final JList mainList = ((ListPopupImpl)popup).getList(); @@ -156,6 +160,77 @@ public class AttachToLocalProcessAction extends AnAction { return result; } + public static void addToHistory(@NotNull Project project, @NotNull AttachItem item) { + LinkedHashMap history = project.getUserData(HISTORY_KEY); + if (history == null) { + project.putUserData(HISTORY_KEY, history = new LinkedHashMap()); + } + ProcessInfo processInfo = item.getProcessInfo(); + history.remove(processInfo.getCommandLine()); + history.put(processInfo.getCommandLine(), new HistoryItem(processInfo, item.getGroup(), item.getSelectedDebugger())); + while (history.size() > 4) { + history.remove(history.keySet().iterator().next()); + } + } + + @NotNull + public static List getHistory(@NotNull Project project) { + LinkedHashMap history = project.getUserData(HISTORY_KEY); + return history == null ? Collections.emptyList() + : Collections.unmodifiableList(new ArrayList(history.values())); + } + + public static class HistoryItem { + @NotNull private final ProcessInfo myProcessInfo; + @NotNull private final XLocalAttachGroup myGroup; + @NotNull private final XLocalAttachDebugger myDebugger; + + public HistoryItem(@NotNull ProcessInfo processInfo, + @NotNull XLocalAttachGroup group, + @NotNull XLocalAttachDebugger debugger) { + myProcessInfo = processInfo; + myGroup = group; + myDebugger = debugger; + } + + @NotNull + public ProcessInfo getProcessInfo() { + return myProcessInfo; + } + + @NotNull + public XLocalAttachGroup getGroup() { + return myGroup; + } + + @NotNull + public XLocalAttachDebugger getDebugger() { + return myDebugger; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + HistoryItem item = (HistoryItem)o; + + if (!myProcessInfo.equals(item.myProcessInfo)) return false; + if (!myGroup.equals(item.myGroup)) return false; + if (!myDebugger.equals(item.myDebugger)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myProcessInfo.hashCode(); + result = 31 * result + myGroup.hashCode(); + result = 31 * result + myDebugger.hashCode(); + return result; + } + } + public static class AttachItem { @NotNull private final XLocalAttachGroup myGroup; private final boolean myIsFirstInGroup; @@ -173,6 +248,7 @@ public class AttachToLocalProcessAction extends AnAction { myIsFirstInGroup = isFirstInGroup; myProcessInfo = info; myDebuggers = debuggers; + if (debuggers.size() > 1) { mySubItems = ContainerUtil.map(debuggers, new Function() { @Override @@ -186,6 +262,16 @@ public class AttachToLocalProcessAction extends AnAction { } } + @NotNull + public ProcessInfo getProcessInfo() { + return myProcessInfo; + } + + @NotNull + public XLocalAttachGroup getGroup() { + return myGroup; + } + @Nullable public String getSeparatorTitle() { return myIsFirstInGroup ? myGroup.getGroupName() : null; @@ -225,11 +311,13 @@ public class AttachToLocalProcessAction extends AnAction { } } - private static class MyPopupStep extends BaseListPopupStep implements ListPopupStepEx { - @NotNull private final Project myProject; + private static class MyBasePopupStep extends BaseListPopupStep { + @NotNull final Project myProject; - public MyPopupStep(@NotNull List items, @NotNull Project project) { - super(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items); + public MyBasePopupStep(@NotNull Project project, + @Nullable String title, + List values) { + super(title, values); myProject = project; } @@ -243,6 +331,24 @@ public class AttachToLocalProcessAction extends AnAction { return false; } + @Override + public boolean hasSubstep(AttachItem selectedValue) { + return !selectedValue.getSubItems().isEmpty(); + } + + @Override + public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { + addToHistory(myProject, selectedValue); + selectedValue.startDebugSession(myProject); + return FINAL_CHOICE; + } + } + + private static class ProcessListStep extends MyBasePopupStep implements ListPopupStepEx { + public ProcessListStep(@NotNull List items, @NotNull Project project) { + super(project, XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items); + } + @Nullable @Override public ListSeparator getSeparatorAbove(AttachItem value) { @@ -261,11 +367,6 @@ public class AttachToLocalProcessAction extends AnAction { return value.getText(myProject); } - @Override - public boolean hasSubstep(AttachItem selectedValue) { - return !selectedValue.getSubItems().isEmpty(); - } - @Nullable @Override public String getTooltipTextFor(AttachItem value) { @@ -277,33 +378,12 @@ public class AttachToLocalProcessAction extends AnAction { emptyText.setText(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.emptyText")); } - @Override public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { if (finalChoice) { - selectedValue.startDebugSession(myProject); - return FINAL_CHOICE; + return super.onChosen(selectedValue, true); } - - return new BaseListPopupStep(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.selectDebugger.title"), - selectedValue.getSubItems()) { - @Override - public boolean isSpeedSearchEnabled() { - return true; - } - - @NotNull - @Override - public String getTextFor(AttachItem value) { - return value.getSelectedDebugger().getDebuggerDisplayName(); - } - - @Override - public PopupStep onChosen(AttachItem selectedValue, boolean finalChoice) { - selectedValue.startDebugSession(myProject); - return FINAL_CHOICE; - } - }; + return new DebuggerListStep(selectedValue); } @Override @@ -312,5 +392,18 @@ public class AttachToLocalProcessAction extends AnAction { @MagicConstant(flagsFromClass = InputEvent.class) int eventModifiers) { return onChosen(selectedValue, finalChoice); } + + private class DebuggerListStep extends MyBasePopupStep { + public DebuggerListStep(AttachItem selectedValue) { + super(ProcessListStep.this.myProject, + XDebuggerBundle.message("xdebugger.attach.toLocal.popup.selectDebugger.title"), selectedValue.getSubItems()); + } + + @NotNull + @Override + public String getTextFor(AttachItem value) { + return value.getSelectedDebugger().getDebuggerDisplayName(); + } + } } } diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java index 097850b69360..e3db3518482a 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java @@ -31,12 +31,10 @@ import com.intellij.xdebugger.attach.XLocalAttachGroup; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; import java.util.Collections; import java.util.List; -import static com.intellij.xdebugger.impl.actions.AttachToLocalProcessAction.AttachItem; -import static com.intellij.xdebugger.impl.actions.AttachToLocalProcessAction.collectAttachItems; +import static com.intellij.xdebugger.impl.actions.AttachToLocalProcessAction.*; public class AttachToLocalProcessActionTest extends PlatformTestCase { public void testCollectingAttachItems_Empty() throws Exception { @@ -272,6 +270,72 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { }, "dbg1")); } + public void testHistory() throws Exception { + ProcessInfo info1 = new ProcessInfo(1, "command line 1", "exec1", "args1", null, null); + ProcessInfo info2 = new ProcessInfo(1, "command line 2", "exec1", "args1", null, null); + ProcessInfo info3 = new ProcessInfo(1, "command line 3", "exec1", "args1", null, null); + ProcessInfo info4 = new ProcessInfo(1, "command line 4", "exec1", "args1", null, null); + ProcessInfo info5 = new ProcessInfo(1, "command line 5", "exec1", "args1", null, null); + + List debuggers = createDebuggers("gdb"); + AttachItem item1 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info1, debuggers); + AttachItem item2 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info2, debuggers); + AttachItem item3 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info3, debuggers); + AttachItem item4 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info4, debuggers); + AttachItem item5 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info5, debuggers); + + HistoryItem historyItem1 = new HistoryItem(info1, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + HistoryItem historyItem2 = new HistoryItem(info2, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + HistoryItem historyItem3 = new HistoryItem(info3, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + HistoryItem historyItem4 = new HistoryItem(info4, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + HistoryItem historyItem5 = new HistoryItem(info5, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + + // empty + assertEmpty(getHistory(getProject())); + + // adding some items + addToHistory(getProject(), item1); + addToHistory(getProject(), item2); + + assertOrderedEquals(getHistory(getProject()), historyItem1, historyItem2); + + addToHistory(getProject(), item3); + addToHistory(getProject(), item4); + + assertOrderedEquals(getHistory(getProject()), historyItem1, historyItem2, historyItem3, historyItem4); + + // limiting size to 4 items + addToHistory(getProject(), item5); + assertOrderedEquals(getHistory(getProject()), historyItem2, historyItem3, historyItem4, historyItem5); + + // popping up recent items + addToHistory(getProject(), item3); + addToHistory(getProject(), item2); + assertOrderedEquals(getHistory(getProject()), historyItem4, historyItem5, historyItem3, historyItem2); + } + + public void testHistory_UpdatingPreviousItems() throws Exception { + TestAttachGroup group1 = new TestAttachGroup("group1", 1); + TestAttachGroup group2 = new TestAttachGroup("group2", 2); + + List debuggers1 = createDebuggers("gdb1"); + List debuggers2 = createDebuggers("gdb2"); + + ProcessInfo info1 = new ProcessInfo(1, "same command line", "exec1", "args1", null, null); + ProcessInfo info2 = new ProcessInfo(2, "same command line", "exec2", "args2", null, null); + + AttachItem item1 = new AttachItem(group1, true, info1, debuggers1); + AttachItem item2 = new AttachItem(group2, true, info2, debuggers2); + + HistoryItem historyItem1 = new HistoryItem(info1, group1, debuggers1.get(0)); + HistoryItem historyItem2 = new HistoryItem(info2, group2, debuggers2.get(0)); + + addToHistory(getProject(), item1); + assertOrderedEquals(getHistory(getProject()), historyItem1); + addToHistory(getProject(), item2); + assertOrderedEquals(getHistory(getProject()), historyItem2); + } + private static void assertItems(String expected, @NotNull XLocalAttachDebuggerProvider... providers) { Project project = ProjectManager.getInstance().getDefaultProject(); assertEquals(expected, printItems(project, collectAttachItems(project, getProcessList(), providers))); @@ -299,6 +363,28 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { }; } + @NotNull + private static List createDebuggers(String... names) { + return ContainerUtil.map(names, new Function() { + @Override + public XLocalAttachDebugger fun(final String s) { + return new XLocalAttachDebugger() { + @NotNull + @Override + public String getDebuggerDisplayName() { + return s; + } + + @NotNull + @Override + public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException { + return null; + } + }; + } + }); + } + private static class TestAttachGroup extends XDefaultLocalAttachGroup { @Nullable String myName; @Nullable Integer myOrder; @@ -322,11 +408,11 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { private static class TestDebuggerProvider implements XLocalAttachDebuggerProvider { XLocalAttachGroup myGroup; - List myNames; + String[] myNames; public TestDebuggerProvider(XLocalAttachGroup group, String... names) { myGroup = group; - myNames = Arrays.asList(names); + myNames = names; } public TestDebuggerProvider(String... names) { @@ -344,24 +430,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { public List getAvailableDebuggers(@NotNull Project project, @NotNull ProcessInfo processInfo, @NotNull UserDataHolder contextHolder) { - return ContainerUtil.map(myNames, new Function() { - @Override - public XLocalAttachDebugger fun(final String s) { - return new XLocalAttachDebugger() { - @NotNull - @Override - public String getDebuggerDisplayName() { - return s; - } - - @NotNull - @Override - public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException { - return null; - } - }; - } - }); + return createDebuggers(myNames); } } } \ No newline at end of file From 44d9bedac3c1b3f040baa43cc62275943bffa0a8 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 11 Jan 2016 18:21:13 +0100 Subject: [PATCH 023/825] IDEA-149798 Extensible Attach to Local Process action: messages --- .../src/messages/XDebuggerBundle.properties | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 00d11b86e76a..d885bd179fc0 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -9,10 +9,11 @@ debugger.hotswap.display.name=HotSwap xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger -xdebugger.attach.toLocal.popup.title=Attach -xdebugger.attach.toLocal.popup.emptyText=No process to attach to +xdebugger.attach.toLocal.popup.title=Attach To +xdebugger.attach.toLocal.popup.emptyText=No processes to attach to xdebugger.attach.toLocal.popup.adText=Attach with {0} -xdebugger.attach.toLocal.popup.selectDebugger.title=Select Debugger +xdebugger.attach.toLocal.popup.selectDebugger.title=Debugger +xdebugger.attach.toLocal.popup.recent=Recent xdebugger.attach.toLocal.action=Attach to Local Process... xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger From 0aa1e2863835977241175a5337c75382979f58fa Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 11 Jan 2016 21:52:57 +0100 Subject: [PATCH 024/825] IDEA-150278 Show recent items in 'Attach to Local Process' action --- .../actions/AttachToLocalProcessAction.java | 85 ++++- .../AttachToLocalProcessActionTest.java | 357 +++++++++++++++--- 2 files changed, 372 insertions(+), 70 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 3cebd488f2fe..757fa27d1021 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -139,7 +139,7 @@ public class AttachToLocalProcessAction extends AnAction { } }); - List result = new ArrayList(); + List currentItems = new ArrayList(); for (final XLocalAttachGroup eachGroup : sortedGroups) { List>> sortedItems = new ArrayList>>(groupWithItems.get(eachGroup)); @@ -152,12 +152,42 @@ public class AttachToLocalProcessAction extends AnAction { boolean first = true; for (Pair> eachItem : sortedItems) { - result.add(new AttachItem(eachGroup, first, eachItem.first, eachItem.second)); + currentItems.add(new AttachItem(eachGroup, first, eachItem.first, eachItem.second)); first = false; } } - return result; + List currentHistoryItems = new ArrayList(); + List history = getHistory(project); + for (int i = history.size() - 1; i >= 0; i--) { + HistoryItem eachHistoryItem = history.get(i); + for (AttachItem eachCurrentItem : currentItems) { + boolean isSuitableItem = eachHistoryItem.getGroup().equals(eachCurrentItem.getGroup()) && + eachHistoryItem.getProcessInfo().getCommandLine().equals(eachCurrentItem.getProcessInfo().getCommandLine()); + if (!isSuitableItem) continue; + + List debuggers = eachCurrentItem.getDebuggers(); + int selectedDebugger = -1; + for (int j = 0; j < debuggers.size(); j++) { + XLocalAttachDebugger eachDebugger = debuggers.get(j); + if (eachDebugger.getDebuggerDisplayName().equals(eachHistoryItem.getDebuggerName())) { + selectedDebugger = j; + break; + } + } + if (selectedDebugger == -1) continue; + + currentHistoryItems.add(new AttachItem(eachCurrentItem.getGroup(), + currentHistoryItems.isEmpty(), + XDebuggerBundle.message("xdebugger.attach.toLocal.popup.recent"), + eachCurrentItem.getProcessInfo(), + debuggers, + selectedDebugger)); + } + } + + currentHistoryItems.addAll(currentItems); + return currentHistoryItems; } public static void addToHistory(@NotNull Project project, @NotNull AttachItem item) { @@ -167,7 +197,8 @@ public class AttachToLocalProcessAction extends AnAction { } ProcessInfo processInfo = item.getProcessInfo(); history.remove(processInfo.getCommandLine()); - history.put(processInfo.getCommandLine(), new HistoryItem(processInfo, item.getGroup(), item.getSelectedDebugger())); + history.put(processInfo.getCommandLine(), new HistoryItem(processInfo, item.getGroup(), + item.getSelectedDebugger().getDebuggerDisplayName())); while (history.size() > 4) { history.remove(history.keySet().iterator().next()); } @@ -183,14 +214,14 @@ public class AttachToLocalProcessAction extends AnAction { public static class HistoryItem { @NotNull private final ProcessInfo myProcessInfo; @NotNull private final XLocalAttachGroup myGroup; - @NotNull private final XLocalAttachDebugger myDebugger; + @NotNull private final String myDebuggerName; public HistoryItem(@NotNull ProcessInfo processInfo, @NotNull XLocalAttachGroup group, - @NotNull XLocalAttachDebugger debugger) { + @NotNull String debuggerName) { myProcessInfo = processInfo; myGroup = group; - myDebugger = debugger; + myDebuggerName = debuggerName; } @NotNull @@ -204,8 +235,8 @@ public class AttachToLocalProcessAction extends AnAction { } @NotNull - public XLocalAttachDebugger getDebugger() { - return myDebugger; + public String getDebuggerName() { + return myDebuggerName; } @Override @@ -217,7 +248,7 @@ public class AttachToLocalProcessAction extends AnAction { if (!myProcessInfo.equals(item.myProcessInfo)) return false; if (!myGroup.equals(item.myGroup)) return false; - if (!myDebugger.equals(item.myDebugger)) return false; + if (!myDebuggerName.equals(item.myDebuggerName)) return false; return true; } @@ -226,7 +257,7 @@ public class AttachToLocalProcessAction extends AnAction { public int hashCode() { int result = myProcessInfo.hashCode(); result = 31 * result + myGroup.hashCode(); - result = 31 * result + myDebugger.hashCode(); + result = 31 * result + myDebuggerName.hashCode(); return result; } } @@ -234,20 +265,34 @@ public class AttachToLocalProcessAction extends AnAction { public static class AttachItem { @NotNull private final XLocalAttachGroup myGroup; private final boolean myIsFirstInGroup; + @NotNull private final String myGroupName; @NotNull private final ProcessInfo myProcessInfo; @NotNull private final List myDebuggers; + private final int mySelectedDebugger; @NotNull private final List mySubItems; public AttachItem(@NotNull XLocalAttachGroup group, boolean isFirstInGroup, @NotNull ProcessInfo info, @NotNull List debuggers) { - assert !debuggers.isEmpty(); + this(group, isFirstInGroup, group.getGroupName(), info, debuggers, 0); + } + + public AttachItem(@NotNull XLocalAttachGroup group, + boolean isFirstInGroup, + @NotNull String groupName, + @NotNull ProcessInfo info, + @NotNull List debuggers, + int selectedDebugger) { + myGroupName = groupName; + assert !debuggers.isEmpty() : "debugger list should not be empty"; + assert selectedDebugger >= 0 && selectedDebugger < debuggers.size() : "wrong selected debugger index"; myGroup = group; myIsFirstInGroup = isFirstInGroup; myProcessInfo = info; myDebuggers = debuggers; + mySelectedDebugger = selectedDebugger; if (debuggers.size() > 1) { mySubItems = ContainerUtil.map(debuggers, new Function() { @@ -274,7 +319,7 @@ public class AttachToLocalProcessAction extends AnAction { @Nullable public String getSeparatorTitle() { - return myIsFirstInGroup ? myGroup.getGroupName() : null; + return myIsFirstInGroup ? myGroupName : null; } @Nullable @@ -287,9 +332,14 @@ public class AttachToLocalProcessAction extends AnAction { return myProcessInfo.getPid() + " " + myGroup.getProcessDisplayText(project, myProcessInfo); } + @NotNull + public List getDebuggers() { + return myDebuggers; + } + @NotNull public XLocalAttachDebugger getSelectedDebugger() { - return myDebuggers.get(0); + return myDebuggers.get(mySelectedDebugger); } @NotNull @@ -383,7 +433,7 @@ public class AttachToLocalProcessAction extends AnAction { if (finalChoice) { return super.onChosen(selectedValue, true); } - return new DebuggerListStep(selectedValue); + return new DebuggerListStep(selectedValue.getSubItems(), selectedValue.mySelectedDebugger); } @Override @@ -394,9 +444,10 @@ public class AttachToLocalProcessAction extends AnAction { } private class DebuggerListStep extends MyBasePopupStep { - public DebuggerListStep(AttachItem selectedValue) { + public DebuggerListStep(List items, int selectedItem) { super(ProcessListStep.this.myProject, - XDebuggerBundle.message("xdebugger.attach.toLocal.popup.selectDebugger.title"), selectedValue.getSubItems()); + XDebuggerBundle.message("xdebugger.attach.toLocal.popup.selectDebugger.title"), items); + setDefaultOptionIndex(selectedItem); } @NotNull diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java index e3db3518482a..1f7bc2a764ae 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/impl/actions/AttachToLocalProcessActionTest.java @@ -18,7 +18,6 @@ package com.intellij.xdebugger.impl.actions; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessInfo; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.UserDataHolder; import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.Function; @@ -46,8 +45,6 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { } public void testCollectingAttachItems_OneDebugger() throws Exception { - Project project = ProjectManager.getInstance().getDefaultProject(); - assertItems("--------\n" + "1 exec1: dbg\n" + "2 exec2: dbg\n", @@ -59,26 +56,8 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { assertItems("--------\n" + "1 exec1: dbg1\n" + "2 exec2: dbg2\n", - new TestDebuggerProvider("dbg1") { - @NotNull - @Override - public List getAvailableDebuggers(@NotNull Project project, - @NotNull ProcessInfo processInfo, - @NotNull UserDataHolder contextHolder) { - if (processInfo.getPid() != 1) return Collections.emptyList(); - return super.getAvailableDebuggers(project, processInfo, contextHolder); - } - }, - new TestDebuggerProvider("dbg2") { - @NotNull - @Override - public List getAvailableDebuggers(@NotNull Project project, - @NotNull ProcessInfo processInfo, - @NotNull UserDataHolder contextHolder) { - if (processInfo.getPid() != 2) return Collections.emptyList(); - return super.getAvailableDebuggers(project, processInfo, contextHolder); - } - }); + new TestDebuggerProvider(1, XLocalAttachGroup.DEFAULT, "dbg1"), + new TestDebuggerProvider(2, XLocalAttachGroup.DEFAULT, "dbg2")); } public void testCollectingAttachItems_SeveralDebuggers() throws Exception { @@ -284,11 +263,11 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { AttachItem item4 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info4, debuggers); AttachItem item5 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info5, debuggers); - HistoryItem historyItem1 = new HistoryItem(info1, XLocalAttachGroup.DEFAULT, debuggers.get(0)); - HistoryItem historyItem2 = new HistoryItem(info2, XLocalAttachGroup.DEFAULT, debuggers.get(0)); - HistoryItem historyItem3 = new HistoryItem(info3, XLocalAttachGroup.DEFAULT, debuggers.get(0)); - HistoryItem historyItem4 = new HistoryItem(info4, XLocalAttachGroup.DEFAULT, debuggers.get(0)); - HistoryItem historyItem5 = new HistoryItem(info5, XLocalAttachGroup.DEFAULT, debuggers.get(0)); + HistoryItem historyItem1 = new HistoryItem(info1, XLocalAttachGroup.DEFAULT, "gdb"); + HistoryItem historyItem2 = new HistoryItem(info2, XLocalAttachGroup.DEFAULT, "gdb"); + HistoryItem historyItem3 = new HistoryItem(info3, XLocalAttachGroup.DEFAULT, "gdb"); + HistoryItem historyItem4 = new HistoryItem(info4, XLocalAttachGroup.DEFAULT, "gdb"); + HistoryItem historyItem5 = new HistoryItem(info5, XLocalAttachGroup.DEFAULT, "gdb"); // empty assertEmpty(getHistory(getProject())); @@ -318,36 +297,302 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { TestAttachGroup group1 = new TestAttachGroup("group1", 1); TestAttachGroup group2 = new TestAttachGroup("group2", 2); - List debuggers1 = createDebuggers("gdb1"); - List debuggers2 = createDebuggers("gdb2"); - ProcessInfo info1 = new ProcessInfo(1, "same command line", "exec1", "args1", null, null); ProcessInfo info2 = new ProcessInfo(2, "same command line", "exec2", "args2", null, null); - AttachItem item1 = new AttachItem(group1, true, info1, debuggers1); - AttachItem item2 = new AttachItem(group2, true, info2, debuggers2); + AttachItem item1 = new AttachItem(group1, true, info1, createDebuggers("gdb1")); + AttachItem item2 = new AttachItem(group2, true, info2, createDebuggers("gdb2")); - HistoryItem historyItem1 = new HistoryItem(info1, group1, debuggers1.get(0)); - HistoryItem historyItem2 = new HistoryItem(info2, group2, debuggers2.get(0)); + HistoryItem historyItem1 = new HistoryItem(info1, group1, "gdb1"); + HistoryItem historyItem2 = new HistoryItem(info2, group2, "gdb2"); addToHistory(getProject(), item1); assertOrderedEquals(getHistory(getProject()), historyItem1); addToHistory(getProject(), item2); assertOrderedEquals(getHistory(getProject()), historyItem2); } - - private static void assertItems(String expected, @NotNull XLocalAttachDebuggerProvider... providers) { - Project project = ProjectManager.getInstance().getDefaultProject(); - assertEquals(expected, printItems(project, collectAttachItems(project, getProcessList(), providers))); + + public void testHistoryGroup() throws Exception { + TestAttachGroup group1 = new TestAttachGroup("group1", 1); + TestAttachGroup group2 = new TestAttachGroup("group2", 2); + List debuggers1 = createDebuggers("gdb1", "lldb1"); + List debuggers2 = createDebuggers("gdb2", "lldb2"); + + List originalItems = collectAttachItems(getProject(), + new ProcessInfo[]{ + new ProcessInfo(1, "command line 1", "exec1", "args1", null, null), + new ProcessInfo(2, "command line 2", "exec2", "args2", null, null)}, + new TestDebuggerProvider(1, group1, debuggers1), + new TestDebuggerProvider(2, group2, debuggers2)); + + // one item in history + addToHistory(getProject(), originalItems.get(0)); + assertItems("----Recent----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + + // several items in history + addToHistory(getProject(), originalItems.get(1)); + assertItems("----Recent----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + + // put most recent item on top + addToHistory(getProject(), originalItems.get(0)); + assertItems("----Recent----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + + // put debugger used in history item on top + addToHistory(getProject(), originalItems.get(0).getSubItems().get(1)); + addToHistory(getProject(), originalItems.get(1).getSubItems().get(1)); + assertItems("----Recent----\n" + + "20 exec20: lldb2\n" + + " gdb2\n" + + " lldb2\n" + + "10 exec10: lldb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + + // filter unavailable history items + assertItems("----Recent----\n" + + "20 exec20: lldb2\n" + + " gdb2\n" + + " lldb2\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 10", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + assertItems("----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 10", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 20", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + // history items available again: + assertItems("----Recent----\n" + + "20 exec20: lldb2\n" + + " gdb2\n" + + " lldb2\n" + + "10 exec10: lldb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + + // filter items from history by suitable group + assertItems("----Recent----\n" + + "10 exec10: lldb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group1, debuggers2)); + assertItems("----Recent----\n" + + "20 exec20: lldb2\n" + + " gdb2\n" + + " lldb2\n" + + "----group2----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group2, debuggers1), + new TestDebuggerProvider(20, group2, debuggers2)); + // filter by group equality, not by name + assertItems("----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, new TestAttachGroup(group1.getGroupName(), group1.getOrder()), debuggers1), + new TestDebuggerProvider(20, new TestAttachGroup(group2.getGroupName(), group2.getOrder()), debuggers2)); + + // filter items from history by available debugger + assertItems("----Recent----\n" + + "10 exec10: lldb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb1\n" + + " gdb1\n" + + " lldb1\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, debuggers1), + new TestDebuggerProvider(20, group2, debuggers1)); + + // filter debuggers by name, not by equality + assertItems("----Recent----\n" + + "20 exec20: lldb2\n" + + " gdb2\n" + + " lldb2\n" + + "10 exec10: lldb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group1----\n" + + "10 exec10: gdb1\n" + + " gdb1\n" + + " lldb1\n" + + "----group2----\n" + + "20 exec20: gdb2\n" + + " gdb2\n" + + " lldb2\n", + new ProcessInfo[]{ + new ProcessInfo(10, "command line 1", "exec10", "args10", null, null), + new ProcessInfo(20, "command line 2", "exec20", "args20", null, null) + }, + new TestDebuggerProvider(10, group1, createDebuggers("gdb1", "lldb1")), + new TestDebuggerProvider(20, group2, createDebuggers("gdb2", "lldb2"))); } - private static String printItems(Project project, List items) { + private void assertItems(String expected, @NotNull XLocalAttachDebuggerProvider... providers) { + ProcessInfo[] infos = { + new ProcessInfo(1, "command line 1", "exec1", "args1", null, null), + new ProcessInfo(2, "command line 2", "exec2", "args2", null, null), + }; + assertItems(expected, infos, providers); + } + + private void assertItems(String expected, ProcessInfo[] infos, @NotNull XLocalAttachDebuggerProvider... providers) { + assertEquals(expected, printItems(collectAttachItems(getProject(), infos, providers))); + } + + private void assertItems(String expected, List items) { + assertEquals(expected, printItems(items)); + } + + private String printItems(List items) { StringBuilder builder = new StringBuilder(); for (AttachItem each : items) { String title = each.getSeparatorTitle(); if (title != null) builder.append("----").append(title).append("----\n"); - builder.append(each.getText(project)).append(": ").append(each.getSelectedDebugger().getDebuggerDisplayName()).append("\n"); + builder.append(each.getText(getProject())).append(": ").append(each.getSelectedDebugger().getDebuggerDisplayName()).append("\n"); for (AttachItem eachSubItem : each.getSubItems()) { builder.append(" ").append(eachSubItem.getSelectedDebugger().getDebuggerDisplayName()).append("\n"); } @@ -356,13 +601,6 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { return builder.toString(); } - private static ProcessInfo[] getProcessList() { - return new ProcessInfo[]{ - new ProcessInfo(1, "command line 1", "exec1", "args1", null, null), - new ProcessInfo(2, "command line 2", "exec2", "args2", null, null), - }; - } - @NotNull private static List createDebuggers(String... names) { return ContainerUtil.map(names, new Function() { @@ -407,12 +645,24 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { } private static class TestDebuggerProvider implements XLocalAttachDebuggerProvider { - XLocalAttachGroup myGroup; - String[] myNames; + @Nullable private final Integer myFilterPID; + @NotNull private final XLocalAttachGroup myGroup; + @NotNull private final List myDebuggers; - public TestDebuggerProvider(XLocalAttachGroup group, String... names) { + public TestDebuggerProvider(@Nullable Integer filterPID, + @NotNull XLocalAttachGroup group, + @NotNull List debuggers) { + myFilterPID = filterPID; myGroup = group; - myNames = names; + myDebuggers = debuggers; + } + + public TestDebuggerProvider(@Nullable Integer filterPID, @NotNull XLocalAttachGroup group, String... names) { + this(filterPID, group, createDebuggers(names)); + } + + public TestDebuggerProvider(@NotNull XLocalAttachGroup group, String... names) { + this(null, group, names); } public TestDebuggerProvider(String... names) { @@ -430,7 +680,8 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase { public List getAvailableDebuggers(@NotNull Project project, @NotNull ProcessInfo processInfo, @NotNull UserDataHolder contextHolder) { - return createDebuggers(myNames); + if (myFilterPID != null && processInfo.getPid() != myFilterPID) return Collections.emptyList(); + return myDebuggers; } } } \ No newline at end of file From 7e025397fb279c82ebb8804918661d39dff56f56 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 12 Jan 2016 14:56:10 +0100 Subject: [PATCH 025/825] IDEA-149798 Extensible Attach to Local Process action CPP-1001 Attach to existing local process * after merge fixes --- .../execution/process/ProcessUtils.java | 136 ++---------------- .../process/impl/OSProcessManagerImpl.java | 8 -- .../process/impl/ProcessListUtil.java | 4 +- .../process/impl/ProcessListTest.java | 3 +- .../actions/AttachToLocalProcessAction.java | 4 +- 5 files changed, 14 insertions(+), 141 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java index d01b84f2bc8c..3fe33f687092 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java @@ -27,101 +27,23 @@ ******************************************************************************/ package com.intellij.execution.process; +import com.intellij.execution.process.impl.ProcessListUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jvnet.winp.WinProcess; -import org.jvnet.winp.WinpException; -import java.io.*; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public class ProcessUtils { private static final Logger LOG = Logger.getInstance(ProcessUtils.class); - /** - * Passes the commands directly to Runtime.exec (with the passed envp) - */ @NotNull - public static Process createProcess(String[] cmdarray, String[] envp, File workingDir) throws IOException { - return Runtime.getRuntime().exec(getWithoutEmptyParams(cmdarray), getWithoutEmptyParams(envp), workingDir); - } - - /** - * @return a new array without any null/empty elements originally contained in the array. - */ - @Nullable - private static String[] getWithoutEmptyParams(@Nullable String[] cmdarray) { - if (cmdarray == null) { - return null; - } - ArrayList list = new ArrayList(); - for (String string : cmdarray) { - if (string != null && string.length() > 0) { - list.add(string); - } - } - return ArrayUtil.toStringArray(list); - } - - @NotNull - public static IProcessList getProcessList(@NotNull String helpersRoot) { - if (SystemInfo.isWindows) { - return new ProcessListWin32(helpersRoot); - } - if (SystemInfo.isLinux) { - return new ProcessListLinux(); - } - if (SystemInfo.isMac) { - return new ProcessListMac(); - } - - LOG.error("Unexpected platform. Unable to list processes."); - return new IProcessList() { - - @Override - public ProcessInfo[] getProcessList() { - return new ProcessInfo[0]; - } - }; - } - - @NotNull - public static char[] loadFileText(@NotNull File file, @Nullable String encoding) throws IOException { - InputStream stream = new FileInputStream(file); - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - Reader reader = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding); - try { - return loadText(reader); - } - finally { - reader.close(); - } - } - - @NotNull - public static char[] loadText(@NotNull Reader reader) throws IOException { - //fill a buffer with the contents - int BUFFER_SIZE = 2 * 1024; - - char[] readBuffer = new char[BUFFER_SIZE]; - int n = reader.read(readBuffer); - - int DEFAULT_FILE_SIZE = 8 * BUFFER_SIZE; - - StringBuilder builder = new StringBuilder(DEFAULT_FILE_SIZE); - - while (n > 0) { - builder.append(readBuffer, 0, n); - n = reader.read(readBuffer); - } - - return builder.toString().toCharArray(); + public static ProcessInfo[] getProcessList() { + return ProcessListUtil.getProcessList(); } public static boolean killProcessTree(@NotNull Process process) { @@ -181,52 +103,10 @@ public class ProcessUtils { @Nullable public static List getCommandLinesOfRunningProcesses() { - try { - if (SystemInfo.isWindows) { - List commandLines = new ArrayList(); - for (WinProcess process : WinProcess.all()) { - try { - commandLines.add(process.getCommandLine()); - } - catch (WinpException ignored) { } - } - return commandLines; - } - else { - String[] cmd = UnixProcessManager.getPSCmd(true); - Process process = Runtime.getRuntime().exec(cmd); - List outputLines = readLines(process.getInputStream(), false); - List errorLines = readLines(process.getErrorStream(), false); - if (!errorLines.isEmpty()) { - throw new IOException(Arrays.toString(cmd) + " failed: " + StringUtil.join(errorLines, "\n")); - } - - //trim 'ps' output header - return outputLines.subList(1, outputLines.size()); - } - } - catch (Throwable e) { - LOG.info("Cannot collect command lines"); - LOG.info(e); - return null; - } - } - - @NotNull - private static List readLines(@NotNull InputStream inputStream, boolean includeEmpty) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - try { - List lines = new ArrayList(); - String line; - while ((line = reader.readLine()) != null) { - if (includeEmpty || !line.isEmpty()) { - lines.add(line); - } - } - return lines; - } - finally { - reader.close(); + List result = new ArrayList(); + for (ProcessInfo each : getProcessList()) { + result.add(each.getCommandLine()); } + return Collections.unmodifiableList(result); } } diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java index ae92de5cf003..d43f90af1a56 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java @@ -31,14 +31,6 @@ public class OSProcessManagerImpl extends OSProcessManager { return ProcessUtils.killProcessTree(process); } - public static void killProcess(@NotNull Process process) { - ProcessUtils.killProcess(process); - } - - public static int getProcessID(@NotNull Process process) { - return ProcessUtils.getProcessID(process); - } - @Override @Nullable public List getCommandLinesOfRunningProcesses() { diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index d70acd77c201..4f94042b82c8 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -37,11 +37,11 @@ import java.util.Collections; import java.util.List; -class ProcessListUtil { +public class ProcessListUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.impl.ProcessListUtil"); @NotNull - static ProcessInfo[] getProcessList() { + public static ProcessInfo[] getProcessList() { List result = doGetProcessList(); return result.isEmpty() ? ProcessInfo.EMPTY_ARRAY : result.toArray(new ProcessInfo[result.size()]); } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index 6773c6d08be5..3a4c3813cf7b 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -16,6 +16,7 @@ package com.intellij.execution.process.impl; import com.intellij.execution.process.ProcessInfo; +import com.intellij.execution.process.ProcessUtils; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.IoTestUtil; @@ -49,7 +50,7 @@ public class ProcessListTest extends UsefulTestCase { } public void testWorksOnAllPlatforms() throws Exception { - assertNotEmpty(Arrays.asList(OSProcessManagerImpl.getProcessList())); + assertNotEmpty(Arrays.asList(ProcessUtils.getProcessList())); if (SystemInfo.isWindows) { assertNotEmpty(Arrays.asList(ProcessListUtil.getProcessList_WindowsTaskList())); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 757fa27d1021..ee71c044eee3 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -17,7 +17,7 @@ package com.intellij.xdebugger.impl.actions; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.process.impl.OSProcessManagerImpl; +import com.intellij.execution.process.ProcessUtils; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; @@ -73,7 +73,7 @@ public class AttachToLocalProcessAction extends AnAction { final Project project = getEventProject(e); if (project == null) return; - ProcessInfo[] processList = OSProcessManagerImpl.getProcessList(); + ProcessInfo[] processList = ProcessUtils.getProcessList(); XLocalAttachDebuggerProvider[] providers = Extensions.getExtensions(XLocalAttachDebuggerProvider.EP); ProcessListStep step = new ProcessListStep(collectAttachItems(project, processList, providers), project); From 730bae6e23c4f37e5eac46366748a617221a2bce Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 12 Jan 2016 14:58:14 +0100 Subject: [PATCH 026/825] IDEA-149798 Extensible Attach to Local Process action CPP-1001 Attach to existing local process * after merge fixes + OSProcessUtil introduced --- .../process/{ProcessUtils.java => OSProcessUtil.java} | 4 ++-- .../execution/process/impl/OSProcessManagerImpl.java | 6 +++--- .../intellij/execution/process/impl/ProcessListTest.java | 4 ++-- .../xdebugger/impl/actions/AttachToLocalProcessAction.java | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename platform/platform-impl/src/com/intellij/execution/process/{ProcessUtils.java => OSProcessUtil.java} (97%) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java b/platform/platform-impl/src/com/intellij/execution/process/OSProcessUtil.java similarity index 97% rename from platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java rename to platform/platform-impl/src/com/intellij/execution/process/OSProcessUtil.java index 3fe33f687092..75c9dc9f365e 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessUtils.java +++ b/platform/platform-impl/src/com/intellij/execution/process/OSProcessUtil.java @@ -38,8 +38,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class ProcessUtils { - private static final Logger LOG = Logger.getInstance(ProcessUtils.class); +public class OSProcessUtil { + private static final Logger LOG = Logger.getInstance(OSProcessUtil.class); @NotNull public static ProcessInfo[] getProcessList() { diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java index d43f90af1a56..fa6246d76479 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/OSProcessManagerImpl.java @@ -16,7 +16,7 @@ package com.intellij.execution.process.impl; import com.intellij.execution.process.OSProcessManager; -import com.intellij.execution.process.ProcessUtils; +import com.intellij.execution.process.OSProcessUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,12 +28,12 @@ import java.util.List; public class OSProcessManagerImpl extends OSProcessManager { @Override public boolean killProcessTree(@NotNull Process process) { - return ProcessUtils.killProcessTree(process); + return OSProcessUtil.killProcessTree(process); } @Override @Nullable public List getCommandLinesOfRunningProcesses() { - return ProcessUtils.getCommandLinesOfRunningProcesses(); + return OSProcessUtil.getCommandLinesOfRunningProcesses(); } } diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index 3a4c3813cf7b..968f60e3b92f 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -15,8 +15,8 @@ */ package com.intellij.execution.process.impl; +import com.intellij.execution.process.OSProcessUtil; import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.process.ProcessUtils; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.IoTestUtil; @@ -50,7 +50,7 @@ public class ProcessListTest extends UsefulTestCase { } public void testWorksOnAllPlatforms() throws Exception { - assertNotEmpty(Arrays.asList(ProcessUtils.getProcessList())); + assertNotEmpty(Arrays.asList(OSProcessUtil.getProcessList())); if (SystemInfo.isWindows) { assertNotEmpty(Arrays.asList(ProcessListUtil.getProcessList_WindowsTaskList())); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index ee71c044eee3..965bf497919f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -16,8 +16,8 @@ package com.intellij.xdebugger.impl.actions; import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.OSProcessUtil; import com.intellij.execution.process.ProcessInfo; -import com.intellij.execution.process.ProcessUtils; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; @@ -73,7 +73,7 @@ public class AttachToLocalProcessAction extends AnAction { final Project project = getEventProject(e); if (project == null) return; - ProcessInfo[] processList = ProcessUtils.getProcessList(); + ProcessInfo[] processList = OSProcessUtil.getProcessList(); XLocalAttachDebuggerProvider[] providers = Extensions.getExtensions(XLocalAttachDebuggerProvider.EP); ProcessListStep step = new ProcessListStep(collectAttachItems(project, processList, providers), project); From 7818ea28158bfda340f1a85f317531d455df9abe Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 12 Jan 2016 16:54:30 +0100 Subject: [PATCH 027/825] IDEA-149798 Extensible Attach to Local Process action: * show selected debugger in the title instead of at the bottom * limit title and item length --- .../src/messages/XDebuggerBundle.properties | 1 - .../impl/actions/AttachToLocalProcessAction.java | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index d885bd179fc0..fbc3a53afd9f 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -9,7 +9,6 @@ debugger.hotswap.display.name=HotSwap xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger -xdebugger.attach.toLocal.popup.title=Attach To xdebugger.attach.toLocal.popup.emptyText=No processes to attach to xdebugger.attach.toLocal.popup.adText=Attach with {0} xdebugger.attach.toLocal.popup.selectDebugger.title=Debugger diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java index 965bf497919f..e29a59b124af 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AttachToLocalProcessAction.java @@ -30,6 +30,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Function; @@ -94,9 +95,9 @@ public class AttachToLocalProcessAction extends AnAction { } if (item instanceof AttachItem) { - popup.setAdText(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.adText", - ((AttachItem)item).getSelectedDebugger().getDebuggerDisplayName()), - SwingConstants.LEADING); + String debuggerName = ((AttachItem)item).getSelectedDebugger().getDebuggerDisplayName(); + debuggerName = StringUtil.shortenTextWithEllipsis(debuggerName, 50, 0); + ((ListPopupImpl)popup).setCaption(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.adText", debuggerName)); } } }; @@ -329,7 +330,8 @@ public class AttachToLocalProcessAction extends AnAction { @NotNull public String getText(@NotNull Project project) { - return myProcessInfo.getPid() + " " + myGroup.getProcessDisplayText(project, myProcessInfo); + String shortenedText = StringUtil.shortenTextWithEllipsis(myGroup.getProcessDisplayText(project, myProcessInfo), 80, 0); + return myProcessInfo.getPid() + " " + shortenedText; } @NotNull @@ -396,7 +398,7 @@ public class AttachToLocalProcessAction extends AnAction { private static class ProcessListStep extends MyBasePopupStep implements ListPopupStepEx { public ProcessListStep(@NotNull List items, @NotNull Project project) { - super(project, XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title"), items); + super(project, XDebuggerBundle.message("xdebugger.attach.toLocal.popup.adText", ""), items); } @Nullable From 18165e1bb85a7269dc0b70b9f77a0bd931b91e06 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 12 Jan 2016 21:01:57 +0100 Subject: [PATCH 028/825] IDEA-149798 Extensible Attach to Local Process action: additional logging --- .../execution/process/impl/ProcessListUtil.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index 4f94042b82c8..f95f6f03ee06 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -19,6 +19,7 @@ package com.intellij.execution.process.impl; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.ProcessInfo; +import com.intellij.execution.process.ProcessOutput; import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; @@ -77,9 +78,18 @@ public class ProcessListUtil { @NotNull NullableFunction> parser) { String output; try { - output = ExecUtil.execAndGetOutput(new GeneralCommandLine(command)).getStdout(); + ProcessOutput processOutput = ExecUtil.execAndGetOutput(new GeneralCommandLine(command)); + int exitCode = processOutput.getExitCode(); + if (exitCode != 0) { + LOG.error("Cannot get process list, 'ps' exited with code " + exitCode + ", stdout:\n" + + processOutput.getStdout() + + "\nstderr:\n" + + processOutput.getStderr()); + } + output = processOutput.getStdout(); } - catch (ExecutionException ignore) { + catch (ExecutionException e) { + LOG.error("Cannot get process list", e); return null; } return parser.fun(output); @@ -265,7 +275,8 @@ public class ProcessListUtil { result.add(new ProcessInfo(pid, name, name, "", null, null)); } } - catch (IOException ignore) { + catch (IOException e) { + LOG.error("Cannot parse listtasks output", e); return null; } finally { From 75a4d0bc9203cbedba7169d49beab98107a67564 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 13 Jan 2016 17:20:58 +0300 Subject: [PATCH 029/825] dumb-aware run configurations: run startup tasks immediately, simplify --- .../execution/startup/ProjectStartupRunner.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/startup/ProjectStartupRunner.java b/platform/lang-impl/src/com/intellij/execution/startup/ProjectStartupRunner.java index 36daaff5c606..cae3cd3dfe46 100644 --- a/platform/lang-impl/src/com/intellij/execution/startup/ProjectStartupRunner.java +++ b/platform/lang-impl/src/com/intellij/execution/startup/ProjectStartupRunner.java @@ -22,7 +22,6 @@ import com.intellij.ide.startup.StartupManagerEx; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import com.intellij.openapi.startup.StartupManager; @@ -42,20 +41,6 @@ public class ProjectStartupRunner implements StartupActivity, DumbAware { @Override public void runActivity(@NotNull final Project project) { - if (Registry.is("dumb.aware.run.configurations")) { - doRunActivity(project); - } else { - DumbService.getInstance(project).runWhenSmart(new Runnable() { - @Override - public void run() { - if (project.isDisposed()) return; - doRunActivity(project); - } - }); - } - } - - protected void doRunActivity(@NotNull Project project) { final ProjectStartupTaskManager projectStartupTaskManager = ProjectStartupTaskManager.getInstance(project); if (projectStartupTaskManager.isEmpty()) return; From b079c088deaa10f1f94a9691c5e838b570c41089 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 13 Jan 2016 17:37:03 +0300 Subject: [PATCH 030/825] IDEA-110029 documentation window disappears immediately --- .../src/com/intellij/ui/popup/AbstractPopup.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index fee50ce87fab..ec6cc41fe9f3 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -555,7 +555,7 @@ public class AbstractPopup implements JBPopup { if (preferredBounds.y - adjustedBounds.y <= 0) { return preferredLocation; } - int adjustedY = preferredBounds.y - editor.getLineHeight() * 3 / 2 - preferredSize.height; + int adjustedY = preferredBounds.y - editor.getLineHeight() - preferredSize.height; if (adjustedY < 0) { return preferredLocation; } From a738a080747cb23e01f739e10c8cf3774cb9318b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 13 Jan 2016 16:00:11 +0100 Subject: [PATCH 031/825] recover jetbrains protocol args --- .../src/com/intellij/idea/SocketLock.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/idea/SocketLock.java b/platform/platform-impl/src/com/intellij/idea/SocketLock.java index da9053d98511..c629d3f2d37a 100644 --- a/platform/platform-impl/src/com/intellij/idea/SocketLock.java +++ b/platform/platform-impl/src/com/intellij/idea/SocketLock.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -15,6 +15,7 @@ */ package com.intellij.idea; +import com.intellij.openapi.application.JetBrainsProtocolHandler; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; @@ -189,6 +190,7 @@ public final class SocketLock { @NotNull private static ActivateStatus tryActivate(int portNumber, @NotNull Collection paths, @NotNull String[] args) { log("trying: port=%s", portNumber); + args = checkForJetBrainsProtocolCommand(args); try { Socket socket = new Socket(NetUtils.getLoopbackAddress(), portNumber); try { @@ -245,6 +247,14 @@ public final class SocketLock { return ActivateStatus.NO_INSTANCE; } + private static String[] checkForJetBrainsProtocolCommand(String[] args) { + final String jbUrl = System.getProperty(JetBrainsProtocolHandler.class.getName()); + if (jbUrl != null) { + return new String[]{jbUrl}; + } + return args; + } + private static class MyChannelInboundHandler extends MessageDecoder { private enum State {HEADER, CONTENT} From 0e570e0b44b79b58252647aed6ccc2375b211664 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 13 Jan 2016 16:02:11 +0100 Subject: [PATCH 032/825] handle jetbrains protocol commands with no additional command line processor --- .../intellij/ide/CommandLineProcessor.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java index 293c4a55eeae..a89f13fb1a82 100644 --- a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java +++ b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -18,8 +18,7 @@ package com.intellij.ide; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.impl.ProjectUtil; import com.intellij.idea.StartupUtil; -import com.intellij.openapi.application.ApplicationStarter; -import com.intellij.openapi.application.ApplicationStarterEx; +import com.intellij.openapi.application.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.OpenFileDescriptor; @@ -135,7 +134,7 @@ public class CommandLineProcessor { LOG.info("-----"); if (args.size() > 0) { - String command = args.get(0); + final String command = args.get(0); for(ApplicationStarter starter: Extensions.getExtensions(ApplicationStarter.EP_NAME)) { if (command.equals(starter.getCommandName()) && starter instanceof ApplicationStarterEx && @@ -145,6 +144,18 @@ public class CommandLineProcessor { return null; } } + + if (command.startsWith(JetBrainsProtocolHandler.PROTOCOL)) { + JetBrainsProtocolHandler.processJetBrainsLauncherParameters(command); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + JBProtocolCommand.handleCurrentCommand(); + } + }, ModalityState.any()); + + return null; + } } Project lastOpenedProject = null; From 4fb91649f4930b9747db6f98424a1e042a30cc28 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 13 Jan 2016 16:03:26 +0100 Subject: [PATCH 033/825] -> 1.8 use method ref --- .../jetbrains/ide/JetBrainsProtocolHandlerHttpService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platform/built-in-server/src/org/jetbrains/ide/JetBrainsProtocolHandlerHttpService.java b/platform/built-in-server/src/org/jetbrains/ide/JetBrainsProtocolHandlerHttpService.java index 811f13985acb..b6005cce57eb 100644 --- a/platform/built-in-server/src/org/jetbrains/ide/JetBrainsProtocolHandlerHttpService.java +++ b/platform/built-in-server/src/org/jetbrains/ide/JetBrainsProtocolHandlerHttpService.java @@ -44,12 +44,7 @@ public class JetBrainsProtocolHandlerHttpService extends RestService { if (URL_PARAM_NAME.equals(name) && url != null && url.startsWith(JetBrainsProtocolHandler.PROTOCOL)) { JetBrainsProtocolHandler.processJetBrainsLauncherParameters(url); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - JBProtocolCommand.handleCurrentCommand(); - } - }, ModalityState.any()); + ApplicationManager.getApplication().invokeLater(JBProtocolCommand::handleCurrentCommand, ModalityState.any()); } sendOk(request, context); From 7b81c62a121d55bd56ce63eac327c3da7d4d2536 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 13 Jan 2016 16:16:36 +0100 Subject: [PATCH 034/825] IDEA-149798 Extensible Attach to Local Process action: dialog title --- .../src/messages/XDebuggerBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index fbc3a53afd9f..ed9eb2f0535a 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -10,7 +10,7 @@ xdebugger.default.content.title=Debug xdebugger.debugger.tab.title=Debugger xdebugger.attach.toLocal.popup.emptyText=No processes to attach to -xdebugger.attach.toLocal.popup.adText=Attach with {0} +xdebugger.attach.toLocal.popup.adText=Attach with {0} To xdebugger.attach.toLocal.popup.selectDebugger.title=Debugger xdebugger.attach.toLocal.popup.recent=Recent xdebugger.attach.toLocal.action=Attach to Local Process... From f216063703ebf3160e868e4e49b891b6867321ec Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 13 Jan 2016 16:31:25 +0100 Subject: [PATCH 035/825] =?UTF-8?q?ElectronDebugTest=20=E2=80=94=20passed.?= =?UTF-8?q?=20Support=20debug=20pure=20js=20file=20in=20the=20ASAR=20?= =?UTF-8?q?=E2=80=94=20we=20resolve=20real=20file=20in=20the=20project=20u?= =?UTF-8?q?sing=20source=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/annotations/jdk/java/nio/file/annotations.xml | 3 +++ platform/built-in-server/client/node-rpc-client/package.json | 1 - .../src/com/intellij/openapi/util/io/fileUtil.kt | 4 ++-- .../src/org/jetbrains/debugger/frame/AsyncFramesHeader.kt | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/annotations/jdk/java/nio/file/annotations.xml b/lib/annotations/jdk/java/nio/file/annotations.xml index 6706a3e31d7b..4fc7d46c809e 100644 --- a/lib/annotations/jdk/java/nio/file/annotations.xml +++ b/lib/annotations/jdk/java/nio/file/annotations.xml @@ -2,6 +2,9 @@ + + + diff --git a/platform/built-in-server/client/node-rpc-client/package.json b/platform/built-in-server/client/node-rpc-client/package.json index 054e9913fa0f..40f2601a636c 100644 --- a/platform/built-in-server/client/node-rpc-client/package.json +++ b/platform/built-in-server/client/node-rpc-client/package.json @@ -13,7 +13,6 @@ "url": "https://github.com/JetBrains/intellij-community.git" }, "devDependencies": { - "dts-generator": "^1.6.3", "mocha": "^2.3.4", "rimraf": "^2.5.0", "should": "^8.0.2", diff --git a/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt b/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt index e64dd11a62da..eeb97cb8c019 100644 --- a/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt +++ b/platform/platform-impl/src/com/intellij/openapi/util/io/fileUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -23,7 +23,7 @@ val File.systemIndependentPath: String get() = path.replace(File.separatorChar, '/') val File.parentSystemIndependentPath: String - get() = getParent().replace(File.separatorChar, '/') + get() = parent.replace(File.separatorChar, '/') // PathUtilRt.getParentPath returns empty string if no parent path, but in Kotlin "null" is better because elvis operator could be used fun getParentPath(path: String) = StringUtil.nullize(PathUtilRt.getParentPath(path)) diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/AsyncFramesHeader.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/AsyncFramesHeader.kt index 3c6c267fb24d..5a07ddb3ed10 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/AsyncFramesHeader.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/AsyncFramesHeader.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -20,7 +20,7 @@ import com.intellij.ui.SimpleTextAttributes import com.intellij.util.ui.UIUtil import com.intellij.xdebugger.frame.XStackFrame -class AsyncFramesHeader(val asyncFunctionName: String) : XStackFrame() { +internal class AsyncFramesHeader(val asyncFunctionName: String) : XStackFrame() { override fun customizePresentation(component: ColoredTextContainer) { component.append("Async call from ", PREFIX_ATTRIBUTES) component.append(asyncFunctionName, NAME_ATTRIBUTES) From 8e59641f2e368f37516bd2b90d272eee4929cd5d Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 13 Jan 2016 18:02:39 +0300 Subject: [PATCH 036/825] no invokeLater for paintCycleEnd (otherwise ballon hide may happen too late even with animation off) --- .../src/com/intellij/util/ui/Animator.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/Animator.java b/platform/platform-api/src/com/intellij/util/ui/Animator.java index 5d8a92bf72b2..f23281871aff 100644 --- a/platform/platform-api/src/com/intellij/util/ui/Animator.java +++ b/platform/platform-api/src/com/intellij/util/ui/Animator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -106,14 +106,9 @@ public abstract class Animator implements Disposable { } private void animationDone() { + ApplicationManager.getApplication().assertIsDispatchThread(); stopTicker(); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - paintCycleEnd(); - } - }); + paintCycleEnd(); } private void stopTicker() { From ef59b92a12256a4c8ab081a1c8684ff61604726b Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 13 Jan 2016 16:39:14 +0100 Subject: [PATCH 037/825] IDEA-150345 Invalidate Cache / Restart doesn't delete jars --- .../openapi/vfs/impl/jar/JarHandler.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java index d7c27e57f614..b089dec7a135 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java @@ -246,22 +246,29 @@ public class JarHandler extends ZipHandler { private static final int VERSION = 1 + (PersistentHashMapValueStorage.COMPRESSION_ENABLED ? 15 : 0); static { - File snapshotInfoFile = new File(new File(getJarsDir()), "snapshots_info"); + File jarsDir = new File(getJarsDir()); + File snapshotInfoFile = new File(jarsDir, "snapshots_info"); int currentVersion = -1; + long currentVfsVersion = -1; File versionFile = getVersionFile(snapshotInfoFile); if (versionFile.exists()) { try { DataInputStream versionStream = new DataInputStream(new BufferedInputStream(new FileInputStream(versionFile))); try { currentVersion = DataInputOutputUtil.readINT(versionStream); + currentVfsVersion = DataInputOutputUtil.readTIME(versionStream); } finally { versionStream.close(); } } catch (IOException ignore) {} } - if (currentVersion != VERSION) { + if (currentVfsVersion != FSRecords.getCreationTimestamp()) { + FileUtil.deleteWithRenaming(jarsDir); + jarsDir.mkdirs(); + saveVersion(versionFile); + } else if (currentVersion != VERSION) { PersistentHashMap.deleteFilesStartingWith(snapshotInfoFile); saveVersion(versionFile); } @@ -275,13 +282,13 @@ public class JarHandler extends ZipHandler { @Override public void save(@NotNull DataOutput out, CacheLibraryInfo value) throws IOException { IOUtil.writeUTF(out, value.mySnapshotPath); - out.writeLong(value.myModificationTime); - out.writeLong(value.myFileLength); + DataInputOutputUtil.writeTIME(out, value.myModificationTime); + DataInputOutputUtil.writeLONG(out, value.myFileLength); } @Override public CacheLibraryInfo read(@NotNull DataInput in) throws IOException { - return new CacheLibraryInfo(IOUtil.readUTF(in), in.readLong(), in.readLong()); + return new CacheLibraryInfo(IOUtil.readUTF(in), DataInputOutputUtil.readTIME(in), DataInputOutputUtil.readLONG(in)); } } ); @@ -391,6 +398,7 @@ public class JarHandler extends ZipHandler { DataOutputStream versionOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(versionFile))); try { DataInputOutputUtil.writeINT(versionOutputStream, VERSION); + DataInputOutputUtil.writeTIME(versionOutputStream, FSRecords.getCreationTimestamp()); } finally { versionOutputStream.close(); From b56e7e0c20e5d851154e7142daf0e38a296b77e9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 11:15:47 +0100 Subject: [PATCH 038/825] change signature: propagate parameters change to lambda expressions (IDEA-150138) --- .../FunctionalInterfaceChangedUsageInfo.java | 38 ++++++++++++ .../JavaChangeSignatureUsageProcessor.java | 59 +++++++++++++------ .../JavaChangeSignatureUsageSearcher.java | 12 ---- .../util/FieldConflictsResolver.java | 6 +- .../changeSignature/MethodArgument_after.java | 11 ++++ .../VariableDeclaration_after.java | 9 +++ .../ReorderParamsOfFunctionalInterface.java | 9 +++ ...rderParamsOfFunctionalInterface_after.java | 9 +++ .../ChangeSignatureTouchLambdaTest.java | 16 +---- .../refactoring/ChangeSignatureTest.java | 7 +++ 10 files changed, 131 insertions(+), 45 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/FunctionalInterfaceChangedUsageInfo.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/MethodArgument_after.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/VariableDeclaration_after.java create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface.java create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/FunctionalInterfaceChangedUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/FunctionalInterfaceChangedUsageInfo.java new file mode 100644 index 000000000000..36e21b69d431 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/FunctionalInterfaceChangedUsageInfo.java @@ -0,0 +1,38 @@ +/* + * 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. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.usageView.UsageInfo; + +class FunctionalInterfaceChangedUsageInfo extends UsageInfo { + + private final PsiMethod myMethod; + + public FunctionalInterfaceChangedUsageInfo(PsiElement element, PsiMethod method) { + super(element); + myMethod = method; + } + + public String getDescription() { + return "Functional expression will be corrupted"; + } + + public PsiMethod getMethod() { + return myMethod; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index b3421166d490..40c23aa51674 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -110,6 +110,15 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } return true; } + else if (usage instanceof FunctionalInterfaceChangedUsageInfo) { + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(usage.getProject()); + final PsiElement element = usage.getElement(); + if (element instanceof PsiLambdaExpression) { + processMethodParams((JavaChangeInfo)changeInfo, ((FunctionalInterfaceChangedUsageInfo)usage).getMethod(), + elementFactory, PsiSubstitutor.EMPTY, ((PsiLambdaExpression)element).getParameterList(), ((PsiLambdaExpression)element).getBody()); + } + return true; + } } else { @@ -728,10 +737,24 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } PsiParameterList list = method.getParameterList(); + int newParamsLength = processMethodParams(changeInfo, baseMethod, factory, substitutor, list, method.getBody()); + fixJavadocsForChangedMethod(method, changeInfo, newParamsLength); + if (changeInfo.isExceptionSetOrOrderChanged()) { + final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo); + fixPrimaryThrowsLists(method, newExceptions); + } + } + + private static int processMethodParams(JavaChangeInfo changeInfo, + PsiMethod baseMethod, + PsiElementFactory factory, + PsiSubstitutor substitutor, + PsiParameterList list, + PsiElement methodBody) { PsiParameter[] parameters = list.getParameters(); final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters(); - final int delta = baseMethod != null ? baseMethod.getParameterList().getParametersCount() - method.getParameterList().getParametersCount() : 0; + final int delta = baseMethod != null ? baseMethod.getParameterList().getParametersCount() - list.getParametersCount() : 0; PsiParameter[] newParms = new PsiParameter[Math.max(parameterInfos.length - delta, 0)]; final String[] oldParameterNames = changeInfo.getOldParameterNames(); final String[] oldParameterTypes = changeInfo.getOldParameterTypes(); @@ -748,12 +771,15 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr parameter.getNameIdentifier().replace(newIdentifier); } - String oldType = oldParameterTypes[index]; - if (!oldType.equals(info.getTypeText())) { - parameter.normalizeDeclaration(); - PsiType newType = substitutor.substitute(info.createType(changeInfo.getMethod().getParameterList(), method.getManager())); - - parameter.getTypeElement().replace(factory.createTypeElement(newType)); + final PsiTypeElement typeElement = parameter.getTypeElement(); + if (typeElement != null) { + String oldType = oldParameterTypes[index]; + if (!oldType.equals(info.getTypeText())) { + parameter.normalizeDeclaration(); + PsiType newType = + substitutor.substitute(info.createType(changeInfo.getMethod().getParameterList(), changeInfo.getMethod().getManager())); + typeElement.replace(factory.createTypeElement(newType)); + } } } else { @@ -762,12 +788,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } - resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm()); - fixJavadocsForChangedMethod(method, changeInfo, newParms.length); - if (changeInfo.isExceptionSetOrOrderChanged()) { - final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo); - fixPrimaryThrowsLists(method, newExceptions); - } + resolveParameterVsFieldsConflicts(newParms, list, changeInfo.toRemoveParm(), methodBody); + return newParms.length; } private static PsiClassType[] getPrimaryChangedExceptionInfo(JavaChangeInfo changeInfo) throws IncorrectOperationException { @@ -804,7 +826,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr PsiParameter[] arrayed = newParameters.toArray(new PsiParameter[newParameters.size()]); boolean[] toRemoveParm = new boolean[arrayed.length]; Arrays.fill(toRemoveParm, false); - resolveParameterVsFieldsConflicts(arrayed, caller, caller.getParameterList(), toRemoveParm); + resolveParameterVsFieldsConflicts(arrayed, caller.getParameterList(), toRemoveParm, caller.getBody()); } if (toInsertThrows) { @@ -883,12 +905,12 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } private static void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms, - final PsiMethod method, final PsiParameterList list, - boolean[] toRemoveParm) throws IncorrectOperationException { + boolean[] toRemoveParm, + final PsiElement methodBody) throws IncorrectOperationException { List conflictResolvers = new ArrayList(); for (PsiParameter parameter : newParms) { - conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody())); + conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), methodBody)); } ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm); JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list); @@ -957,7 +979,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } checkContract(conflictDescriptions, method); - } else if (element instanceof PsiMethodReferenceExpression) { + } + else if (element instanceof PsiMethodReferenceExpression) { conflictDescriptions.putValue(element, "Changed method is used in method reference"); } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java index b56779ff9957..245d1d7e3ee1 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java @@ -329,16 +329,4 @@ class JavaChangeSignatureUsageSearcher { RefactoringUIUtil.getDescription(myMethod, true)); } } - - private static class FunctionalInterfaceChangedUsageInfo extends UnresolvableCollisionUsageInfo { - - public FunctionalInterfaceChangedUsageInfo(PsiElement element, PsiElement referencedElement) { - super(element, referencedElement); - } - - @Override - public String getDescription() { - return "Functional expression will be corrupted"; - } - } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/FieldConflictsResolver.java b/java/java-impl/src/com/intellij/refactoring/util/FieldConflictsResolver.java index 38a194ac2fde..51e3afa907ff 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/FieldConflictsResolver.java +++ b/java/java-impl/src/com/intellij/refactoring/util/FieldConflictsResolver.java @@ -31,12 +31,16 @@ import java.util.List; */ public class FieldConflictsResolver { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.FieldConflictsResolver"); - private final PsiCodeBlock myScope; + private final PsiElement myScope; private final PsiField myField; private final List myReferenceExpressions; private PsiClass myQualifyingClass; public FieldConflictsResolver(String name, PsiCodeBlock scope) { + this(name, (PsiElement)scope); + } + + public FieldConflictsResolver(String name, PsiElement scope) { myScope = scope; if (myScope == null) { myField = null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/MethodArgument_after.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/MethodArgument_after.java new file mode 100644 index 000000000000..944570b78ecc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/MethodArgument_after.java @@ -0,0 +1,11 @@ +interface SAM { + void foo(boolean b); +} + +class Test { + { + bar((boolean b) -> {}); + } + + void bar(SAM sam){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/VariableDeclaration_after.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/VariableDeclaration_after.java new file mode 100644 index 000000000000..126a6c7c447f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/VariableDeclaration_after.java @@ -0,0 +1,9 @@ +interface SAM { + void foo(boolean b); +} + +class Test { + { + SAM sam = (boolean b) -> {}; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface.java b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface.java new file mode 100644 index 000000000000..b582d586e97d --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface.java @@ -0,0 +1,9 @@ +interface I { + void m(int a, int b); +} + +class Test { + { + I i = (a, b) -> {}; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface_after.java b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface_after.java new file mode 100644 index 000000000000..40a29a71729e --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterface_after.java @@ -0,0 +1,9 @@ +interface I { + void m(int b, boolean a); +} + +class Test { + { + I i = (b, a) -> {}; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ChangeSignatureTouchLambdaTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ChangeSignatureTouchLambdaTest.java index eef39a1aa92a..720cfdbbb31b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ChangeSignatureTouchLambdaTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ChangeSignatureTouchLambdaTest.java @@ -15,23 +15,19 @@ */ package com.intellij.codeInsight.daemon.lambda; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiType; -import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.ChangeSignatureBaseTest; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; -import com.intellij.testFramework.IdeaTestUtil; public class ChangeSignatureTouchLambdaTest extends ChangeSignatureBaseTest { public void testVariableDeclaration() { - doTestConflict(); + doTest(null, null, null, new ParameterInfoImpl[] {new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, new ThrownExceptionInfo[0], false); } public void testMethodArgument() throws Exception { - doTestConflict(); + doTest(null, null, null, new ParameterInfoImpl[] {new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, new ThrownExceptionInfo[0], false); } public void testDefaultMethodTouched() throws Exception { @@ -42,14 +38,6 @@ public class ChangeSignatureTouchLambdaTest extends ChangeSignatureBaseTest { doTest(null, null, null, new ParameterInfoImpl[] {new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN, "false")}, new ThrownExceptionInfo[0], true); } - private void doTestConflict() { - try { - doTest(null, null, null, new ParameterInfoImpl[] {new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, new ThrownExceptionInfo[0], false); - fail("Conflict expected"); - } - catch (BaseRefactoringProcessor.ConflictsInTestsException ignored) { } - } - @Override protected String getRelativePath() { return "/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/"; diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index afcb86dc945a..8d82e7a39b6e 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -333,6 +333,13 @@ public class ChangeSignatureTest extends ChangeSignatureBaseTest { }, false); } + public void testReorderParamsOfFunctionalInterface() { + doTest(null, null, null, method -> new ParameterInfoImpl[]{ + new ParameterInfoImpl(1, "b", PsiType.INT), + new ParameterInfoImpl(0, "a", PsiType.BOOLEAN) + }, false); + } + public void testMethodParametersAlignmentAfterMethodNameChange() { getJavaSettings().ALIGN_MULTILINE_PARAMETERS = true; getJavaSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; From 3fd8dfd38c619b257334e83e6540b4e9372ea7a6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 11:45:21 +0100 Subject: [PATCH 039/825] change signature: convert method reference to lambda if SAM method signature was changed (IDEA-150138) --- .../JavaChangeSignatureUsageProcessor.java | 13 ++++++--- ...ctionalInterfaceExpandMethodReference.java | 11 ++++++++ ...lInterfaceExpandMethodReference_after.java | 11 ++++++++ .../refactoring/ChangeSignatureBaseTest.java | 27 ++++++++++++++++++- .../refactoring/ChangeSignatureTest.java | 8 ++++++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference.java create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 40c23aa51674..a26df80d7c28 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -113,9 +113,16 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr else if (usage instanceof FunctionalInterfaceChangedUsageInfo) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(usage.getProject()); final PsiElement element = usage.getElement(); + final PsiMethod interfaceMethod = ((FunctionalInterfaceChangedUsageInfo)usage).getMethod(); if (element instanceof PsiLambdaExpression) { - processMethodParams((JavaChangeInfo)changeInfo, ((FunctionalInterfaceChangedUsageInfo)usage).getMethod(), - elementFactory, PsiSubstitutor.EMPTY, ((PsiLambdaExpression)element).getParameterList(), ((PsiLambdaExpression)element).getBody()); + processMethodParams((JavaChangeInfo)changeInfo, interfaceMethod, + elementFactory, PsiSubstitutor.EMPTY, ((PsiLambdaExpression)element).getParameterList(), ((PsiLambdaExpression)element).getBody()); + } + else if (element instanceof PsiMethodReferenceExpression) { + final PsiLambdaExpression lambdaExpression = + LambdaRefactoringUtil.convertMethodReferenceToLambda((PsiMethodReferenceExpression)element, false, true); + processMethodParams(((JavaChangeInfo)changeInfo), interfaceMethod, elementFactory, PsiSubstitutor.EMPTY, + lambdaExpression.getParameterList(), lambdaExpression.getBody()); } return true; } @@ -981,7 +988,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr checkContract(conflictDescriptions, method); } else if (element instanceof PsiMethodReferenceExpression) { - conflictDescriptions.putValue(element, "Changed method is used in method reference"); + conflictDescriptions.putValue(element, "Changed method is used in method reference. Proceeding would result in conversion to lambda expression"); } } diff --git a/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference.java b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference.java new file mode 100644 index 000000000000..9adff1442040 --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference.java @@ -0,0 +1,11 @@ +interface I { + void m(int a, int b); +} + +class Test { + { + I i = this::foo; + } + + private void foo(int a, int b) {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference_after.java b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference_after.java new file mode 100644 index 000000000000..067fdab032dd --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReorderParamsOfFunctionalInterfaceExpandMethodReference_after.java @@ -0,0 +1,11 @@ +interface I { + void m(int b, int a); +} + +class Test { + { + I i = (b, a) -> foo(a, b); + } + + private void foo(int a, int b) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureBaseTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureBaseTest.java index c2ba39a70750..7233b17f6009 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureBaseTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureBaseTest.java @@ -17,11 +17,13 @@ package com.intellij.refactoring; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.TargetElementUtil; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; +import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -96,6 +98,16 @@ public abstract class ChangeSignatureBaseTest extends LightRefactoringTestCase { GenParams genParams, GenExceptions genExceptions, boolean generateDelegate) { + doTest(newVisibility, newName, newReturnType, genParams, genExceptions, generateDelegate, false); + } + + protected void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility, + @Nullable String newName, + @Nullable String newReturnType, + GenParams genParams, + GenExceptions genExceptions, + boolean generateDelegate, + boolean skipConflict) { String basePath = getRelativePath() + getTestName(false); configureByFile(basePath + ".java"); PsiElement targetElement = TargetElementUtil.findTargetElement(getEditor(), TargetElementUtil.ELEMENT_NAME_ACCEPTED); @@ -104,7 +116,20 @@ public abstract class ChangeSignatureBaseTest extends LightRefactoringTestCase { PsiType newType = newReturnType != null ? myFactory.createTypeFromText(newReturnType, method) : method.getReturnType(); new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility, newName != null ? newName : method.getName(), - newType, genParams.genParams(method), genExceptions.genExceptions(method)).run(); + newType, genParams.genParams(method), genExceptions.genExceptions(method)) { + @Override + protected boolean preprocessUsages(@NotNull Ref refUsages) { + try { + return super.preprocessUsages(refUsages); + } + catch (ConflictsInTestsException e) { + if (skipConflict) { + return true; + } + throw e; + } + } + }.run(); checkResultByFile(basePath + "_after.java"); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index 8d82e7a39b6e..6d7531e421cb 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -340,6 +340,14 @@ public class ChangeSignatureTest extends ChangeSignatureBaseTest { }, false); } + public void testReorderParamsOfFunctionalInterfaceExpandMethodReference() { + GenParams genParams = method -> new ParameterInfoImpl[]{ + new ParameterInfoImpl(1, "b", PsiType.INT), + new ParameterInfoImpl(0, "a", PsiType.INT) + }; + doTest(null, null, null, genParams, new SimpleExceptionsGen(), false, true); + } + public void testMethodParametersAlignmentAfterMethodNameChange() { getJavaSettings().ALIGN_MULTILINE_PARAMETERS = true; getJavaSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; From 1b3ce12a930562f734beb1c5b8e0a56ebbc73c89 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 12:22:47 +0100 Subject: [PATCH 040/825] anonym -> lambda: accept refs to initialized final fields in classes inside constructors (IDEA-150322) --- .../AnonymousCanBeLambdaInspection.java | 1 + .../afterInitializedFinalFieldInConstructor.java | 7 +++++++ .../beforeInitializedFinalFieldInConstructor.java | 12 ++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterInitializedFinalFieldInConstructor.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeInitializedFinalFieldInConstructor.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index 808af618006b..87791a12f50b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -511,6 +511,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection final PsiElement resolved = expression.resolve(); if (resolved instanceof PsiField && ((PsiField)resolved).hasModifierProperty(PsiModifier.FINAL) && + ((PsiField)resolved).getInitializer() == null && ((PsiField)resolved).getContainingClass() == method.getContainingClass()) { try { final PsiCodeBlock constructorBody = method.getBody(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterInitializedFinalFieldInConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterInitializedFinalFieldInConstructor.java new file mode 100644 index 000000000000..d934fa2ec7ef --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterInitializedFinalFieldInConstructor.java @@ -0,0 +1,7 @@ +// "Replace with lambda" "true" +class HelloLambda { + public HelloLambda() { + Runnable r = () -> System.out.println(x); + } + private final int x = 0; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeInitializedFinalFieldInConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeInitializedFinalFieldInConstructor.java new file mode 100644 index 000000000000..0b505b590b5a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeInitializedFinalFieldInConstructor.java @@ -0,0 +1,12 @@ +// "Replace with lambda" "true" +class HelloLambda { + public HelloLambda() { + Runnable r = new Runnable() { + @Override + public void run () { + System.out.println(x); + } + } ; + } + private final int x = 0; +} \ No newline at end of file From 84b6b19292029bfde29699e99304d4c9babe84d6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 12:37:26 +0100 Subject: [PATCH 041/825] safe delete: more precise check for safe delete top level classes (IDEA-150276) --- .../safeDelete/JavaSafeDeleteProcessor.java | 10 +++++++--- .../safeDelete/InnerClassUsedInTheSameFile.java | 5 +++++ .../com/intellij/refactoring/SafeDeleteTest.java | 11 +++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/refactoring/safeDelete/InnerClassUsedInTheSameFile.java diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java index a3fd53d37421..b7bd9384442a 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java @@ -519,9 +519,13 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase { } LOG.assertTrue(element.getTextRange() != null); final PsiFile containingFile = psiClass.getContainingFile(); - final boolean sameFileWithSingleClass = containingFile instanceof PsiClassOwner && - ((PsiClassOwner)containingFile).getClasses().length == 1 && - element.getContainingFile() == containingFile; + boolean sameFileWithSingleClass = false; + if (containingFile instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)containingFile).getClasses(); + sameFileWithSingleClass = classes.length == 1 && + classes[0] == psiClass && + element.getContainingFile() == containingFile; + } usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiClass, sameFileWithSingleClass || isInNonStaticImport(element))); } return true; diff --git a/java/java-tests/testData/refactoring/safeDelete/InnerClassUsedInTheSameFile.java b/java/java-tests/testData/refactoring/safeDelete/InnerClassUsedInTheSameFile.java new file mode 100644 index 000000000000..fdfab00afc52 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/InnerClassUsedInTheSameFile.java @@ -0,0 +1,5 @@ +class Test { + public void method(Foo p) {} + + static class Foo {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java index 719a074891ef..6dbea8657cf8 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java @@ -289,6 +289,17 @@ public class SafeDeleteTest extends MultiFileTestCase { doTest("ClassWithInnerStaticImport"); } + public void testInnerClassUsedInTheSameFile() throws Exception { + try { + doSingleFileTest(); + fail("Side effect was ignored"); + } + catch (BaseRefactoringProcessor.ConflictsInTestsException e) { + String message = e.getMessage(); + assertEquals("class Test.Foo has 1 usage that is not safe to delete.", message); + } + } + private void doTest(@NonNls final String qClassName) throws Exception { doTest((rootDir, rootAfter) -> { SafeDeleteTest.this.performAction(qClassName); From a599a786ff01c6bc339b587caace835e451d33ae Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 12:56:45 +0100 Subject: [PATCH 042/825] show coverage for interfaces if no default methods were found, they would be skipped (IDEA-150079) --- .../intellij/coverage/view/JavaCoverageViewExtension.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 99799ff40d8f..73341869e03a 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -95,11 +95,8 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { public PackageAnnotator.SummaryCoverageInfo getSummaryCoverageForNodeValue(Object value) { if (value instanceof PsiClass) { - //no coverage gathered - if (!((PsiClass)value).isInterface()) { - final String qualifiedName = ((PsiClass)value).getQualifiedName(); - return myAnnotator.getClassCoverageInfo(qualifiedName); - } + final String qualifiedName = ((PsiClass)value).getQualifiedName(); + return myAnnotator.getClassCoverageInfo(qualifiedName); } if (value instanceof PsiPackage) { return myAnnotator.getPackageCoverageInfo((PsiPackage)value, myStateBean.myFlattenPackages); From f7bbd49f75b28563f8c7c9cadcc2403261ef809e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 16:30:04 +0100 Subject: [PATCH 043/825] (on-the-fly) static import of constant --- .../quickfix/DefaultQuickFixProvider.java | 1 + .../quickfix/MyStaticMembersProcessor.java | 194 +++++++++++ .../quickfix/StaticImportConstantFix.java | 102 ++++++ .../impl/quickfix/StaticImportMemberFix.java | 146 ++++++++ .../impl/quickfix/StaticImportMethodFix.java | 320 ++++-------------- .../StaticImportMethodQuestionAction.java | 61 ++-- .../staticImportConstant/afterConstant.java | 17 + .../afterConstantInAssignment.java | 17 + .../staticImportConstant/beforeConstant.java | 15 + .../beforeConstantInAssignment.java | 15 + .../quickFix/StaticImportConstantTest.java | 23 ++ .../src/messages/QuickFixBundle.properties | 1 + 12 files changed, 628 insertions(+), 284 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MyStaticMembersProcessor.java create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMemberFix.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstant.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstantInAssignment.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstant.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstantInAssignment.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportConstantTest.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java index b5dc43e0f84a..7151726b0fb2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java @@ -39,6 +39,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) { QuickFixFactory factory = QuickFixFactory.getInstance(); registrar.register(new ImportClassFix(ref)); + registrar.register(new StaticImportConstantFix(ref)); registrar.register(factory.createSetupJDKFix()); OrderEntryFix.registerFixes(registrar, ref); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MyStaticMembersProcessor.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MyStaticMembersProcessor.java new file mode 100644 index 000000000000..1848382e04ec --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MyStaticMembersProcessor.java @@ -0,0 +1,194 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.completion.JavaCompletionUtil; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.proximity.PsiProximityComparator; +import com.intellij.util.ArrayUtilRt; +import com.intellij.util.Processor; +import com.intellij.util.containers.LinkedMultiMap; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +abstract class MyStaticMembersProcessor implements Processor { + private final MultiMap myDeprecated = new LinkedMultiMap(); + private final MultiMap mySuggestions = new LinkedMultiMap(); + + private final Map myPossibleClasses = new HashMap(); + + private final PsiElement myPlace; + private PsiType myExpectedType; + + protected MyStaticMembersProcessor(PsiElement place) { + myPlace = place; + myExpectedType = PsiType.NULL; + } + + protected abstract boolean isApplicable(T member, PsiElement place); + + @NotNull + public List getMembersToImport() { + final List list = new ArrayList(); + final List applicableList = new ArrayList(); + for (Map.Entry> methodEntry : mySuggestions.entrySet()) { + registerMember(methodEntry.getKey(), methodEntry.getValue(), list, applicableList); + } + + for (Map.Entry> deprecatedMethod : myDeprecated.entrySet()) { + registerMember(deprecatedMethod.getKey(), deprecatedMethod.getValue(), list, applicableList); + } + + List result = applicableList.isEmpty() ? list : applicableList; + for (int i = result.size() - 1; i >= 0; i--) { + ProgressManager.checkCanceled(); + T method = result.get(i); + // check for manually excluded + if (StaticImportMethodFix.isExcluded(method)) { + result.remove(i); + } + } + Collections.sort(result, new PsiProximityComparator(myPlace)); + return result; + } + + public PsiType getExpectedType() { + if (myExpectedType == PsiType.NULL) { + myExpectedType = getExpectedTypeInternal(); + } + return myExpectedType; + } + + private PsiType getExpectedTypeInternal() { + if (myPlace == null) return null; + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(myPlace.getParent()); + + if (parent instanceof PsiVariable) { + if (myPlace.equals(PsiUtil.skipParenthesizedExprDown(((PsiVariable)parent).getInitializer()))) { + return ((PsiVariable)parent).getType(); + } + } + else if (parent instanceof PsiAssignmentExpression) { + if (myPlace.equals(PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)parent).getRExpression()))) { + return ((PsiAssignmentExpression)parent).getLExpression().getType(); + } + } + else if (parent instanceof PsiReturnStatement) { + final PsiElement psiElement = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, PsiMethod.class); + if (psiElement instanceof PsiLambdaExpression) { + return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)psiElement).getFunctionalInterfaceType()); + } + else if (psiElement instanceof PsiMethod) { + return ((PsiMethod)psiElement).getReturnType(); + } + } + else if (parent instanceof PsiExpressionList) { + final PsiElement pParent = parent.getParent(); + if (pParent instanceof PsiCallExpression && parent.equals(((PsiCallExpression)pParent).getArgumentList())) { + final JavaResolveResult resolveResult = ((PsiCallExpression)pParent).resolveMethodGenerics(); + final PsiElement psiElement = resolveResult.getElement(); + if (psiElement instanceof PsiMethod) { + final PsiMethod psiMethod = (PsiMethod)psiElement; + final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + final int idx = ArrayUtilRt.find(((PsiExpressionList)parent).getExpressions(), PsiUtil.skipParenthesizedExprUp(myPlace)); + if (idx > -1 && parameters.length > 0) { + PsiType parameterType = parameters[Math.min(idx, parameters.length - 1)].getType(); + if (idx >= parameters.length - 1) { + final PsiParameter lastParameter = parameters[parameters.length - 1]; + if (lastParameter.isVarArgs()) { + parameterType = ((PsiEllipsisType)lastParameter.getType()).getComponentType(); + } + } + return resolveResult.getSubstitutor().substitute(parameterType); + } + else { + return null; + } + } + } + } + else if (parent instanceof PsiLambdaExpression) { + return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType()); + } + return null; + } + + @Override + public boolean process(T member) { + ProgressManager.checkCanceled(); + if (JavaCompletionUtil.isInExcludedPackage(member, false) || !member.hasModifierProperty(PsiModifier.STATIC)) return true; + PsiFile file = member.getContainingFile(); + final PsiClass containingClass = member.getContainingClass(); + if (file instanceof PsiJavaFile + //do not show methods from default package + && !((PsiJavaFile)file).getPackageName().isEmpty()) { + if (isEffectivelyDeprecated(member)) { + myDeprecated.putValue(containingClass, member); + return processCondition(); + } + mySuggestions.putValue(containingClass, member); + } + return processCondition(); + } + + private boolean isEffectivelyDeprecated(T member) { + if (((PsiDocCommentOwner)member).isDeprecated()) { + return true; + } + + PsiClass aClass = member.getContainingClass(); + while (aClass != null) { + if (aClass.isDeprecated()) { + return true; + } + aClass = aClass.getContainingClass(); + } + return false; + } + + private boolean processCondition() { + return mySuggestions.size() + myDeprecated.size() < 50; + } + + private void registerMember(PsiClass containingClass, + Collection members, + List list, + List applicableList) { + final Boolean alreadyMentioned = myPossibleClasses.get(containingClass); + if (alreadyMentioned == Boolean.TRUE) return; + if (alreadyMentioned == null) { + if (!members.isEmpty()) { + list.add(members.iterator().next()); + } + myPossibleClasses.put(containingClass, false); + } + for (T member : members) { + if (!PsiUtil.isAccessible(myPlace.getProject(), member, myPlace, containingClass)) { + continue; + } + if (isApplicable(member, myPlace)) { + applicableList.add(member); + myPossibleClasses.put(containingClass, true); + break; + } + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java new file mode 100644 index 000000000000..489596bc50e0 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java @@ -0,0 +1,102 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiShortNamesCache; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; +import com.intellij.psi.util.TypeConversionUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class StaticImportConstantFix extends StaticImportMemberFix { + private final SmartPsiElementPointer myRef; + + public StaticImportConstantFix(@NotNull PsiJavaCodeReferenceElement referenceElement) { + myRef = SmartPointerManager.getInstance(referenceElement.getProject()).createSmartPsiElementPointer(referenceElement); + } + + @NotNull + @Override + protected String getBaseText() { + return "Static import constant"; + } + + @NotNull + @Override + protected String getMemberPresentableText(PsiField field) { + return PsiFormatUtil.formatVariable(field, PsiFormatUtilBase.SHOW_NAME | + PsiFormatUtilBase.SHOW_CONTAINING_CLASS | + PsiFormatUtilBase.SHOW_FQ_NAME, PsiSubstitutor.EMPTY); + } + + @NotNull + @Override + protected List getMembersToImport() { + final Project project = myRef.getProject(); + PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); + final PsiJavaCodeReferenceElement element = myRef.getElement(); + String name = element != null ? element.getReferenceName() : null; + if (name == null) return Collections.emptyList(); + final MyStaticMembersProcessor processor = new MyStaticMembersProcessor(element) { + @Override + protected boolean isApplicable(PsiField field, PsiElement place) { + final PsiType expectedType = getExpectedType(); + return expectedType == null || TypeConversionUtil.isAssignable(expectedType, field.getType()); + } + }; + cache.processFieldsWithName(name, processor, element.getResolveScope(), null); + return processor.getMembersToImport(); + } + + @NotNull + protected StaticImportMethodQuestionAction createQuestionAction(List methodsToImport, @NotNull Project project, Editor editor) { + return new StaticImportMethodQuestionAction(project, editor, methodsToImport, myRef) { + @NotNull + @Override + protected String getPopupTitle() { + return QuickFixBundle.message("field.to.import.chooser.title"); + } + }; + } + + @Nullable + @Override + protected PsiElement getElement() { + return myRef.getElement(); + } + + @Nullable + @Override + protected PsiElement getQualifierExpression() { + final PsiJavaCodeReferenceElement element = myRef.getElement(); + return element != null ? element.getQualifier() : null; + } + + @Nullable + @Override + protected PsiElement resolveRef() { + final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)getElement(); + return referenceElement != null ? referenceElement.resolve() : null; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMemberFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMemberFix.java new file mode 100644 index 000000000000..481417926ab6 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMemberFix.java @@ -0,0 +1,146 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.QuestionAction; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.HintAction; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.PsiMember; +import com.intellij.psi.util.PsiUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public abstract class StaticImportMemberFix implements IntentionAction, HintAction { + private List candidates; + + @NotNull protected abstract String getBaseText(); + @NotNull protected abstract String getMemberPresentableText(T t); + + @Override + @NotNull + public String getText() { + String text = getBaseText(); + if (candidates != null && candidates.size() == 1) { + text += " '" + getMemberPresentableText(candidates.get(0)) + "'"; + } + else { + text += "..."; + } + return text; + } + + @Override + @NotNull + public String getFamilyName() { + return getText(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return PsiUtil.isLanguageLevel5OrHigher(file) + && file instanceof PsiJavaFile + && getElement() != null + && getElement().isValid() + && getQualifierExpression() == null + && resolveRef() == null + && file.getManager().isInProject(file) + && !(candidates == null ? candidates = getMembersToImport() : candidates).isEmpty() + ; + } + + @NotNull protected abstract List getMembersToImport(); + @NotNull protected abstract QuestionAction createQuestionAction(List methodsToImport, @NotNull Project project, Editor editor); + + @Nullable protected abstract PsiElement getElement(); + @Nullable protected abstract PsiElement getQualifierExpression(); + @Nullable protected abstract PsiElement resolveRef(); + + @Override + public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + final List methodsToImport = getMembersToImport(); + if (methodsToImport.isEmpty()) return; + createQuestionAction(methodsToImport, project, editor).execute(); + } + }); + } + + private ImportClassFixBase.Result doFix(Editor editor) { + if (candidates.isEmpty()) { + return ImportClassFixBase.Result.POPUP_NOT_SHOWN; + } + + final PsiElement element = getElement(); + if (element == null) { + return ImportClassFixBase.Result.POPUP_NOT_SHOWN; + } + + final QuestionAction action = createQuestionAction(candidates, element.getProject(), editor); + if (candidates.size() == 1 && ImportClassFixBase.canAddUnambiguousImport(element.getContainingFile())) { + CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { + @Override + public void run() { + action.execute(); + } + }); + return ImportClassFixBase.Result.CLASS_AUTO_IMPORTED; + } + + String hintText = ShowAutoImportPass.getMessage(candidates.size() > 1, getMemberPresentableText(candidates.get(0))); + if (!ApplicationManager.getApplication().isUnitTestMode() && !HintManager.getInstance().hasShownHintsThatWillHideByOtherHint(true)) { + final TextRange textRange = element.getTextRange(); + HintManager.getInstance().showQuestionHint(editor, hintText, + textRange.getStartOffset(), + textRange.getEndOffset(), action); + } + return ImportClassFixBase.Result.POPUP_SHOWN; + } + + + + @Override + public boolean startInWriteAction() { + return false; + } + + @Override + public boolean showHint(@NotNull Editor editor) { + final PsiElement callExpression = getElement(); + if (callExpression == null || + getQualifierExpression() != null) { + return false; + } + ImportClassFixBase.Result result = doFix(editor); + return result == ImportClassFixBase.Result.POPUP_SHOWN || result == ImportClassFixBase.Result.CLASS_AUTO_IMPORTED; + } + +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java index 79e2f69eee20..7a960fdd8188 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java @@ -15,245 +15,56 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.JavaProjectCodeInsightSettings; -import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.HintAction; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; -import com.intellij.psi.util.*; -import com.intellij.psi.util.proximity.PsiProximityComparator; -import com.intellij.util.ArrayUtilRt; -import com.intellij.util.Processor; -import com.intellij.util.containers.LinkedMultiMap; -import com.intellij.util.containers.MultiMap; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collections; +import java.util.List; -public class StaticImportMethodFix implements IntentionAction, HintAction { - private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix"); +public class StaticImportMethodFix extends StaticImportMemberFix { private final SmartPsiElementPointer myMethodCall; - private List candidates; public StaticImportMethodFix(@NotNull PsiMethodCallExpression methodCallExpression) { myMethodCall = SmartPointerManager.getInstance(methodCallExpression.getProject()).createSmartPsiElementPointer(methodCallExpression); } + @NotNull @Override - @NotNull - public String getText() { - String text = QuickFixBundle.message("static.import.method.text"); - if (candidates != null && candidates.size() == 1) { - text += " '" + getMethodPresentableText() + "'"; - } - else { - text += "..."; - } - return text; + protected String getBaseText() { + return QuickFixBundle.message("static.import.method.text"); } @NotNull - private String getMethodPresentableText() { - return PsiFormatUtil.formatMethod(candidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | - PsiFormatUtilBase.SHOW_CONTAINING_CLASS | - PsiFormatUtilBase.SHOW_FQ_NAME, 0); - } - @Override - @NotNull - public String getFamilyName() { - return getText(); + protected String getMemberPresentableText(PsiMethod method) { + return PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | + PsiFormatUtilBase.SHOW_CONTAINING_CLASS | + PsiFormatUtilBase.SHOW_FQ_NAME, 0); } + @NotNull @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return PsiUtil.isLanguageLevel5OrHigher(file) - && file instanceof PsiJavaFile - && myMethodCall.getElement() != null - && myMethodCall.getElement().isValid() - && myMethodCall.getElement().getMethodExpression().getQualifierExpression() == null - && myMethodCall.getElement().resolveMethod() == null - && file.getManager().isInProject(file) - && !(candidates == null ? candidates = getMethodsToImport() : candidates).isEmpty() - ; - } - - private PsiType getExpectedType() { - final PsiMethodCallExpression methodCall = myMethodCall.getElement(); - if (methodCall == null) return null; - final PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent()); - - if (parent instanceof PsiVariable) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiVariable)parent).getInitializer()))) { - return ((PsiVariable)parent).getType(); - } - } - else if (parent instanceof PsiAssignmentExpression) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)parent).getRExpression()))) { - return ((PsiAssignmentExpression)parent).getLExpression().getType(); - } - } - else if (parent instanceof PsiReturnStatement) { - final PsiElement psiElement = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, PsiMethod.class); - if (psiElement instanceof PsiLambdaExpression) { - return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)psiElement).getFunctionalInterfaceType()); - } - else if (psiElement instanceof PsiMethod) { - return ((PsiMethod)psiElement).getReturnType(); - } - } - else if (parent instanceof PsiExpressionList) { - final PsiElement pParent = parent.getParent(); - if (pParent instanceof PsiCallExpression && parent.equals(((PsiCallExpression)pParent).getArgumentList())) { - final JavaResolveResult resolveResult = ((PsiCallExpression)pParent).resolveMethodGenerics(); - final PsiElement psiElement = resolveResult.getElement(); - if (psiElement instanceof PsiMethod) { - final PsiMethod psiMethod = (PsiMethod)psiElement; - final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); - final int idx = ArrayUtilRt.find(((PsiExpressionList)parent).getExpressions(), PsiUtil.skipParenthesizedExprUp(methodCall)); - if (idx > -1 && parameters.length > 0) { - PsiType parameterType = parameters[Math.min(idx, parameters.length - 1)].getType(); - if (idx >= parameters.length - 1) { - final PsiParameter lastParameter = parameters[parameters.length - 1]; - if (lastParameter.isVarArgs()) { - parameterType = ((PsiEllipsisType)lastParameter.getType()).getComponentType(); - } - } - return resolveResult.getSubstitutor().substitute(parameterType); - } - else { - return null; - } - } - } - } - else if (parent instanceof PsiLambdaExpression) { - return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType()); - } - return null; - } - - @NotNull - private List getMethodsToImport() { + protected List getMembersToImport() { final Project project = myMethodCall.getProject(); PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); final PsiMethodCallExpression element = myMethodCall.getElement(); - PsiReferenceExpression reference = element.getMethodExpression(); - final PsiExpressionList argumentList = element.getArgumentList(); - String name = reference.getReferenceName(); - final List list = new ArrayList(); - if (name == null) return list; - GlobalSearchScope scope = element.getResolveScope(); - final Map possibleClasses = new HashMap(); - final PsiType expectedType = getExpectedType(); - final List applicableList = new ArrayList(); - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper(); - - final MultiMap deprecated = new LinkedMultiMap(); - final MultiMap suggestions = new LinkedMultiMap(); - class RegisterMethodsProcessor { - private void registerMethod(PsiClass containingClass, Collection methods) { - final Boolean alreadyMentioned = possibleClasses.get(containingClass); - if (alreadyMentioned == Boolean.TRUE) return; - if (alreadyMentioned == null) { - if (!methods.isEmpty()) { - list.add(methods.iterator().next()); - } - possibleClasses.put(containingClass, false); - } - for (PsiMethod method : methods) { - if (!PsiUtil.isAccessible(project, method, element, containingClass)) { - continue; - } - PsiSubstitutor substitutorForMethod = resolveHelper - .inferTypeArguments(method.getTypeParameters(), method.getParameterList().getParameters(), - argumentList.getExpressions(), - PsiSubstitutor.EMPTY, element.getParent(), DefaultParameterTypeInferencePolicy.INSTANCE); - if (PsiUtil.isApplicable(method, substitutorForMethod, argumentList)) { - final PsiType returnType = substitutorForMethod.substitute(method.getReturnType()); - if (expectedType == null || returnType == null || TypeConversionUtil.isAssignable(expectedType, returnType)) { - applicableList.add(method); - possibleClasses.put(containingClass, true); - break; - } - } - } - } - } - - final RegisterMethodsProcessor registrar = new RegisterMethodsProcessor(); - cache.processMethodsWithName(name, scope, new Processor() { - @Override - public boolean process(PsiMethod method) { - ProgressManager.checkCanceled(); - if (JavaCompletionUtil.isInExcludedPackage(method, false) - || !method.hasModifierProperty(PsiModifier.STATIC)) return true; - PsiFile file = method.getContainingFile(); - final PsiClass containingClass = method.getContainingClass(); - if (file instanceof PsiJavaFile - //do not show methods from default package - && !((PsiJavaFile)file).getPackageName().isEmpty()) { - if (isEffectivelyDeprecated(method)) { - deprecated.putValue(containingClass, method); - return processCondition(); - } - suggestions.putValue(containingClass, method); - } - return processCondition(); - } - - private boolean isEffectivelyDeprecated(PsiMethod method) { - if (method.isDeprecated()) { - return true; - } - PsiClass aClass = method.getContainingClass(); - while (aClass != null) { - if (aClass.isDeprecated()) { - return true; - } - aClass = aClass.getContainingClass(); - } - return false; - } - - private boolean processCondition() { - return suggestions.size() + deprecated.size() < 50; - } - }); - - for (Map.Entry> methodEntry : suggestions.entrySet()) { - registrar.registerMethod(methodEntry.getKey(), methodEntry.getValue()); - } - - for (Map.Entry> deprecatedMethod : deprecated.entrySet()) { - registrar.registerMethod(deprecatedMethod.getKey(), deprecatedMethod.getValue()); - } - - List result = applicableList.isEmpty() ? list : applicableList; - for (int i = result.size() - 1; i >= 0; i--) { - ProgressManager.checkCanceled(); - PsiMethod method = result.get(i); - // check for manually excluded - if (isExcluded(method)) { - result.remove(i); - } - } - Collections.sort(result, new PsiProximityComparator(argumentList)); - return result; + PsiReferenceExpression reference = element == null ? null : element.getMethodExpression(); + String name = reference == null ? null : reference.getReferenceName(); + if (name == null) return Collections.emptyList(); + final MyStaticMembersProcessor processor = new MyStaticMethodProcessor(project, element); + cache.processMethodsWithName(name, element.getResolveScope(), processor); + return processor.getMembersToImport(); } public static boolean isExcluded(PsiMember method) { @@ -261,68 +72,51 @@ public class StaticImportMethodFix implements IntentionAction, HintAction { return name != null && JavaProjectCodeInsightSettings.getSettings(method.getProject()).isExcluded(name); } - @Override - public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) { - if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - final List methodsToImport = getMethodsToImport(); - if (methodsToImport.isEmpty()) return; - createQuestionAction(methodsToImport, project, editor).execute(); - } - }); - } - @NotNull - private StaticImportMethodQuestionAction createQuestionAction(List methodsToImport, @NotNull Project project, Editor editor) { - return new StaticImportMethodQuestionAction(project, editor, methodsToImport, myMethodCall); + protected StaticImportMethodQuestionAction createQuestionAction(List methodsToImport, @NotNull Project project, Editor editor) { + return new StaticImportMethodQuestionAction(project, editor, methodsToImport, myMethodCall); } - private ImportClassFixBase.Result doFix(Editor editor) { - if (candidates.isEmpty()) { - return ImportClassFixBase.Result.POPUP_NOT_SHOWN; - } - - final StaticImportMethodQuestionAction action = createQuestionAction(candidates, myMethodCall.getProject(), editor); + @Nullable + @Override + protected PsiElement getElement() { + return myMethodCall.getElement(); + } + @Nullable + @Override + protected PsiElement getQualifierExpression() { final PsiMethodCallExpression element = myMethodCall.getElement(); - if (element == null) { - return ImportClassFixBase.Result.POPUP_NOT_SHOWN; - } - - if (candidates.size() == 1 && ImportClassFixBase.canAddUnambiguousImport(element.getContainingFile())) { - CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { - @Override - public void run() { - action.execute(); - } - }); - return ImportClassFixBase.Result.CLASS_AUTO_IMPORTED; - } - - String hintText = ShowAutoImportPass.getMessage(candidates.size() > 1, getMethodPresentableText()); - if (!ApplicationManager.getApplication().isUnitTestMode() && !HintManager.getInstance().hasShownHintsThatWillHideByOtherHint(true)) { - final TextRange textRange = element.getTextRange(); - HintManager.getInstance().showQuestionHint(editor, hintText, - textRange.getStartOffset(), - textRange.getEndOffset(), action); - } - return ImportClassFixBase.Result.POPUP_SHOWN; + return element != null ? element.getMethodExpression().getQualifierExpression() : null; } + @Nullable @Override - public boolean startInWriteAction() { - return false; + protected PsiElement resolveRef() { + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)getElement(); + return methodCallExpression != null ? methodCallExpression.resolveMethod() : null; } - @Override - public boolean showHint(@NotNull Editor editor) { - final PsiMethodCallExpression callExpression = myMethodCall.getElement(); - if (callExpression == null || callExpression.getMethodExpression().getQualifierExpression() != null) { + private static class MyStaticMethodProcessor extends MyStaticMembersProcessor { + + private MyStaticMethodProcessor(Project project, PsiMethodCallExpression place) { + super(place); + } + + @Override + protected boolean isApplicable(PsiMethod method, PsiElement place) { + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper(); + final PsiExpressionList argumentList = ((PsiMethodCallExpression)place).getArgumentList(); + PsiSubstitutor substitutorForMethod = resolveHelper + .inferTypeArguments(method.getTypeParameters(), method.getParameterList().getParameters(), + argumentList.getExpressions(), + PsiSubstitutor.EMPTY, place.getParent(), DefaultParameterTypeInferencePolicy.INSTANCE); + if (PsiUtil.isApplicable(method, substitutorForMethod, argumentList)) { + final PsiType returnType = substitutorForMethod.substitute(method.getReturnType()); + final PsiType expectedType = getExpectedType(); + return expectedType == null || returnType == null || TypeConversionUtil.isAssignable(expectedType, returnType); + } return false; } - ImportClassFixBase.Result result = doFix(editor); - return result == ImportClassFixBase.Result.POPUP_SHOWN || result == ImportClassFixBase.Result.CLASS_AUTO_IMPORTED; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java index 4f83e31e79ed..bfd9e4c52dcd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java @@ -19,7 +19,8 @@ import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.actions.AddImportAction; import com.intellij.codeInsight.hint.QuestionAction; import com.intellij.codeInsight.intention.impl.AddSingleMemberStaticImportAction; -import com.intellij.ide.util.MethodCellRenderer; +import com.intellij.ide.util.PsiClassListCellRenderer; +import com.intellij.ide.util.PsiElementListCellRenderer; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -29,7 +30,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.psi.*; -import com.intellij.psi.util.PsiFormatUtilBase; +import com.intellij.psi.presentation.java.ClassPresentationUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.ui.popup.list.PopupListElementRenderer; @@ -42,33 +43,38 @@ import javax.swing.*; import java.awt.*; import java.util.List; -public class StaticImportMethodQuestionAction implements QuestionAction { +public class StaticImportMethodQuestionAction implements QuestionAction { private static final Logger LOG = Logger.getInstance("#" + StaticImportMethodQuestionAction.class.getName()); private final Project myProject; private final Editor myEditor; - private List myCandidates; - private final SmartPsiElementPointer myMethodCall; + private List myCandidates; + private final SmartPsiElementPointer myRef; public StaticImportMethodQuestionAction(Project project, Editor editor, - List candidates, - SmartPsiElementPointer methodCall) { + List candidates, + SmartPsiElementPointer ref) { myProject = project; myEditor = editor; myCandidates = candidates; - myMethodCall = methodCall; + myRef = ref; + } + + @NotNull + protected String getPopupTitle() { + return QuickFixBundle.message("method.to.import.chooser.title"); } @Override public boolean execute() { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - final PsiMethodCallExpression element = myMethodCall.getElement(); + final PsiElement element = myRef.getElement(); if (element == null || !element.isValid()){ return false; } - for (PsiMethod targetMethod : myCandidates) { + for (T targetMethod : myCandidates) { if (!targetMethod.isValid()) { return false; } @@ -83,7 +89,7 @@ public class StaticImportMethodQuestionAction implements QuestionAction { return true; } - private void doImport(final PsiMethod toImport) { + private void doImport(final T toImport) { final Project project = toImport.getProject(); CommandProcessor.getInstance().executeCommand(project, new Runnable(){ @Override @@ -92,7 +98,7 @@ public class StaticImportMethodQuestionAction implements QuestionAction { @Override public void run() { try { - PsiMethodCallExpression element = myMethodCall.getElement(); + PsiElement element = myRef.getElement(); if (element != null) { AddSingleMemberStaticImportAction.bindAllClassRefs(element.getContainingFile(), toImport, toImport.getName(), toImport.getContainingClass()); } @@ -113,11 +119,11 @@ public class StaticImportMethodQuestionAction implements QuestionAction { doImport(myCandidates.get(0)); return; } - final BaseListPopupStep step = - new BaseListPopupStep(QuickFixBundle.message("method.to.import.chooser.title"), myCandidates) { + final BaseListPopupStep step = + new BaseListPopupStep(getPopupTitle(), myCandidates) { @Override - public PopupStep onChosen(PsiMethod selectedValue, boolean finalChoice) { + public PopupStep onChosen(T selectedValue, boolean finalChoice) { if (selectedValue == null) { return FINAL_CHOICE; } @@ -151,18 +157,18 @@ public class StaticImportMethodQuestionAction implements QuestionAction { } @Override - public boolean hasSubstep(PsiMethod selectedValue) { + public boolean hasSubstep(T selectedValue) { return true; } @NotNull @Override - public String getTextFor(PsiMethod value) { + public String getTextFor(T value) { return ObjectUtils.assertNotNull(value.getName()); } @Override - public Icon getIconFor(PsiMethod aValue) { + public Icon getIconFor(T aValue) { return aValue.getIcon(0); } }; @@ -171,14 +177,27 @@ public class StaticImportMethodQuestionAction implements QuestionAction { final PopupListElementRenderer rightArrow = new PopupListElementRenderer(this); @Override protected ListCellRenderer getListElementRenderer() { - return new MethodCellRenderer(true, PsiFormatUtilBase.SHOW_NAME){ + return new PsiElementListCellRenderer() { + public String getElementText(T element) { + final PsiClass aClass = element.getContainingClass(); + LOG.assertTrue(aClass != null); + return ClassPresentationUtil.getNameForClass(aClass, false) + "." + element.getName(); + } + + public String getContainerText(final T element, final String name) { + return PsiClassListCellRenderer.getContainerTextStatic(element); + } + + public int getIconFlags() { + return 0; + } @Nullable @Override protected TextAttributes getNavigationItemAttributes(Object value) { TextAttributes attrs = super.getNavigationItemAttributes(value); - if (value instanceof PsiMethod && !((PsiMethod)value).isDeprecated()) { - PsiClass psiClass = ((PsiMethod)value).getContainingClass(); + if (value instanceof PsiDocCommentOwner && !((PsiDocCommentOwner)value).isDeprecated()) { + PsiClass psiClass = ((T)value).getContainingClass(); if (psiClass != null && psiClass.isDeprecated()) { return TextAttributes.merge(attrs, super.getNavigationItemAttributes(psiClass)); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstant.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstant.java new file mode 100644 index 000000000000..00620ce2ed20 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstant.java @@ -0,0 +1,17 @@ +// "Static import constant..." "true" +package foo; + +import static foo.B.aaaaaaa; + +public class X { + { + aaaaaaa; + } +} + +class B { + public static Integer aaaaaaa = 1; +} +class B1 { + public static String aaaaaaa = ""; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstantInAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstantInAssignment.java new file mode 100644 index 000000000000..9ffd4f90553f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/afterConstantInAssignment.java @@ -0,0 +1,17 @@ +// "Static import constant 'foo.B.aaaaaaa'" "true" +package foo; + +import static foo.B.aaaaaaa; + +public class X { + { + int i = aaaaaaa; + } +} + +class B { + public static Integer aaaaaaa = 1; +} +class B1 { + public static String aaaaaaa = ""; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstant.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstant.java new file mode 100644 index 000000000000..aa0b01907d4a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstant.java @@ -0,0 +1,15 @@ +// "Static import constant..." "true" +package foo; + +public class X { + { + aaaaaaa; + } +} + +class B { + public static Integer aaaaaaa = 1; +} +class B1 { + public static String aaaaaaa = ""; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstantInAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstantInAssignment.java new file mode 100644 index 000000000000..5781759480f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant/beforeConstantInAssignment.java @@ -0,0 +1,15 @@ +// "Static import constant 'foo.B.aaaaaaa'" "true" +package foo; + +public class X { + { + int i = aaaaaaa; + } +} + +class B { + public static Integer aaaaaaa = 1; +} +class B1 { + public static String aaaaaaa = ""; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportConstantTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportConstantTest.java new file mode 100644 index 000000000000..decfb04dca89 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportConstantTest.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.quickFix; + +public class StaticImportConstantTest extends LightQuickFixParameterizedTestCase { + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/staticImportConstant"; + } +} diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index 506d63d4b51f..0b853daccd46 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -1,6 +1,7 @@ add.import=Add Import class.to.import.chooser.title=Class to Import method.to.import.chooser.title=Method to Import +field.to.import.chooser.title=Field to Import access.static.via.class.reference.family=Access static via class reference access.static.via.class.reference.text=Access static ''{1}.{0}'' via class ''{2}'' reference add.default.constructor.family=Add Default Constructor From a73b29ff19a7ba0d5434922d2fd0cc2b1efa992b Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 13 Jan 2016 19:05:12 +0300 Subject: [PATCH 044/825] Revert "dumb-aware run configurations: do not enable slow resolve if run configurations are not dumb aware" This reverts commit 1106cb05c4c5bc7c46390b4d95fcb70e48f91138. --- .../src/com/intellij/execution/impl/RunManagerImpl.java | 2 +- .../intellij/execution/testframework/sm/runner/SMTestProxy.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index 870e3dfef0aa..25f10b7ea89f 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -1100,7 +1100,7 @@ public class RunManagerImpl extends RunManagerEx implements PersistentStateCompo } else { try { - DumbService.getInstance(myProject).setAlternativeResolveEnabled(Registry.is("dumb.aware.run.configurations")); + DumbService.getInstance(myProject).setAlternativeResolveEnabled(true); settings.checkSettings(); icon = ProgramRunnerUtil.getConfigurationIcon(settings, false); } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index 8d854b19734f..634f0e0a1475 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -266,7 +266,7 @@ public class SMTestProxy extends AbstractTestProxy { String path = VirtualFileManager.extractPath(locationUrl); if (!DumbService.isDumb(project) || DumbService.isDumbAware(myLocator) || Registry.is("dumb.aware.run.configurations")) { try { - DumbService.getInstance(project).setAlternativeResolveEnabled(Registry.is("dumb.aware.run.configurations")); + DumbService.getInstance(project).setAlternativeResolveEnabled(true); List locations = myLocator.getLocation(protocolId, path, project, searchScope); if (!locations.isEmpty()) { return locations.get(0); From e14a96e3c29af8d14c0ae0d82e62fdfe363b2022 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 13 Jan 2016 18:44:26 +0300 Subject: [PATCH 045/825] [hg]: compareWith fixed for newly created branch and compare with bookmark (EA-77367, EA-77294); handle not found reference by name --- .../action/HgCompareWithBranchAction.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCompareWithBranchAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCompareWithBranchAction.java index 2f30bb67dcb6..4184477fb261 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCompareWithBranchAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCompareWithBranchAction.java @@ -29,6 +29,7 @@ import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.impl.HashImpl; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgContentRevision; import org.zmlx.hg4idea.HgFile; import org.zmlx.hg4idea.HgNameWithHashInfo; @@ -50,8 +51,8 @@ public class HgCompareWithBranchAction extends DvcsCompareWithBranchAction other_bookmarks = getOtherBookmarks(repository, currentRevisionHash); if (!other_bookmarks.isEmpty()) return false; - // if only one heavy branch and no other bookmarks -> check that current revision is no "main" branch head - return getBranchMainHash(repository, repository.getCurrentBranch()).equals(currentRevisionHash); + // if only one heavy branch and no other bookmarks -> check that current revision is not "main" branch head + return currentRevisionHash.equals(getHeavyBranchMainHash(repository, repository.getCurrentBranch())); } @NotNull @@ -72,11 +73,30 @@ public class HgCompareWithBranchAction extends DvcsCompareWithBranchAction() { + @Override + public boolean value(HgNameWithHashInfo info) { + return info.getName().equals(bookmarkName); + } + }); + return bookmarkInfo != null ? bookmarkInfo.getHash() : null; } + @Nullable + private static Hash getHeavyBranchMainHash(@NotNull HgRepository repository, @NotNull String branchName) { + // null for new branch or not heavy ref + final LinkedHashSet branchHashes = repository.getBranches().get(branchName); + return branchHashes != null ? ObjectUtils.assertNotNull(Iterables.getLast(branchHashes)) : null; + } + + @Nullable + private static Hash detectActiveHashByName(@NotNull HgRepository repository, @NotNull String branchToCompare) { + Hash refHashToCompare = getHeavyBranchMainHash(repository, branchToCompare); + return refHashToCompare != null ? refHashToCompare : findBookmarkHashByName(repository, branchToCompare); + } @NotNull @Override @@ -84,11 +104,11 @@ public class HgCompareWithBranchAction extends DvcsCompareWithBranchAction namesToCompare = new ArrayList(repository.getBranches().keySet()); final String currentBranchName = repository.getCurrentBranchName(); assert currentBranchName != null; - Hash currentBranchHash = getBranchMainHash(repository, currentBranchName); - if (currentBranchHash.equals(getCurrentHash(repository))) { + final Hash currentHash = getCurrentHash(repository); + if (currentHash.equals(getHeavyBranchMainHash(repository, currentBranchName))) { namesToCompare.remove(currentBranchName); } - namesToCompare.addAll(HgUtil.getNamesWithoutHashes(getOtherBookmarks(repository, currentBranchHash))); + namesToCompare.addAll(HgUtil.getNamesWithoutHashes(getOtherBookmarks(repository, currentHash))); return namesToCompare; } @@ -111,9 +131,11 @@ public class HgCompareWithBranchAction extends DvcsCompareWithBranchAction changes = HgUtil.getDiff(project, repositoryRoot, filePath, compareWithRevisionNumber, null); if (changes.isEmpty() && !existInBranch(repository, filePath, compareWithRevisionNumber)) { throw new VcsException(fileDoesntExistInBranchError(file, branchToCompare)); From 0cc1ef0529f478890ebe34b929748322278ce934 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 13 Jan 2016 19:05:36 +0300 Subject: [PATCH 046/825] [shelf]: IDEA-150357 Add mnemonic to "remove successfully applied files from the shelf" checkbox --- .../openapi/vcs/changes/shelf/UnshelveWithDialogAction.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java index 6ae2332f1462..a4671d3bbfdc 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/UnshelveWithDialogAction.java @@ -46,6 +46,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.io.File; import java.util.Collections; import java.util.List; @@ -154,6 +155,7 @@ public class UnshelveWithDialogAction extends DumbAwareAction { @NotNull private static JCheckBox createRemoveFilesStrategyCheckbox(@NotNull Project project) { final JCheckBox removeOptionCheckBox = new JCheckBox("Remove successfully applied files from the shelf"); + removeOptionCheckBox.setMnemonic(KeyEvent.VK_R); final ShelveChangesManager shelveChangesManager = ShelveChangesManager.getInstance(project); removeOptionCheckBox.setSelected(shelveChangesManager.isRemoveFilesFromShelf()); removeOptionCheckBox.addActionListener(new ActionListener() { From fa1e316ad7d4838b66ecded21e2704672180f612 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 13 Jan 2016 17:25:22 +0100 Subject: [PATCH 047/825] silently ignore errors to load IdeaWin32.dll (the code assumes that it's located under an IDEA installation and the DLL is available, which is not true when util.jar is used in a different context such as the Kotlin compiler) --- .../openapi/util/io/win32/IdeaWin32.java | 9 ++++---- .../intellij/util/lang/UrlClassLoader.java | 21 +++++++++++++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java index adac6fab239a..2d8aa61e0d03 100644 --- a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java +++ b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -38,9 +38,10 @@ public class IdeaWin32 { IdeaWin32 instance = null; if (SystemInfo.isWin2kOrNewer && SystemProperties.getBooleanProperty("idea.use.native.fs.for.win", true)) { try { - UrlClassLoader.loadPlatformLibrary("IdeaWin32"); - instance = new IdeaWin32(); - LOG.info("Native filesystem for Windows is operational"); + if (UrlClassLoader.tryLoadPlatformLibrary("IdeaWin32")) { + instance = new IdeaWin32(); + LOG.info("Native filesystem for Windows is operational"); + } } catch (Throwable t) { LOG.warn("Failed to initialize native filesystem for Windows", t); diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java index d0780622def9..4541d526ce39 100644 --- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java +++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -301,7 +301,7 @@ public class UrlClassLoader extends ClassLoader { return getClassPath().getResources(name, true); } - public static void loadPlatformLibrary(@NotNull String libName) { + private static boolean loadPlatformLibrary(@NotNull String libName, boolean reportError) { String libFileName = mapLibraryName(libName); String libPath = null; @@ -314,6 +314,11 @@ public class UrlClassLoader extends ClassLoader { } } if (libPath == null) { + // If we're not running inside IDEA and don't need to report errors, fail silently + if (!reportError && PathManager.getHomePathFor(PathManager.class) == null) { + return false; + } + libPath = PathManager.getBinPath() + "/" + libFileName; } @@ -322,6 +327,9 @@ public class UrlClassLoader extends ClassLoader { if (!new File(libPath = PathManager.getHomePath() + "/community/bin/" + platform + libFileName).exists()) { if (!new File(libPath = PathManager.getHomePath() + "/bin/" + platform + libFileName).exists()) { if (!new File(libPath = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libFileName).exists()) { + if (!reportError) { + return false; + } File libDir = new File(PathManager.getBinPath()); throw new UnsatisfiedLinkError("'" + libFileName + "' not found in '" + libDir + "' among " + Arrays.toString(libDir.list())); } @@ -330,6 +338,15 @@ public class UrlClassLoader extends ClassLoader { } System.load(libPath); + return true; + } + + public static boolean tryLoadPlatformLibrary(@NotNull String libName) { + return loadPlatformLibrary(libName, false); + } + + public static void loadPlatformLibrary(@NotNull String libName) { + loadPlatformLibrary(libName, true); } private static String mapLibraryName(String libName) { From 8ea76ce40ac17246b07ff79f00287410a106554f Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Wed, 13 Jan 2016 19:38:10 +0300 Subject: [PATCH 048/825] add incompatible plugins --- platform/platform-resources/src/brokenPlugins.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index d2bb583f5661..f00526448309 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -1,19 +1,19 @@ // This file contains list of broken plugins. // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 144.988 143.1138 143.1088 143.769 143.751 143.516 143.381.8 143.380.6 143.381.11 143.380.8 143.444 143.379.15 143.21 143.110 143.250 142.4426 142.4100 142.3858 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 +NodeJS 144.2562 144.2131 144.988 143.1138 143.1088 143.769 143.751 143.516 143.381.8 143.380.6 143.381.11 143.380.8 143.444 143.379.15 143.21 143.110 143.250 142.4426 142.4100 142.3858 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 com.jetbrains.php 143.382.38 143.279 143.381.48 143.129 142.5282 142.2716 142.3969 142.4491 140.2765 141.332 139.732 139.659 139.496 139.173 139.105 138.2502 138.2000.2262 138.1751 138.1806 138.1505 138.1161 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 org.jetbrains.plugins.ruby 8.0.0.20151005 8.0.0.20180821 8.0.0.20150708 8.0.0.20150624 8.0.0.20150616 7.0.0.20150216 7.0.0.20150204 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 Pythonid 5.0.2.143.121 5.0.142.1177 5.0.143.116 5.0.143.100 5.0.143.103 5.0.143.95 5.0.142.1060 5.0.143.53 5.0.142.2 "142.176 v4.5" 4.1 "4.1 141.4 EAP" 3.1 4.0.25 4.0.26 PythonCore 5.0.143.103 -Karma 144.988 142.3390 142.2492 142.2064 140.2109 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 +Karma 144.2131 144.988 142.3390 142.2492 142.2064 140.2109 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 org.intellij.scala 1.9.133 1.9.140 1.9.147 1.9.151 1.9.2.2 1.9.4 1.9.4.1 1.9.2 1.8.5 1.8.0 1.8.2 1.8.4 1.7.4 1.7.2 1.6.2 1.6.1 1.6.0 1.2.67.3.EAP 1.3.2-14.1 1.3.3-14.1 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 org.jetbrains.kannotator 0.2.420 org.jetbrains.kotlin 0.10.555 0.10.4 0.8.1615 0.7.1360 0.7.1376 0.8.7 SBT 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0 1.5.1 1.6.0 1.6.1 1.7.0 -"JSTestDriver Plugin" 144.988 142.2492 142.2064 140.2109 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 +"JSTestDriver Plugin" 144.2131 144.988 142.2492 142.2064 140.2109 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 AngularJS 141.1237 141.991 142.2481 142.4081 142.1935 141.2 140.1968 139.1112 139.12 134.1243 134.1341 134.1444 135.1063 135.565 135.831 135.937 138.1242 138.1988 134.1094 0.1.8 0.1.9 com.jetbrains.plugins.ini4idea 0.4 0.5 0.6 0.7 0.8 0.8.1 0.9 0.9.1 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 130.1176 org.jetbrains.plugins.vagrant 0.1 0.2 0.3 0.4 0.5 0.6.143.3 From c58d8ac07f525a200002193c6ce8db3b8e6250d6 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 13 Jan 2016 20:01:30 +0300 Subject: [PATCH 049/825] disabled ctrl-hover mouse handler for gutter (it highlights strange nearby code) --- .../com/intellij/codeInsight/navigation/CtrlMouseHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 cc8805666494..d8859e3fda7f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -199,7 +199,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { myStoredModifiers = mouseEvent.getModifiers(); BrowseMode browseMode = getBrowseMode(myStoredModifiers); - if (browseMode == BrowseMode.None) { + if (browseMode == BrowseMode.None || e.getArea() != EditorMouseEventArea.EDITING_AREA) { disposeHighlighter(); return; } From 80713f912d76e7b18b00a1ef873103d4637cac67 Mon Sep 17 00:00:00 2001 From: Andrey Starovoyt Date: Wed, 13 Jan 2016 20:10:11 +0300 Subject: [PATCH 050/825] json scheme: fix order + add completion for tsconfig.json --- platform/platform-resources/src/META-INF/JsonPlugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index ad80a0b8c605..329333d5b131 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -32,7 +32,7 @@ - + From 79f8f1e30164a4b3522f20e059a0ceb1a818d0ad Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 13 Jan 2016 14:49:44 +0300 Subject: [PATCH 051/825] PY-16541 Support copying references of top level functions --- .../actions/PyQualifiedNameProvider.java | 12 ++++++ .../topLevelFunctionReference/a/__init__.py | 0 .../topLevelFunctionReference/a/b/__init__.py | 0 .../a/b/c/__init__.py | 0 .../topLevelFunctionReference/a/b/c/module.py | 2 + .../python/PyQualifiedNameProviderTest.java | 43 +++++++++++++++++++ 6 files changed, 57 insertions(+) create mode 100644 python/testData/qualifiedName/topLevelFunctionReference/a/__init__.py create mode 100644 python/testData/qualifiedName/topLevelFunctionReference/a/b/__init__.py create mode 100644 python/testData/qualifiedName/topLevelFunctionReference/a/b/c/__init__.py create mode 100644 python/testData/qualifiedName/topLevelFunctionReference/a/b/c/module.py create mode 100644 python/testSrc/com/jetbrains/python/PyQualifiedNameProviderTest.java diff --git a/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java b/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java index 024883766c03..79509794e015 100644 --- a/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java +++ b/python/src/com/jetbrains/python/actions/PyQualifiedNameProvider.java @@ -15,17 +15,22 @@ */ package com.jetbrains.python.actions; +import com.google.common.collect.Iterables; import com.intellij.ide.actions.QualifiedNameProvider; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.stubs.PyClassNameIndex; +import com.jetbrains.python.psi.stubs.PyFunctionNameIndex; import org.jetbrains.annotations.Nullable; +import java.util.Collection; + /** * User: anna @@ -48,6 +53,9 @@ public class PyQualifiedNameProvider implements QualifiedNameProvider { if (containingClass != null) { return containingClass.getQualifiedName() + "#" + ((PyFunction)element).getName(); } + else { + return ((PyFunction)element).getQualifiedName(); + } } return null; } @@ -59,6 +67,10 @@ public class PyQualifiedNameProvider implements QualifiedNameProvider { if (aClass != null) { return aClass; } + final Collection functions = PyFunctionNameIndex.find(fqn, project); + if (!functions.isEmpty()) { + return ContainerUtil.getFirstItem(functions); + } final int sharpIdx = fqn.indexOf("#"); if (sharpIdx > -1) { final String className = StringUtil.getPackageName(fqn, '#'); diff --git a/python/testData/qualifiedName/topLevelFunctionReference/a/__init__.py b/python/testData/qualifiedName/topLevelFunctionReference/a/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/qualifiedName/topLevelFunctionReference/a/b/__init__.py b/python/testData/qualifiedName/topLevelFunctionReference/a/b/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/qualifiedName/topLevelFunctionReference/a/b/c/__init__.py b/python/testData/qualifiedName/topLevelFunctionReference/a/b/c/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/qualifiedName/topLevelFunctionReference/a/b/c/module.py b/python/testData/qualifiedName/topLevelFunctionReference/a/b/c/module.py new file mode 100644 index 000000000000..c1015f4f20f2 --- /dev/null +++ b/python/testData/qualifiedName/topLevelFunctionReference/a/b/c/module.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyQualifiedNameProviderTest.java b/python/testSrc/com/jetbrains/python/PyQualifiedNameProviderTest.java new file mode 100644 index 000000000000..c57e3bcb542f --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PyQualifiedNameProviderTest.java @@ -0,0 +1,43 @@ +/* + * 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. + */ +package com.jetbrains.python; + +import com.jetbrains.python.actions.PyQualifiedNameProvider; +import com.jetbrains.python.fixtures.PyTestCase; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; + +/** + * @author Mikhail Golubev + */ +public class PyQualifiedNameProviderTest extends PyTestCase { + @Test + public void testTopLevelFunctionReference() { + myFixture.copyDirectoryToProject(getTestName(true) + "/a", "a"); + myFixture.configureByFile("a/b/c/module.py"); + assertEquals("a.b.c.module.func", getQualifiedNameOfElementUnderCaret()); + } + + @Nullable + private String getQualifiedNameOfElementUnderCaret() { + return new PyQualifiedNameProvider().getQualifiedName(myFixture.getElementAtCaret()); + } + + @Override + protected String getTestDataPath() { + return super.getTestDataPath() + "/qualifiedName"; + } +} From 5b763d7de7f7e317f1379a6516fe10cdfd1846d5 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 12 Jan 2016 15:36:06 +0300 Subject: [PATCH 052/825] PY-17979 Reverted controversial fix for the PY-13304 Continuation indent is used for function arguments only to avoid structure ambiguity. --- .../jetbrains/python/formatter/PyBlock.java | 22 +++++++++++++++++-- ...estedFunctionCallsInWithStatement_after.py | 2 +- ...hangingIndentInNamedArgumentValue_after.py | 2 +- .../noAlignForMethodArguments_after.py | 2 +- .../formatter/noWrapBeforeParen_after.py | 2 +- .../formatter/setLiteralInArgList_after.py | 4 ++-- ...functionCallWithCommentNotInlined.after.py | 6 ++--- .../com/jetbrains/python/PyIndentTest.java | 3 ++- 8 files changed, 31 insertions(+), 12 deletions(-) diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 1c94b0ecbe1d..461e0fad9b90 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -323,8 +323,13 @@ public class PyBlock implements ASTBlock { if (childType == PyTokenTypes.RPAR) { childIndent = Indent.getNoneIndent(); } - else if (childType != PyTokenTypes.LPAR){ - childIndent = Indent.getContinuationIndent(); + else { + if (parentType == PyElementTypes.PARAMETER_LIST || argumentMayHaveSameIndentAsFollowingStatementList()) { + childIndent = Indent.getContinuationIndent(); + } + else { + childIndent = Indent.getNormalIndent(); + } } } else if (parentType == PyElementTypes.SUBSCRIPTION_EXPRESSION) { @@ -421,6 +426,19 @@ public class PyBlock implements ASTBlock { return node.getPsi() instanceof PySequenceExpression && ((PySequenceExpression)node.getPsi()).isEmpty(); } + private boolean argumentMayHaveSameIndentAsFollowingStatementList() { + if (myNode.getElementType() != PyElementTypes.ARGUMENT_LIST) { + return false; + } + // This check is supposed to prevent PEP8's error: Continuation line with the same indent as next logical line + final PsiElement header = getControlStatementHeader(myNode); + if (header instanceof PyStatementListContainer) { + final PyStatementList statementList = ((PyStatementListContainer)header).getStatementList(); + return PyUtil.onSameLine(header, myNode.getPsi()) && !PyUtil.onSameLine(header, statementList); + } + return false; + } + // Check https://www.python.org/dev/peps/pep-0008/#indentation private static boolean hasHangingIndent(@NotNull PsiElement elem) { if (elem instanceof PyCallExpression) { diff --git a/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py b/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py index 9a4e5063b2ab..c867a3f0451a 100644 --- a/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py +++ b/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py @@ -1,4 +1,4 @@ with raises_assertion( has_string('Missing download_urls: {}, {}'.format( - self.other_download_url, self.another_download_url))): + self.other_download_url, self.another_download_url))): fixture.assert_detail_page_yields_expected() diff --git a/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py b/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py index 1102984b4b98..4585528e01cd 100644 --- a/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py +++ b/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py @@ -1,3 +1,3 @@ funcWithLongName(x=[ ], - y=42) + y=42) diff --git a/python/testData/formatter/noAlignForMethodArguments_after.py b/python/testData/formatter/noAlignForMethodArguments_after.py index 740f638adf4c..5682f4ca4f45 100644 --- a/python/testData/formatter/noAlignForMethodArguments_after.py +++ b/python/testData/formatter/noAlignForMethodArguments_after.py @@ -2,4 +2,4 @@ def long_method_name(bar, baz): pass long_method_name("long string one", - "long string two") + "long string two") diff --git a/python/testData/formatter/noWrapBeforeParen_after.py b/python/testData/formatter/noWrapBeforeParen_after.py index 003f387c408c..5ab3054984db 100644 --- a/python/testData/formatter/noWrapBeforeParen_after.py +++ b/python/testData/formatter/noWrapBeforeParen_after.py @@ -4,4 +4,4 @@ def foo(): if comments: for comment in comments: record += ' \n' + ca + '=' + quoteattr(comment[ca]) + ' ' for ca in comment) + '/>\n' diff --git a/python/testData/formatter/setLiteralInArgList_after.py b/python/testData/formatter/setLiteralInArgList_after.py index 48bec3381227..9c2f75d6dca6 100644 --- a/python/testData/formatter/setLiteralInArgList_after.py +++ b/python/testData/formatter/setLiteralInArgList_after.py @@ -1,3 +1,3 @@ self.assertEqual( - {"000000000000", "111111111111"}, - foo['bar']['baz']) + {"000000000000", "111111111111"}, + foo['bar']['baz']) diff --git a/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py b/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py index f73d8462c0c9..3140c9b2ab96 100644 --- a/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py +++ b/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py @@ -1,8 +1,8 @@ import subprocess as sp a = sp.check_output( - args=['python', '-c', 'print("Spam")'], - # read errors too - stderr=sp.STDOUT + args=['python', '-c', 'print("Spam")'], + # read errors too + stderr=sp.STDOUT ) print(a) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyIndentTest.java b/python/testSrc/com/jetbrains/python/PyIndentTest.java index d6c09b817227..0164e14fc5ce 100644 --- a/python/testSrc/com/jetbrains/python/PyIndentTest.java +++ b/python/testSrc/com/jetbrains/python/PyIndentTest.java @@ -16,6 +16,7 @@ package com.jetbrains.python; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.jetbrains.python.fixtures.PyTestCase; @@ -199,7 +200,7 @@ public class PyIndentTest extends PyTestCase { public void testEnterInNonEmptyArgList() { // PY-1947 doTest("Task(params=1)", "Task(\n" + - " params=1)"); + " params=1)"); } public void testEnterInNonClosedArgList() { // PY-4863 From 0f0ee7d7314420c98cd1795241edd2b7eb187a8b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 13 Jan 2016 16:14:53 +0300 Subject: [PATCH 053/825] PY-13304, PY-17979 Add option that allows to use continuation indent for arguments --- .../com/jetbrains/python/PyBundle.properties | 1 + .../jetbrains/python/formatter/PyBlock.java | 4 ++- .../python/formatter/PyCodeStylePanel.form | 12 +++++++-- .../python/formatter/PyCodeStylePanel.java | 27 ++++++++++++++++--- .../python/formatter/PyCodeStyleSettings.java | 8 ++++++ ...ntinuationIndentBeforeFunctionArguments.py | 10 +++++++ ...tionIndentBeforeFunctionArguments_after.py | 10 +++++++ .../com/jetbrains/python/PyFormatterTest.java | 6 +++++ 8 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 python/testData/formatter/continuationIndentBeforeFunctionArguments.py create mode 100644 python/testData/formatter/continuationIndentBeforeFunctionArguments_after.py diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index c28fa7a526a0..be923916065a 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -965,6 +965,7 @@ formatter.panel.dict.alignment.align.on.colon=Align on colon formatter.panel.dict.alignment.align.on.value=Align on value formatter.panel.dict.alignment.label=Dict alignment: formatter.panel.add.trailing.line.feed=Add line feed at the end of file +formatter.panel.use.continuation.indent.for.arguments=Use continuation indent for arguments formatter.left.bracket = Left bracket formatter.around.eq.in.named.parameter = Around = in named parameter diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 461e0fad9b90..4afd0d362595 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -324,7 +324,9 @@ public class PyBlock implements ASTBlock { childIndent = Indent.getNoneIndent(); } else { - if (parentType == PyElementTypes.PARAMETER_LIST || argumentMayHaveSameIndentAsFollowingStatementList()) { + if (parentType == PyElementTypes.PARAMETER_LIST || + settings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS || + argumentMayHaveSameIndentAsFollowingStatementList()) { childIndent = Indent.getContinuationIndent(); } else { diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.form b/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.form index 392973f56cd5..1bedd0b8863b 100644 --- a/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.form +++ b/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.form @@ -23,7 +23,7 @@ - + @@ -47,12 +47,20 @@ - + + + + + + + + + diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.java b/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.java index 00334078dc9b..2d18301ff07b 100644 --- a/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.java +++ b/python/src/com/jetbrains/python/formatter/PyCodeStylePanel.java @@ -43,6 +43,7 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel { private JPanel myPanel; private JBCheckBox myAddTrailingBlankLineCheckbox; + private JBCheckBox myUseContinuationIndentForArguments; private ComboBox myDictAlignmentCombo; private JPanel myPreviewPanel; @@ -71,6 +72,13 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel { somethingChanged(); } }); + + myUseContinuationIndentForArguments.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + somethingChanged(); + } + }); } @Override @@ -103,6 +111,7 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel { } } myAddTrailingBlankLineCheckbox.setSelected(getCustomSettings(settings).BLANK_LINE_AT_FILE_END); + myUseContinuationIndentForArguments.setSelected(getCustomSettings(settings).USE_CONTINUATION_INDENT_FOR_ARGUMENTS); } @Override @@ -110,6 +119,7 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel { final PyCodeStyleSettings customSettings = getCustomSettings(settings); customSettings.DICT_ALIGNMENT = getDictAlignmentAsInt(); customSettings.BLANK_LINE_AT_FILE_END = ensureTrailingBlankLine(); + customSettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS = useContinuationIndentForArguments(); } @Override @@ -137,8 +147,17 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel { return myAddTrailingBlankLineCheckbox.isSelected(); } - public static final String PREVIEW = "{\n" + - " \"green\": 42,\n" + - " \"eggs and ham\": -0.0e0\n" + - "}"; + private boolean useContinuationIndentForArguments() { + return myUseContinuationIndentForArguments.isSelected(); + } + + public static final String PREVIEW = "x = max(\n" + + " 1,\n" + + " 2,\n" + + " 3)\n" + + "\n" + + "{\n" + + " \"green\": 42,\n" + + " \"eggs and ham\": -0.0e0\n" + + "}"; } diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java index 6b75cd2ef9f6..e87b16768cd5 100644 --- a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java +++ b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java @@ -78,6 +78,14 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings { public boolean DICT_NEW_LINE_BEFORE_RIGHT_BRACE = false; public int BLANK_LINES_AFTER_LOCAL_IMPORTS = 0; + /** + * Code style for most languages use continuation indent both for parameters in function definition and for arguments in function calls. + * In Python continuation indent (assuming it's 8 spaces) for parameters is required by PEP 8, because otherwise they won't be visually + * distinctive from function body. However for arguments (except several special cases) both normal and continuation indents are acceptable + * (as long as they're multiple of 4), though examples in PEP 8 itself use mostly normal indent. Nontheless some users prefer to have + * the same indetation level for arguments as for parameters. + */ + public boolean USE_CONTINUATION_INDENT_FOR_ARGUMENTS = false; public PyCodeStyleSettings(CodeStyleSettings container) { super("Python", container); diff --git a/python/testData/formatter/continuationIndentBeforeFunctionArguments.py b/python/testData/formatter/continuationIndentBeforeFunctionArguments.py new file mode 100644 index 000000000000..ace58e4ed49a --- /dev/null +++ b/python/testData/formatter/continuationIndentBeforeFunctionArguments.py @@ -0,0 +1,10 @@ +sum( + 1, + 2, 3, +5, +) + +sum( +1, + 2, 3, + 5) diff --git a/python/testData/formatter/continuationIndentBeforeFunctionArguments_after.py b/python/testData/formatter/continuationIndentBeforeFunctionArguments_after.py new file mode 100644 index 000000000000..152610f98170 --- /dev/null +++ b/python/testData/formatter/continuationIndentBeforeFunctionArguments_after.py @@ -0,0 +1,10 @@ +sum( + 1, + 2, 3, + 5, +) + +sum( + 1, + 2, 3, + 5) diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java index 575abfd664be..030542de8dca 100644 --- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java +++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java @@ -659,4 +659,10 @@ public class PyFormatterTest extends PyTestCase { public void testBlanksBetweenImportsPreservedWithoutOptimizeImports() { doTest(); } + + // PY-17979, PY-13304 + public void testContinuationIndentBeforeFunctionArguments() { + getPythonCodeStyleSettings().USE_CONTINUATION_INDENT_FOR_ARGUMENTS = true; + doTest(); + } } From f93d2caef2744ab085670230939641d8ae697b53 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 17:47:57 +0100 Subject: [PATCH 054/825] extract "exclude from auto-import substep" --- .../daemon/impl/actions/AddImportAction.java | 47 ++++++++++--------- .../StaticImportMethodQuestionAction.java | 20 +------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/AddImportAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/AddImportAction.java index ce827c34353c..b64b91a65b6a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/AddImportAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/AddImportAction.java @@ -46,6 +46,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -120,27 +121,7 @@ public class AddImportAction implements QuestionAction { return FINAL_CHOICE; } - String qname = selectedValue.getQualifiedName(); - if (qname == null) return FINAL_CHOICE; - - List toExclude = getAllExcludableStrings(qname); - - return new BaseListPopupStep(null, toExclude) { - @NotNull - @Override - public String getTextFor(String value) { - return "Exclude '" + value + "' from auto-import"; - } - - @Override - public PopupStep onChosen(String selectedValue, boolean finalChoice) { - if (finalChoice) { - excludeFromImport(myProject, selectedValue); - } - - return super.onChosen(selectedValue, finalChoice); - } - }; + return getExcludesStep(selectedValue.getQualifiedName(), myProject); } @Override @@ -179,6 +160,30 @@ public class AddImportAction implements QuestionAction { popup.showInBestPositionFor(myEditor); } + @Nullable + public static PopupStep getExcludesStep(String qname, final Project project) { + if (qname == null) return PopupStep.FINAL_CHOICE; + + List toExclude = getAllExcludableStrings(qname); + + return new BaseListPopupStep(null, toExclude) { + @NotNull + @Override + public String getTextFor(String value) { + return "Exclude '" + value + "' from auto-import"; + } + + @Override + public PopupStep onChosen(String selectedValue, boolean finalChoice) { + if (finalChoice) { + excludeFromImport(project, selectedValue); + } + + return super.onChosen(selectedValue, finalChoice); + } + }; + } + public static void excludeFromImport(final Project project, final String prefix) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java index bfd9e4c52dcd..5a6bf7d635ad 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java @@ -135,25 +135,7 @@ public class StaticImportMethodQuestionAction implements Qu return FINAL_CHOICE; } - String qname = PsiUtil.getMemberQualifiedName(selectedValue); - if (qname == null) return FINAL_CHOICE; - List excludableStrings = AddImportAction.getAllExcludableStrings(qname); - return new BaseListPopupStep(null, excludableStrings) { - @NotNull - @Override - public String getTextFor(String value) { - return "Exclude '" + value + "' from auto-import"; - } - - @Override - public PopupStep onChosen(String selectedValue, boolean finalChoice) { - if (finalChoice) { - AddImportAction.excludeFromImport(project, selectedValue); - } - - return super.onChosen(selectedValue, finalChoice); - } - }; + return AddImportAction.getExcludesStep(PsiUtil.getMemberQualifiedName(selectedValue), project); } @Override From bfb3944e08e700412fc87cd154a900b3b7827046 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 18:14:25 +0100 Subject: [PATCH 055/825] for -> forEachOrdered (IDEA-150315) --- .../StreamApiMigrationInspection.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java index 49d6839f5b25..cd21db66ce5e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java @@ -131,7 +131,9 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } else if (REPLACE_TRIVIAL_FOREACH || !isTrivial(body, statement.getIterationParameter())) { holder.registerProblem(iteratedValue, "Can be replaced with foreach call", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithForeachCallFix()); + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + new ReplaceWithForeachCallFix("forEach"), + new ReplaceWithForeachCallFix("forEachOrdered")); } } } @@ -266,6 +268,12 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } private static class ReplaceWithForeachCallFix implements LocalQuickFix { + private final String myForEachMethodName; + + private ReplaceWithForeachCallFix(String forEachMethodName) { + myForEachMethodName = forEachMethodName; + } + @NotNull @Override public String getName() { @@ -275,7 +283,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo @NotNull @Override public String getFamilyName() { - return "Replace with forEach"; + return "Replace with " + myForEachMethodName; } @Override @@ -300,7 +308,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo body = thenBranch; } - buffer.append(".forEach("); + buffer.append("." + myForEachMethodName + "("); final String functionalExpressionText = createForEachFunctionalExpressionText(project, body, parameter); final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); From fe15459e98cd57439afe43c99274f4d1b674fc40 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 13 Jan 2016 20:46:17 +0300 Subject: [PATCH 056/825] dumb-aware run configurations: notify about limited capabilities during indexing --- .../intellij/execution/ProgramRunnerUtil.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java index 141cb4982db4..4a7e38f3f71d 100644 --- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java @@ -28,11 +28,16 @@ import com.intellij.icons.AllIcons; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.LayeredIcon; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -49,7 +54,7 @@ public class ProgramRunnerUtil { return configuration == null ? null : RunnerRegistry.getInstance().getRunner(executorId, configuration.getConfiguration()); } - public static void executeConfiguration(@NotNull ExecutionEnvironment environment, boolean showSettings, boolean assignNewId) { + public static void executeConfiguration(@NotNull final ExecutionEnvironment environment, boolean showSettings, boolean assignNewId) { if (ExecutorRegistry.getInstance().isStarting(environment)) { return; } @@ -91,6 +96,27 @@ public class ProgramRunnerUtil { if (assignNewId) { environment.assignNewExecutionId(); } + final Project project = environment.getProject(); + if (DumbService.isDumb(project) && Registry.is("dumb.aware.run.configurations")) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (project.isDisposed()) { + return; + } + + final String toolWindowId = environment.getExecutor().getToolWindowId(); + ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); + if (toolWindowManager.canShowNotification(toolWindowId)) { + //noinspection SSBasedInspection + toolWindowManager.notifyByBalloon(toolWindowId, MessageType.INFO, + "Some actions may not work as expected if you start a Run/debug configuration while indexing is in progress."); + } + } + }); + + } + environment.getRunner().execute(environment); } catch (ExecutionException e) { From 123989cee9b52bd58d2fa882fb66762bd1aefee9 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 13 Jan 2016 20:59:24 +0300 Subject: [PATCH 057/825] dumb-aware run configurations: don't show configuration editor in dumb mode --- .../src/com/intellij/execution/ProgramRunnerUtil.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java index 4a7e38f3f71d..babdfc97f31d 100644 --- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java @@ -60,6 +60,7 @@ public class ProgramRunnerUtil { } RunnerAndConfigurationSettings runnerAndConfigurationSettings = environment.getRunnerAndConfigurationSettings(); + final Project project = environment.getProject(); if (runnerAndConfigurationSettings != null) { if (!ExecutionTargetManager.canRun(environment)) { ExecutionUtil.handleExecutionError(environment, new ExecutionException( @@ -67,14 +68,15 @@ public class ProgramRunnerUtil { return; } - if (!RunManagerImpl.canRunConfiguration(environment) || (showSettings && runnerAndConfigurationSettings.isEditBeforeRun())) { + if ((!RunManagerImpl.canRunConfiguration(environment) || (showSettings && runnerAndConfigurationSettings.isEditBeforeRun())) && + !DumbService.isDumb(project)) { if (!RunDialog.editConfiguration(environment, "Edit configuration")) { return; } while (!RunManagerImpl.canRunConfiguration(environment)) { if (Messages.YES == Messages - .showYesNoDialog(environment.getProject(), "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings", + .showYesNoDialog(project, "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings", "Edit", "Continue Anyway", Messages.getErrorIcon())) { if (!RunDialog.editConfiguration(environment, "Edit configuration")) { return; @@ -96,7 +98,6 @@ public class ProgramRunnerUtil { if (assignNewId) { environment.assignNewExecutionId(); } - final Project project = environment.getProject(); if (DumbService.isDumb(project) && Registry.is("dumb.aware.run.configurations")) { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override @@ -130,7 +131,7 @@ public class ProgramRunnerUtil { if (name == null) { name = ""; } - ExecutionUtil.handleExecutionError(environment.getProject(), environment.getExecutor().getToolWindowId(), name, e); + ExecutionUtil.handleExecutionError(project, environment.getExecutor().getToolWindowId(), name, e); } } From f6fc7322c1da8facffbc5a0b5dcc4a26eb8127cf Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 18:33:07 +0100 Subject: [PATCH 058/825] java location: trim method name to support ZohhakRunner (IDEA-149899) --- .../com/intellij/execution/testframework/JavaTestLocator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/execution/testframework/JavaTestLocator.java b/java/execution/impl/src/com/intellij/execution/testframework/JavaTestLocator.java index ac4c581f15e9..a02ef2a4d8fd 100644 --- a/java/execution/impl/src/com/intellij/execution/testframework/JavaTestLocator.java +++ b/java/execution/impl/src/com/intellij/execution/testframework/JavaTestLocator.java @@ -67,7 +67,7 @@ public class JavaTestLocator implements SMTestLocator { PsiClass aClass = ClassUtil.findPsiClass(PsiManager.getInstance(project), className, null, true, scope); if (aClass != null) { results = ContainerUtil.newSmartList(); - PsiMethod[] methods = aClass.findMethodsByName(methodName, true); + PsiMethod[] methods = aClass.findMethodsByName(methodName.trim(), true); if (methods.length > 0) { for (PsiMethod method : methods) { results.add(paramName != null ? new PsiMemberParameterizedLocation(project, method, aClass, paramName) From 4b1d5629ec6d37ef31548b0ae7536657d947b599 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Jan 2016 19:17:39 +0100 Subject: [PATCH 059/825] copy classes: retarget refs in extends lists (IDEA-150234) --- .../refactoring/copy/CopyClassesHandler.java | 24 +++---------------- .../packageLocalAndExtends/after/p1/X.java | 4 ++++ .../packageLocalAndExtends/after/p2/X.java | 4 ++++ .../packageLocalAndExtends/after/p2/empty.txt | 0 .../packageLocalAndExtends/before/p1/X.java | 4 ++++ .../before/p2/empty.txt | 0 .../intellij/refactoring/CopyClassTest.java | 4 ++++ 7 files changed, 19 insertions(+), 21 deletions(-) create mode 100644 java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p1/X.java create mode 100644 java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/X.java create mode 100644 java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/empty.txt create mode 100644 java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p1/X.java create mode 100644 java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p2/empty.txt diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index 43706636aa86..1743d08030f4 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -493,27 +493,9 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { final Map rebindMap = new LinkedHashMap(); element.accept(new JavaRecursiveElementVisitor(){ @Override - public void visitReferenceExpression(PsiReferenceExpression expression) { - decodeRef(expression, oldToNewMap, rebindMap); - super.visitReferenceExpression(expression); - } - - @Override - public void visitNewExpression(PsiNewExpression expression) { - super.visitNewExpression(expression); - final PsiJavaCodeReferenceElement referenceElement = expression.getClassReference(); - if (referenceElement != null) { - decodeRef(referenceElement, oldToNewMap, rebindMap); - } - } - - @Override - public void visitTypeElement(PsiTypeElement type) { - super.visitTypeElement(type); - final PsiJavaCodeReferenceElement referenceElement = type.getInnermostComponentReferenceElement(); - if (referenceElement != null) { - decodeRef(referenceElement, oldToNewMap, rebindMap); - } + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + super.visitReferenceElement(reference); + decodeRef(reference, oldToNewMap, rebindMap); } }); for (Map.Entry entry : rebindMap.entrySet()) { diff --git a/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p1/X.java b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p1/X.java new file mode 100644 index 000000000000..373c8a91481a --- /dev/null +++ b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p1/X.java @@ -0,0 +1,4 @@ +package p1; +class X { + class Y extends X {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/X.java b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/X.java new file mode 100644 index 000000000000..efd4aa02914a --- /dev/null +++ b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/X.java @@ -0,0 +1,4 @@ +package p2; +class X { + class Y extends X {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/empty.txt b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/after/p2/empty.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p1/X.java b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p1/X.java new file mode 100644 index 000000000000..373c8a91481a --- /dev/null +++ b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p1/X.java @@ -0,0 +1,4 @@ +package p1; +class X { + class Y extends X {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p2/empty.txt b/java/java-tests/testData/refactoring/copyClass/multifile/packageLocalAndExtends/before/p2/empty.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java index 04237cfa2843..8b2aa98a9b4a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java @@ -98,6 +98,10 @@ public class CopyClassTest extends CodeInsightTestCase { doMultifileTest(); } + public void testPackageLocalAndExtends() throws Exception { + doMultifileTest(); + } + //copy all classes from p1 -> p2 private void doMultifileTest() throws Exception { String root = JavaTestUtil.getJavaTestDataPath() + "/refactoring/copyClass/multifile/" + getTestName(true); From 7b26e4eb36be840c37cefebb9345e11cf59e1eb8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 13 Jan 2016 22:54:56 +0300 Subject: [PATCH 060/825] EA-77361 - NPE: AppearanceConfigurable.isModified --- .../src/com/intellij/ide/ui/AppearanceConfigurable.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index 99e0d18da88a..559eadaf70ca 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -174,7 +174,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab shouldUpdateUI = true; } - if (!myComponent.myAntialiasingInIDE.getSelectedItem().equals(settings.IDE_AA_TYPE)) { + if (myComponent.myAntialiasingInIDE.getSelectedItem() != settings.IDE_AA_TYPE) { settings.IDE_AA_TYPE = (AntialiasingType)myComponent.myAntialiasingInIDE.getSelectedItem(); for (Window w : Window.getWindows()) { for (JComponent c : UIUtil.uiTraverser(w).filter(JComponent.class)) { @@ -184,7 +184,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab shouldUpdateUI = true; } - if (!myComponent.myAntialiasingInEditor.getSelectedItem().equals(settings.EDITOR_AA_TYPE)) { + if (myComponent.myAntialiasingInEditor.getSelectedItem() != settings.EDITOR_AA_TYPE) { settings.EDITOR_AA_TYPE = (AntialiasingType)myComponent.myAntialiasingInEditor.getSelectedItem(); shouldUpdateUI = true; } @@ -401,8 +401,8 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab isModified |= !Comparing.equal(myComponent.myFontCombo.getFontName(), settings.FONT_FACE); isModified |= !Comparing.equal(myComponent.myFontSizeCombo.getEditor().getItem(), Integer.toString(settings.FONT_SIZE)); - isModified |= !myComponent.myAntialiasingInIDE.getSelectedItem().equals(settings.IDE_AA_TYPE); - isModified |= !myComponent.myAntialiasingInEditor.getSelectedItem().equals(settings.EDITOR_AA_TYPE); + isModified |= myComponent.myAntialiasingInIDE.getSelectedItem() != settings.IDE_AA_TYPE; + isModified |= myComponent.myAntialiasingInEditor.getSelectedItem() != settings.EDITOR_AA_TYPE; isModified |= myComponent.myAnimateWindowsCheckBox.isSelected() != settings.ANIMATE_WINDOWS; isModified |= myComponent.myWindowShortcutsCheckBox.isSelected() != settings.SHOW_TOOL_WINDOW_NUMBERS; From 32c619bc7799ed523eb505aa2b319911d1952a81 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 13 Jan 2016 21:41:11 +0100 Subject: [PATCH 061/825] both capturing process classes to listen to the progress manager and be cancellable --- .../process/CapturingProcessHandler.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java index d37946444b95..13331d11520f 100644 --- a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java @@ -18,7 +18,9 @@ package com.intellij.execution.process; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,15 +67,34 @@ public class CapturingProcessHandler extends OSProcessHandler { public ProcessOutput runProcess() { startNotify(); - if (waitFor()) { + if (waitForProcessListeningProgress(this)) { myOutput.setExitCode(getProcess().exitValue()); } else { LOG.info("runProcess: exit value unavailable"); } + return myOutput; } + public static boolean waitForProcessListeningProgress(ProcessHandler handler) { + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + while (!handler.waitFor(300)) { + if (indicator.isCanceled()) { + handler.destroyProcess(); + throw new ProcessCanceledException(); + } + } + } else { + if (!handler.waitFor()) { + LOG.info("runProcess: exit value unavailable"); + return false; + } + } + return true; + } + /** * Starts process with specified timeout * From c536193c49c9d0e7edf2e171bfe50ab89892ad0c Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Thu, 14 Jan 2016 11:13:07 +0300 Subject: [PATCH 062/825] PY-18191 PyCharm doesn't start via pycharm.exe --- python/resources/pycharm_core_logo.png | Bin 44561 -> 31635 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/python/resources/pycharm_core_logo.png b/python/resources/pycharm_core_logo.png index 9cbcbddcbe11b12cb77e06af7b5899e0575eac33..0fb0f25378044217505018f01c6220dbb9c1bd89 100644 GIT binary patch literal 31635 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

    tb%ML-@cv+z>%E68+oP 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 From 837950c69cf45cf4045a77155ddabebc64b389de Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 14 Jan 2016 12:07:20 +0300 Subject: [PATCH 063/825] IDEA-149852 White spaces shown in Editor are hardly noticible on HiDPI monitor --- .../openapi/editor/impl/EditorImpl.java | 40 +++++++---- .../editor/impl/view/EditorPainter.java | 67 ++++++++++++------- .../util/src/com/intellij/util/ui/JBUI.java | 2 +- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 0df463419333..24909e1e2bb2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -100,6 +100,8 @@ import javax.swing.border.Border; import javax.swing.plaf.ScrollBarUI; import javax.swing.plaf.basic.BasicScrollBarUI; import java.awt.*; +import java.awt.BasicStroke; +import java.awt.Graphics; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; @@ -3667,24 +3669,36 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi g.drawString(data.subSequence(start, end).toString(), x, y); if (drawWhitespace) { + Stroke oldStroke = ((Graphics2D)g).getStroke(); Color oldColor = g.getColor(); - g.setColor(myScheme.getColor(EditorColors.WHITESPACES_COLOR)); - final FontMetrics metrics = g.getFontMetrics(); + try { + g.setColor(myScheme.getColor(EditorColors.WHITESPACES_COLOR)); + final FontMetrics metrics = g.getFontMetrics(); + y -= 1; - for (int i = start; i < end; i++) { - final char c = data.charAt(i); - final int charWidth = isOracleRetina ? GraphicsUtil.charWidth(c, g.getFont()) : metrics.charWidth(c); + int rectSize = JBUI.scale(1); + int strokeWidth = JBUI.scale(1); + ((Graphics2D)g).setStroke(new BasicStroke(strokeWidth)); - if (c == ' ') { - g.fillRect(x + (charWidth >> 1), y, 1, 1); - } else if (c == IDEOGRAPHIC_SPACE) { - final int charHeight = getCharHeight(); - g.drawRect(x + 2, y - charHeight, charWidth - 4, charHeight); + for (int i = start; i < end; i++) { + final char c = data.charAt(i); + final int charWidth = isOracleRetina ? GraphicsUtil.charWidth(c, g.getFont()) : metrics.charWidth(c); + + if (c == ' ') { + g.fillRect(x + (charWidth - rectSize >> 1), y - rectSize + 1, rectSize, rectSize); + } + else if (c == IDEOGRAPHIC_SPACE) { + final int charHeight = getCharHeight(); + g.drawRect(x + JBUI.scale(2) + strokeWidth/2, y - charHeight + strokeWidth/2, + charWidth - JBUI.scale(4) - (strokeWidth - 1), charHeight - (strokeWidth - 1)); + } + + x += charWidth; } - - x += charWidth; + } finally { + g.setColor(oldColor); + ((Graphics2D)g).setStroke(oldStroke); } - g.setColor(oldColor); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 4eb5383e9b98..99c20dbf1e67 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -450,35 +450,50 @@ class EditorPainter implements TextDrawingCallback { private void paintWhitespace(Graphics2D g, CharSequence text, float x, int y, int start, int end, EditorImpl.LineWhitespacePaintingStrategy whitespacePaintingStrategy, VisualLineFragmentsIterator.Fragment fragment) { - g.setColor(myEditor.getColorsScheme().getColor(EditorColors.WHITESPACES_COLOR)); - boolean isRtl = fragment.isRtl(); - int baseStartOffset = fragment.getStartOffset(); - int startOffset = isRtl ? baseStartOffset - start : baseStartOffset + start; - for (int i = start; i < end; i++) { - int charOffset = isRtl ? baseStartOffset - i - 1 : baseStartOffset + i; - char c = text.charAt(charOffset); - if (" \t\u3000".indexOf(c) >= 0 && whitespacePaintingStrategy.showWhitespaceAtOffset(charOffset)) { - int startX = (int)fragment.offsetToX(x, startOffset, isRtl ? baseStartOffset - i : baseStartOffset + i); - int endX = (int)fragment.offsetToX(x, startOffset, isRtl ? baseStartOffset - i - 1 : baseStartOffset + i + 1); + Color oldColor = g.getColor(); + Stroke oldStroke = g.getStroke(); + try { + g.setColor(myEditor.getColorsScheme().getColor(EditorColors.WHITESPACES_COLOR)); - if (c == ' ') { - g.fillRect((startX + endX) / 2, y, 1, 1); - } - else if (c == '\t') { - endX -= myView.getPlainSpaceWidth() / 4; - int height = myView.getCharHeight(); - int halfHeight = height / 2; - int mid = y - halfHeight; - int top = y - height; - UIUtil.drawLine(g, startX, mid, endX, mid); - UIUtil.drawLine(g, endX, y, endX, top); - g.fillPolygon(new int[]{endX - halfHeight, endX - halfHeight, endX}, new int[]{y, y - height, y - halfHeight}, 3); - } - else if (c == '\u3000') { // ideographic space - final int charHeight = myView.getCharHeight(); - g.drawRect(startX + 2, y - charHeight, endX - startX - 4, charHeight); + int strokeWidth = JBUI.scale(1); + g.setStroke(new BasicStroke(strokeWidth)); + int rectSize = JBUI.scale(1); + + boolean isRtl = fragment.isRtl(); + int baseStartOffset = fragment.getStartOffset(); + int startOffset = isRtl ? baseStartOffset - start : baseStartOffset + start; + y -= 1; + + for (int i = start; i < end; i++) { + int charOffset = isRtl ? baseStartOffset - i - 1 : baseStartOffset + i; + char c = text.charAt(charOffset); + if (" \t\u3000".indexOf(c) >= 0 && whitespacePaintingStrategy.showWhitespaceAtOffset(charOffset)) { + int startX = (int)fragment.offsetToX(x, startOffset, isRtl ? baseStartOffset - i : baseStartOffset + i); + int endX = (int)fragment.offsetToX(x, startOffset, isRtl ? baseStartOffset - i - 1 : baseStartOffset + i + 1); + + if (c == ' ') { + g.fillRect((startX + endX - rectSize) / 2, y - rectSize + 1, rectSize, rectSize); + } + else if (c == '\t') { + endX -= myView.getPlainSpaceWidth() / 4; + int height = myView.getCharHeight(); + int halfHeight = height / 2; + int mid = y - halfHeight; + int top = y - height; + UIUtil.drawLine(g, startX, mid, endX, mid); + UIUtil.drawLine(g, endX, y, endX, top); + g.fillPolygon(new int[]{endX - halfHeight, endX - halfHeight, endX}, new int[]{y, y - height, y - halfHeight}, 3); + } + else if (c == '\u3000') { // ideographic space + int charHeight = myView.getCharHeight(); + g.drawRect(startX + JBUI.scale(2) + strokeWidth/2, y - charHeight + strokeWidth/2, + endX - startX - JBUI.scale(4) - (strokeWidth - 1), charHeight - (strokeWidth - 1)); + } } } + } finally { + g.setStroke(oldStroke); + g.setColor(oldColor); } } diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 117af24b8d49..140b649f72bc 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -101,7 +101,7 @@ public class JBUI { } public static int scale(int i) { - return (int)(SCALE_FACTOR * i); + return Math.round(SCALE_FACTOR * i); } public static int scaleFontSize(int fontSize) { From 1f8f74313fa4735ef97574a4aa5a57684b365110 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 14 Jan 2016 13:31:56 +0300 Subject: [PATCH 064/825] fix 'quick doc on mouse hover' functionality in decompiled files --- .../codeInsight/documentation/QuickDocOnMouseOverManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java index e306416ac366..95f96ed60bba 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -198,6 +198,7 @@ public class QuickDocOnMouseOverManager { } PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile instanceof PsiCompiledFile) psiFile = ((PsiCompiledFile)psiFile).getDecompiledPsiFile(); if (psiFile == null) { closeQuickDocIfPossible(); return; From 369412a2dec45a37c3f36855df93282cd0b2813c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 14 Jan 2016 12:33:01 +0300 Subject: [PATCH 065/825] soft file reference set --- .../impl/providers/SoftFileReferenceSet.java | 69 +++++++++++++++++++ .../references/FileReferenceInjector.java | 9 +-- 2 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SoftFileReferenceSet.java diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SoftFileReferenceSet.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SoftFileReferenceSet.java new file mode 100644 index 000000000000..101ac7203d9c --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SoftFileReferenceSet.java @@ -0,0 +1,69 @@ +/* + * 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. + */ +package com.intellij.psi.impl.source.resolve.reference.impl.providers; + +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReferenceProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Dennis.Ushakov + */ +public class SoftFileReferenceSet extends FileReferenceSet { + public SoftFileReferenceSet(String str, + @NotNull PsiElement element, + int startInElement, + PsiReferenceProvider provider, + boolean caseSensitive, + boolean endingSlashNotAllowed, + @Nullable FileType[] suitableFileTypes) { + super(str, element, startInElement, provider, caseSensitive, endingSlashNotAllowed, suitableFileTypes); + } + + public SoftFileReferenceSet(String str, + @NotNull PsiElement element, + int startInElement, + PsiReferenceProvider provider, + boolean caseSensitive, + boolean endingSlashNotAllowed, @Nullable FileType[] suitableFileTypes, boolean init) { + super(str, element, startInElement, provider, caseSensitive, endingSlashNotAllowed, suitableFileTypes, init); + } + + public SoftFileReferenceSet(String str, + @NotNull PsiElement element, + int startInElement, + @Nullable PsiReferenceProvider provider, boolean isCaseSensitive) { + super(str, element, startInElement, provider, isCaseSensitive); + } + + public SoftFileReferenceSet(@NotNull String str, + @NotNull PsiElement element, + int startInElement, + PsiReferenceProvider provider, boolean isCaseSensitive, boolean endingSlashNotAllowed) { + super(str, element, startInElement, provider, isCaseSensitive, endingSlashNotAllowed); + } + + public SoftFileReferenceSet(@NotNull PsiElement element) { + super(element); + } + + @Override + protected boolean isSoft() { + return true; + } +} diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java index d5d4cc813eab..b87b36ca92fd 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/references/FileReferenceInjector.java @@ -18,7 +18,7 @@ package org.intellij.plugins.intelliLang.references; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; +import com.intellij.psi.impl.source.resolve.reference.impl.providers.SoftFileReferenceSet; import com.intellij.psi.injection.ReferenceInjector; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; @@ -45,11 +45,6 @@ public class FileReferenceInjector extends ReferenceInjector { @Override public PsiReference[] getReferences(@NotNull PsiElement element, @NotNull ProcessingContext context, @NotNull TextRange range) { String text = range.substring(element.getText()); - return new FileReferenceSet(text, element, range.getStartOffset(), null, true) { - @Override - protected boolean isSoft() { - return true; - } - }.getAllReferences(); + return new SoftFileReferenceSet(text, element, range.getStartOffset(), null, true).getAllReferences(); } } From d774efb3032b0843954746044523878939ee7175 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 14 Jan 2016 13:40:08 +0300 Subject: [PATCH 066/825] IDEA-149852 [follow-up] --- .../openapi/editor/impl/EditorImpl.java | 22 +++++++++++++------ .../editor/impl/view/EditorPainter.java | 15 +++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 24909e1e2bb2..92f98cced438 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -3189,6 +3189,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi g.setFont(myFontType.getFont()); } Color currentColor = null; + int whiteSpaceStrokeWidth = JBUI.scale(1); + BasicStroke whiteSpaceStroke = new BasicStroke(whiteSpaceStrokeWidth); + for (int i = 0; i < myCount; i++) { if (!Comparing.equal(color[i], currentColor)) { currentColor = color[i] != null ? color[i] : JBColor.black; @@ -3196,7 +3199,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi g.setColor(currentColor); } - drawChars(g, data[i], starts[i], ends[i], x[i], y[i], whitespaceShown[i]); + drawChars(g, data[i], starts[i], ends[i], x[i], y[i], whitespaceShown[i], whiteSpaceStroke, whiteSpaceStrokeWidth); color[i] = null; data[i] = null; } @@ -3665,7 +3668,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return true; } - private void drawChars(@NotNull Graphics g, CharSequence data, int start, int end, int x, int y, boolean drawWhitespace) { + private void drawChars(@NotNull Graphics g, + CharSequence data, + int start, + int end, + int x, + int y, + boolean drawWhitespace, + BasicStroke stroke, + int strokeWidth) { g.drawString(data.subSequence(start, end).toString(), x, y); if (drawWhitespace) { @@ -3673,19 +3684,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi Color oldColor = g.getColor(); try { g.setColor(myScheme.getColor(EditorColors.WHITESPACES_COLOR)); + ((Graphics2D)g).setStroke(stroke); final FontMetrics metrics = g.getFontMetrics(); y -= 1; - int rectSize = JBUI.scale(1); - int strokeWidth = JBUI.scale(1); - ((Graphics2D)g).setStroke(new BasicStroke(strokeWidth)); - for (int i = start; i < end; i++) { final char c = data.charAt(i); final int charWidth = isOracleRetina ? GraphicsUtil.charWidth(c, g.getFont()) : metrics.charWidth(c); if (c == ' ') { - g.fillRect(x + (charWidth - rectSize >> 1), y - rectSize + 1, rectSize, rectSize); + g.fillRect(x + (charWidth - strokeWidth >> 1), y - strokeWidth + 1, strokeWidth, strokeWidth); } else if (c == IDEOGRAPHIC_SPACE) { final int charHeight = getCharHeight(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 99c20dbf1e67..77467601959f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -330,6 +330,8 @@ class EditorPainter implements TextDrawingCallback { final EditorImpl.LineWhitespacePaintingStrategy whitespacePaintingStrategy = myEditor.new LineWhitespacePaintingStrategy(); boolean paintAllSoftWraps = myEditor.getSettings().isAllSoftWrapsShown(); int lineCount = myEditor.getVisibleLineCount(); + final int whiteSpaceStrokeWidth = JBUI.scale(1); + final Stroke whiteSpaceStroke = new BasicStroke(whiteSpaceStrokeWidth); LineLayout prefixLayout = myView.getPrefixLayout(); if (startVisualLine == 0 && prefixLayout != null) { @@ -372,7 +374,7 @@ class EditorPainter implements TextDrawingCallback { whitespacePaintingStrategy.update(text, myDocument.getLineStartOffset(logicalLine), myDocument.getLineEndOffset(logicalLine)); currentLogicalLine[0] = logicalLine; } - paintWhitespace(g, text, xStart, y, start, end, whitespacePaintingStrategy, fragment); + paintWhitespace(g, text, xStart, y, start, end, whitespacePaintingStrategy, fragment, whiteSpaceStroke, whiteSpaceStrokeWidth); } boolean allowBorder = fragment.getCurrentFoldRegion() != null; if (attributes != null && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType(), allowBorder)) { @@ -449,15 +451,11 @@ class EditorPainter implements TextDrawingCallback { private void paintWhitespace(Graphics2D g, CharSequence text, float x, int y, int start, int end, EditorImpl.LineWhitespacePaintingStrategy whitespacePaintingStrategy, - VisualLineFragmentsIterator.Fragment fragment) { - Color oldColor = g.getColor(); + VisualLineFragmentsIterator.Fragment fragment, Stroke stroke, int strokeWidth) { Stroke oldStroke = g.getStroke(); try { g.setColor(myEditor.getColorsScheme().getColor(EditorColors.WHITESPACES_COLOR)); - - int strokeWidth = JBUI.scale(1); - g.setStroke(new BasicStroke(strokeWidth)); - int rectSize = JBUI.scale(1); + g.setStroke(stroke); // applied for tab & ideographic space boolean isRtl = fragment.isRtl(); int baseStartOffset = fragment.getStartOffset(); @@ -472,7 +470,7 @@ class EditorPainter implements TextDrawingCallback { int endX = (int)fragment.offsetToX(x, startOffset, isRtl ? baseStartOffset - i - 1 : baseStartOffset + i + 1); if (c == ' ') { - g.fillRect((startX + endX - rectSize) / 2, y - rectSize + 1, rectSize, rectSize); + g.fillRect((startX + endX - strokeWidth) / 2, y - strokeWidth + 1, strokeWidth, strokeWidth); } else if (c == '\t') { endX -= myView.getPlainSpaceWidth() / 4; @@ -493,7 +491,6 @@ class EditorPainter implements TextDrawingCallback { } } finally { g.setStroke(oldStroke); - g.setColor(oldColor); } } From 9805cfad680ea4b4e38326e73578b164d122d5d6 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Thu, 14 Jan 2016 13:51:39 +0300 Subject: [PATCH 067/825] javadoc for TemplatePreprocessor --- .../template/impl/TemplatePreprocessor.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplatePreprocessor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplatePreprocessor.java index 0bc04d7dc6c0..32bd89489b6b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplatePreprocessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplatePreprocessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -16,12 +16,18 @@ package com.intellij.codeInsight.template.impl; -import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiFile; /** - * @author yole + * When an template is started, allows to prepare the editor before actual template expanding. + * + * For example, for some XML-based languages it make sense to check whether text of template contains + * unescaped character and insert CDATA-element to the editor before template expanding. + * + * @see TemplateOptionalProcessor + * @see com.intellij.codeInsight.template.TemplateSubstitutor */ public interface TemplatePreprocessor { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.liveTemplatePreprocessor"); From 71e61af2ffb061c933198846f2de8576bb31b27f Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 14 Jan 2016 13:56:04 +0300 Subject: [PATCH 068/825] IDEA-80778 recollapse fold regions, expanded previously, when iterating over find results in editor --- .../find/impl/livePreview/SelectionManager.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java index 50f37927c506..a0b9714c12f6 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -21,8 +21,12 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + public class SelectionManager { @NotNull private final SearchResults mySearchResults; + private final List myRegionsToRestore = new ArrayList(); public SelectionManager(@NotNull SearchResults results) { mySearchResults = results; @@ -45,10 +49,17 @@ public class SelectionManager { foldingModel.runBatchFoldingOperation(new Runnable() { @Override public void run() { + for (FoldRegion region : myRegionsToRestore) { + if (region.isValid()) region.setExpanded(false); + } + myRegionsToRestore.clear(); for (FoldRegion region : allRegions) { if (!region.isValid()) continue; if (cursor.intersects(TextRange.create(region))) { - region.setExpanded(true); + if (!region.isExpanded()) { + region.setExpanded(true); + myRegionsToRestore.add(region); + } } } } From 9007fe6695d4e659d5bf9d3f4ef331a0f86d7d71 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 13 Jan 2016 14:02:37 +0300 Subject: [PATCH 069/825] lst: recalculate ranges on error --- .../com/intellij/openapi/vcs/ex/LineStatusTracker.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 9177842c6680..03afa30f617c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -405,8 +405,14 @@ public class LineStatusTracker { synchronized (myLock) { if (!myInitialized || myReleased || myBulkUpdate || myDuringRollback || myAnathemaThrown) return; if (myDirtyRange != null) { - doUpdateRanges(myDirtyRange.line1, myDirtyRange.line2, myDirtyRange.lineShift, myDirtyRange.beforeTotalLines); - myDirtyRange = null; + try { + doUpdateRanges(myDirtyRange.line1, myDirtyRange.line2, myDirtyRange.lineShift, myDirtyRange.beforeTotalLines); + myDirtyRange = null; + } + catch (Exception e) { + LOG.error(e); + reinstallRanges(); + } } } } From d7565314af49b4d3f116059b7c793e831d1c252f Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 13 Jan 2016 14:18:18 +0300 Subject: [PATCH 070/825] lst: check passed line range bounds --- .../src/com/intellij/diff/util/DiffUtil.java | 21 ++++++ .../openapi/vcs/ex/DocumentWrapper.java | 66 ------------------- .../openapi/vcs/ex/LineStatusTracker.java | 4 +- .../openapi/vcs/ex/RangesBuilder.java | 3 +- 4 files changed, 25 insertions(+), 69 deletions(-) delete mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/ex/DocumentWrapper.java diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index d7c9affaeff6..bb1f9b7aa893 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -782,6 +782,27 @@ public class DiffUtil { return Math.max(document.getLineCount(), 1); } + @NotNull + public static List getLines(@NotNull Document document) { + return getLines(document, 0, getLineCount(document)); + } + + @NotNull + public static List getLines(@NotNull Document document, int startLine, int endLine) { + if (startLine < 0 || startLine > endLine || endLine > getLineCount(document)) { + throw new IndexOutOfBoundsException(String.format("Wrong line range: [%d, %d); lineCount: '%d'", + startLine, endLine, document.getLineCount())); + } + + List result = new ArrayList(); + for (int i = startLine; i < endLine; i++) { + int start = document.getLineStartOffset(i); + int end = document.getLineEndOffset(i); + result.add(document.getText(new TextRange(start, end))); + } + return result; + } + // // Updating ranges on change // diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/DocumentWrapper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/DocumentWrapper.java deleted file mode 100644 index 1674b55ff3b6..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/DocumentWrapper.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2000-2009 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.openapi.vcs.ex; - -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.TextRange; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * author: lesya - */ -public class DocumentWrapper { - private final Document myDocument; - - public DocumentWrapper(@NotNull Document document) { - myDocument = document; - } - - public int getLineNum(int offset) { - return myDocument.getLineNumber(offset); - } - - @NotNull - public List getLines() { - return getLines(0, getLineCount(myDocument) - 1); - } - - @NotNull - public List getLines(int from, int to) { - ArrayList result = new ArrayList(); - for (int i = from; i <= to; i++) { - result.add(getLine(i)); - } - return result; - } - - @NotNull - private String getLine(final int i) { - TextRange range = new TextRange(myDocument.getLineStartOffset(i), myDocument.getLineEndOffset(i)); - if (range.getLength() < 0) { - assert false : myDocument; - } - return myDocument.getText(range); - } - - private static int getLineCount(@NotNull Document document) { - return Math.max(document.getLineCount(), 1); - } -} - diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 03afa30f617c..4e66b5627148 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -628,8 +628,8 @@ public class LineStatusTracker { return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2)); } - List lines = new DocumentWrapper(myDocument).getLines(changedLine1, changedLine2 - 1); - List vcsLines = new DocumentWrapper(myVcsDocument).getLines(vcsLine1, vcsLine2 - 1); + List lines = DiffUtil.getLines(myDocument, changedLine1, changedLine2); + List vcsLines = DiffUtil.getLines(myVcsDocument, vcsLine1, vcsLine2); return new RangesBuilder(lines, vcsLines, changedLine1, vcsLine1, myMode).getRanges(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java index 6b795a294873..18202a0a6d46 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vcs.ex; +import com.intellij.diff.util.DiffUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.text.StringUtil; @@ -46,7 +47,7 @@ public class RangesBuilder { @NotNull Document vcs, @NotNull LineStatusTracker.Mode mode) throws FilesTooBigForDiffException { - this(new DocumentWrapper(current).getLines(), new DocumentWrapper(vcs).getLines(), 0, 0, mode); + this(DiffUtil.getLines(current), DiffUtil.getLines(vcs), 0, 0, mode); } public RangesBuilder(@NotNull List current, From 3d8ecff7e8391aa8977e4dd56bd46c43f8c52484 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 13 Jan 2016 14:51:12 +0300 Subject: [PATCH 071/825] lst: make RangesBuilder stateless --- .../VcsAwareFormatChangedTextUtil.java | 2 +- .../openapi/vcs/ex/LineStatusTracker.java | 4 +- .../openapi/vcs/ex/RangesBuilder.java | 79 +++++-------------- 3 files changed, 23 insertions(+), 62 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/codeInsight/actions/VcsAwareFormatChangedTextUtil.java b/platform/vcs-impl/src/com/intellij/codeInsight/actions/VcsAwareFormatChangedTextUtil.java index 08bf464035da..da1a77e3c279 100644 --- a/platform/vcs-impl/src/com/intellij/codeInsight/actions/VcsAwareFormatChangedTextUtil.java +++ b/platform/vcs-impl/src/com/intellij/codeInsight/actions/VcsAwareFormatChangedTextUtil.java @@ -113,7 +113,7 @@ class VcsAwareFormatChangedTextUtil extends FormatChangedTextUtil { @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException { Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); - return new RangesBuilder(document, documentFromVcs).getRanges(); + return RangesBuilder.createRanges(document, documentFromVcs); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 4e66b5627148..d40546df0d85 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -152,7 +152,7 @@ public class LineStatusTracker { destroyRanges(); try { - myRanges = new RangesBuilder(myDocument, myVcsDocument, myMode).getRanges(); + myRanges = RangesBuilder.createRanges(myDocument, myVcsDocument, myMode == Mode.SMART); for (final Range range : myRanges) { createHighlighter(range); } @@ -631,7 +631,7 @@ public class LineStatusTracker { List lines = DiffUtil.getLines(myDocument, changedLine1, changedLine2); List vcsLines = DiffUtil.getLines(myVcsDocument, vcsLine1, vcsLine2); - return new RangesBuilder(lines, vcsLines, changedLine1, vcsLine1, myMode).getRanges(); + return RangesBuilder.createRanges(lines, vcsLines, changedLine1, vcsLine1, myMode == Mode.SMART); } private static void shiftRanges(@NotNull List rangesAfterChange, int shift) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java index 18202a0a6d46..56d7ca2449ee 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java @@ -26,80 +26,41 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; -/** - * author: lesya - */ - public class RangesBuilder { private static final Logger LOG = Logger.getInstance(RangesBuilder.class); - @NotNull private final List myRanges; - - public RangesBuilder(@NotNull Document current, - @NotNull Document vcs) throws FilesTooBigForDiffException { - this(current, vcs, LineStatusTracker.Mode.DEFAULT); - } - - public RangesBuilder(@NotNull Document current, - @NotNull Document vcs, - @NotNull LineStatusTracker.Mode mode) - throws FilesTooBigForDiffException { - this(DiffUtil.getLines(current), DiffUtil.getLines(vcs), 0, 0, mode); - } - - public RangesBuilder(@NotNull List current, - @NotNull List vcs, - int shift, - int vcsShift, - @NotNull LineStatusTracker.Mode mode) - throws FilesTooBigForDiffException { - myRanges = new LinkedList(); - - switch (mode) { - case DEFAULT: - case SILENT: - processDefault(current, vcs, shift, vcsShift); - break; - case SMART: - processSmart(current, vcs, shift, vcsShift); - break; - default: - throw new IllegalStateException(); - } + @NotNull + public static List createRanges(@NotNull Document current, @NotNull Document vcs) throws FilesTooBigForDiffException { + return createRanges(current, vcs, false); } @NotNull - public List getRanges() { - return myRanges; + public static List createRanges(@NotNull Document current, @NotNull Document vcs, boolean innerWhitespaceChanges) + throws FilesTooBigForDiffException { + return createRanges(DiffUtil.getLines(current), DiffUtil.getLines(vcs), 0, 0, innerWhitespaceChanges); } - private void processDefault(@NotNull List current, - @NotNull List vcs, - int shift, - int vcsShift) throws FilesTooBigForDiffException { + @NotNull + public static List createRanges(@NotNull List current, + @NotNull List vcs, + int shift, + int vcsShift, + boolean innerWhitespaceChanges) throws FilesTooBigForDiffException { Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(vcs), ArrayUtil.toStringArray(current)); + List result = new ArrayList(); while (ch != null) { - Range range = createOn(ch, shift, vcsShift); - myRanges.add(range); - ch = ch.link; - } - } - - private void processSmart(@NotNull List current, - @NotNull List vcs, - int shift, - int vcsShift) throws FilesTooBigForDiffException { - Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(vcs), ArrayUtil.toStringArray(current)); - - while (ch != null) { - Range range = createOnSmart(ch, shift, vcsShift, current, vcs); - myRanges.add(range); + if (innerWhitespaceChanges) { + result.add(createOnSmart(ch, shift, vcsShift, current, vcs)); + } + else { + result.add(createOn(ch, shift, vcsShift)); + } ch = ch.link; } + return result; } private static Range createOn(@NotNull Diff.Change change, int shift, int vcsShift) { From 9966e06c5488f58759ca516466d890179410ba30 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 11 Jan 2016 16:13:30 +0300 Subject: [PATCH 072/825] editor: better name for gutter area --- .../openapi/editor/impl/EditorGutterComponentImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 43d91537532b..2cba360d0cff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -103,7 +103,7 @@ import java.util.List; *
      *
    • Left free painters
    • *
    • Icons
    • - *
    • Debugger additional area
    • + *
    • Gap (required by debugger to set breakpoints with mouse click - IDEA-137353)
    • *
    • Free painters
    • *
    * @@ -1186,7 +1186,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse public int getLineMarkerAreaWidth() { return isLineMarkersShown() ? getLeftFreePaintersAreaWidth() + myIconsAreaWidth + - getDebuggerAdditionalAreaWidth() + getRightFreePaintersAreaWidth() : 0; + getGapAfterIconsArea() + getRightFreePaintersAreaWidth() : 0; } public void setLineNumberAreaWidthFunction(@NotNull TIntFunction calculator) { @@ -1276,7 +1276,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Override public int getLineMarkerFreePaintersAreaOffset() { - return getIconAreaOffset() + myIconsAreaWidth + getDebuggerAdditionalAreaWidth(); + return getIconAreaOffset() + myIconsAreaWidth + getGapAfterIconsArea(); } public int getLeftFreePaintersAreaWidth() { @@ -1292,7 +1292,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse return myIconsAreaWidth; } - public int getDebuggerAdditionalAreaWidth() { + public int getGapAfterIconsArea() { return isRealEditor() ? GAP_BETWEEN_AREAS : 0; } From fe28d3d31b510325876192ea5c25a52a6f249125 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 12:15:41 +0100 Subject: [PATCH 073/825] [java] using "InnerClasses" attribute for resolving binary names in .class stubs (IDEA-82515) Previously, IDEA relied on heuristics to resolve binary names like "Map$Entry" into a source form ("Map.Entry"). The problem with this approach is that '$' is a legal part of Java identifiers. The fix (1) consolidates the heuristics from two different places into a single mapper, and (2) allows to use "InnerTables" attribute instead (according to JVMS 4.7.6, it should contain at least some of the referenced inner classes) - this part is disabled by default. --- .../impl/compiled/ClassFileStubBuilder.java | 8 +- .../psi/impl/compiled/SignatureParsing.java | 224 +++----- .../impl/compiled/StubBuildingVisitor.java | 495 ++++++++++-------- .../java/stubs/impl/PsiMethodStubImpl.java | 40 +- .../intellij/psi/SignatureParsingTest.java | 21 +- .../util/resources/misc/registry.properties | 5 + .../resolve/GroovyTraitFieldsFileIndex.java | 27 +- 7 files changed, 422 insertions(+), 398 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java index 89125f17034c..baec88c7997e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java @@ -38,7 +38,7 @@ import static com.intellij.psi.compiled.ClassFileDecompilers.Full; public class ClassFileStubBuilder implements BinaryFileStubBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder"); - public static final int STUB_VERSION = 12; + public static final int STUB_VERSION = 13; @Override public boolean acceptsFile(@NotNull VirtualFile file) { @@ -59,7 +59,8 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder { } } catch (ClsFormatException e) { - LOG.debug(e); + if (LOG.isDebugEnabled()) LOG.debug(file.getPath(), e); + else LOG.info(file.getPath() + ": " + e.getMessage()); } try { @@ -70,7 +71,8 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder { return stub; } catch (ClsFormatException e) { - LOG.debug(e); + if (LOG.isDebugEnabled()) LOG.debug(file.getPath(), e); + else LOG.info(file.getPath() + ": " + e.getMessage()); } } finally { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java index b4212b628fa8..215b50a65720 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -15,63 +15,60 @@ */ package com.intellij.psi.impl.compiled; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; -import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; -import com.intellij.psi.impl.java.stubs.PsiTypeParameterListStub; -import com.intellij.psi.impl.java.stubs.PsiTypeParameterStub; -import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterListStubImpl; -import com.intellij.psi.impl.java.stubs.impl.PsiTypeParameterStubImpl; -import com.intellij.psi.stubs.StubElement; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.cls.ClsFormatException; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.StringRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.text.CharacterIterator; +import java.util.Collections; import java.util.List; +import static com.intellij.openapi.util.Pair.pair; + /** * @author max */ public class SignatureParsing { private SignatureParsing() { } - public static PsiTypeParameterListStub parseTypeParametersDeclaration(CharacterIterator iterator, StubElement parentStub) throws ClsFormatException { - PsiTypeParameterListStub list = new PsiTypeParameterListStubImpl(parentStub); - - if (iterator.current() == '<') { - iterator.next(); - while (iterator.current() != '>') { - parseTypeParameter(iterator, list); - } - iterator.next(); + @NotNull + public static List> parseTypeParametersDeclaration(CharacterIterator signature, Function mapping) throws ClsFormatException { + if (signature.current() != '<') { + return Collections.emptyList(); } - return list; + List> typeParameters = ContainerUtil.newArrayList(); + signature.next(); + while (signature.current() != '>') { + typeParameters.add(parseTypeParameter(signature, mapping)); + } + signature.next(); + return typeParameters; } - private static PsiTypeParameterStub parseTypeParameter(CharacterIterator iterator, PsiTypeParameterListStub parent) throws ClsFormatException { + private static Pair parseTypeParameter(CharacterIterator signature, Function mapping) throws ClsFormatException { StringBuilder name = new StringBuilder(); - while (iterator.current() != ':' && iterator.current() != CharacterIterator.DONE) { - name.append(iterator.current()); - iterator.next(); + while (signature.current() != ':' && signature.current() != CharacterIterator.DONE) { + name.append(signature.current()); + signature.next(); } - if (iterator.current() == CharacterIterator.DONE) { + if (signature.current() == CharacterIterator.DONE) { throw new ClsFormatException(); } - - //todo parse annotations on type param - PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(parent, StringRef.fromString(name.toString())); + String parameterName = mapping.fun(name.toString()); // postpone list allocation till a second bound is seen; ignore sole Object bound List bounds = null; boolean jlo = false; - while (iterator.current() == ':') { - iterator.next(); - String bound = parseTopLevelClassRefSignature(iterator); + while (signature.current() == ':') { + signature.next(); + String bound = parseTopLevelClassRefSignature(signature, mapping); if (bound == null) continue; if (bounds == null) { if (CommonClassNames.JAVA_LANG_OBJECT.equals(bound)) { @@ -86,25 +83,25 @@ public class SignatureParsing { bounds.add(bound); } - StubBuildingVisitor.newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, ArrayUtil.toStringArray(bounds)); - - return parameterStub; + return pair(parameterName, ArrayUtil.toStringArray(bounds)); } @Nullable - public static String parseTopLevelClassRefSignature(CharacterIterator signature) throws ClsFormatException { - if (signature.current() == 'L') { - return parseParameterizedClassRefSignature(signature); + public static String parseTopLevelClassRefSignature(CharacterIterator signature, Function mapping) throws ClsFormatException { + switch (signature.current()) { + case 'L': + return parseParameterizedClassRefSignature(signature, mapping); + case 'T': + return parseTypeVariableRefSignature(signature); + default: + return null; } - if (signature.current() == 'T') { - return parseTypeVariableRefSignature(signature); - } - return null; } private static String parseTypeVariableRefSignature(CharacterIterator signature) { - signature.next(); StringBuilder id = new StringBuilder(); + + signature.next(); while (signature.current() != ';' && signature.current() != '>') { id.append(signature.current()); signature.next(); @@ -117,50 +114,27 @@ public class SignatureParsing { return id.toString(); } - private static String parseParameterizedClassRefSignature(CharacterIterator signature) throws ClsFormatException { - assert signature.current() == 'L'; - + private static String parseParameterizedClassRefSignature(CharacterIterator signature, Function mapping) throws ClsFormatException { StringBuilder canonicalText = new StringBuilder(); + boolean mapped = false, firstArg; signature.next(); while (signature.current() != ';' && signature.current() != CharacterIterator.DONE) { - switch (signature.current()) { - case '$': - if (signature.getIndex() > 0) { - char previous = signature.previous(); - signature.next(); - boolean standAlone$ = !StringUtil.isJavaIdentifierPart(previous); // /$ - if (standAlone$) { - canonicalText.append('$'); - break; - } - else if (signature.getIndex() + 1 < signature.getEndIndex()) { - char next = signature.next(); - signature.previous(); - standAlone$ = !StringUtil.isJavaIdentifierPart(next); // $; - if (standAlone$) { - canonicalText.append('$'); - break; - } - } - } - case '/': - case '.': - canonicalText.append('.'); - break; - case '<': - canonicalText.append('<'); - signature.next(); - do { - processTypeArgument(signature, canonicalText); - } - while (signature.current() != '>'); - canonicalText.append('>'); - break; - case ' ': - break; - default: - canonicalText.append(signature.current()); + char c = signature.current(); + if (c == '<') { + canonicalText = new StringBuilder(mapping.fun(canonicalText.toString())); + mapped = true; + firstArg = true; + signature.next(); + do { + canonicalText.append(firstArg ? '<' : ',').append(parseClassOrTypeVariableElement(signature, mapping)); + firstArg = false; + } + while (signature.current() != '>'); + canonicalText.append('>'); + } + else if (c != ' ') { + canonicalText.append(c); } signature.next(); } @@ -168,53 +142,29 @@ public class SignatureParsing { if (signature.current() == CharacterIterator.DONE) { throw new ClsFormatException(); } - - for (int index = 0; index < canonicalText.length(); index++) { - final char c = canonicalText.charAt(index); - if ('0' <= c && c <= '1') { - if (index > 0 && canonicalText.charAt(index - 1) == '.') { - canonicalText.setCharAt(index - 1, '$'); - } - } - } - signature.next(); - return canonicalText.toString(); + String text = canonicalText.toString(); + if (!mapped) text = mapping.fun(text); + return text; } - private static void processTypeArgument(CharacterIterator signature, StringBuilder canonicalText) throws ClsFormatException { - String typeArgument = parseClassOrTypeVariableElement(signature); - canonicalText.append(typeArgument); - if (signature.current() != '>') { - canonicalText.append(','); - } - } - - public static String parseClassOrTypeVariableElement(CharacterIterator signature) throws ClsFormatException { + private static String parseClassOrTypeVariableElement(CharacterIterator signature, Function mapping) throws ClsFormatException { char variance = parseVariance(signature); if (variance == '*') { - return decorateTypeText("*", variance); + return decorateTypeText(null, variance); } - int arrayCount = 0; - while (signature.current() == '[') { - arrayCount++; - signature.next(); + int dimensions = parseDimensions(signature); + + String text = parseTypeWithoutVariance(signature, mapping); + if (text == null) throw new ClsFormatException(); + + if (dimensions > 0) { + text += StringUtil.repeat("[]", dimensions); } - final String type = parseTypeWithoutVariance(signature); - if (type != null) { - String ref = type; - while (arrayCount > 0) { - ref += "[]"; - arrayCount--; - } - return decorateTypeText(ref, variance); - } - else { - throw new ClsFormatException(); - } + return decorateTypeText(text, variance); } private static final char VARIANCE_NONE = '\0'; @@ -224,7 +174,7 @@ public class SignatureParsing { private static final String VARIANCE_EXTENDS_PREFIX = "? extends "; private static final String VARIANCE_SUPER_PREFIX = "? super "; - private static String decorateTypeText(final String canonical, final char variance) { + private static String decorateTypeText(String canonical, char variance) { switch (variance) { case VARIANCE_NONE: return canonical; @@ -256,39 +206,39 @@ public class SignatureParsing { default: variance = '\0'; } - return variance; } - @NotNull - public static String parseTypeString(@NotNull CharacterIterator signature) throws ClsFormatException { - int arrayDimensions = 0; + private static int parseDimensions(CharacterIterator signature) { + int dimensions = 0; while (signature.current() == '[') { - arrayDimensions++; + dimensions++; signature.next(); } + return dimensions; + } - char variance = parseVariance(signature); + @NotNull + public static String parseTypeString(CharacterIterator signature, Function mapping) throws ClsFormatException { + int dimensions = parseDimensions(signature); - String text = parseTypeWithoutVariance(signature); + String text = parseTypeWithoutVariance(signature, mapping); if (text == null) throw new ClsFormatException(); - for (int i = 0; i < arrayDimensions; i++) { - text += "[]"; - } - if (variance != '\0') { - text = variance + text; + if (dimensions > 0) { + text += StringUtil.repeat("[]", dimensions); } + return text; } @Nullable - private static String parseTypeWithoutVariance(final CharacterIterator signature) throws ClsFormatException { - final String text; - switch (signature.current()) { + private static String parseTypeWithoutVariance(CharacterIterator signature, Function mapping) throws ClsFormatException { + String text = null; + switch (signature.current()) { case 'L': - text = parseParameterizedClassRefSignature(signature); + text = parseParameterizedClassRefSignature(signature, mapping); break; case 'T': @@ -339,10 +289,8 @@ public class SignatureParsing { text = "void"; signature.next(); break; - - default: - return null; } + return text; } -} +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java index 464d8ed1e393..aae08dbc0565 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java @@ -15,7 +15,11 @@ */ package com.intellij.psi.impl.compiled; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiNameHelper; import com.intellij.psi.PsiReferenceList; @@ -27,7 +31,10 @@ import com.intellij.psi.stubs.PsiFileStub; import com.intellij.psi.stubs.StubElement; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; +import com.intellij.util.Function; import com.intellij.util.cls.ClsFormatException; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.io.StringRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.*; @@ -35,10 +42,10 @@ import org.jetbrains.org.objectweb.asm.*; import java.lang.reflect.Array; import java.text.CharacterIterator; import java.text.StringCharacterIterator; -import java.util.ArrayList; import java.util.List; -import java.util.regex.Pattern; +import java.util.Map; +import static com.intellij.openapi.util.Pair.pair; import static com.intellij.psi.CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION; import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING; @@ -46,26 +53,27 @@ import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING; * @author max */ public class StubBuildingVisitor extends ClassVisitor { - private static final Pattern REGEX_PATTERN = Pattern.compile("(?<=[^\\$\\.])\\$(?=[^\\$])"); // disallow .$ or $$ + private static final Logger LOG = Logger.getInstance(StubBuildingVisitor.class); - public static final String DOUBLE_POSITIVE_INF = "1.0 / 0.0"; - public static final String DOUBLE_NEGATIVE_INF = "-1.0 / 0.0"; - public static final String DOUBLE_NAN = "0.0d / 0.0"; - - public static final String FLOAT_POSITIVE_INF = "1.0f / 0.0"; - public static final String FLOAT_NEGATIVE_INF = "-1.0f / 0.0"; - public static final String FLOAT_NAN = "0.0f / 0.0"; - - private static final int ASM_API = Opcodes.ASM5; + private static final boolean MAP_INNER_CLASSES_BY_TABLE = Registry.is("java.lib.inner.class.detection.by.table"); + private static final String DOUBLE_POSITIVE_INF = "1.0 / 0.0"; + private static final String DOUBLE_NEGATIVE_INF = "-1.0 / 0.0"; + private static final String DOUBLE_NAN = "0.0d / 0.0"; + private static final String FLOAT_POSITIVE_INF = "1.0f / 0.0"; + private static final String FLOAT_NEGATIVE_INF = "-1.0f / 0.0"; + private static final String FLOAT_NAN = "0.0f / 0.0"; private static final String SYNTHETIC_CLASS_INIT_METHOD = ""; private static final String SYNTHETIC_INIT_METHOD = ""; + private static final int ASM_API = Opcodes.ASM5; + private final T mySource; private final InnerClassSourceStrategy myInnersStrategy; private final StubElement myParent; private final int myAccess; private final String myShortName; + private final Function myMapping; private String myInternalName; private PsiClassStub myResult; private PsiModifierListStub myModList; @@ -77,6 +85,9 @@ public class StubBuildingVisitor extends ClassVisitor { myParent = parent; myAccess = access; myShortName = shortName; + + Map> mapping = loadMapping(classSource); + myMapping = mapping != null ? createMapping(mapping) : GUESSING_MAPPER; } public PsiClassStub getResult() { @@ -97,7 +108,6 @@ public class StubBuildingVisitor extends ClassVisitor { boolean isInterface = (flags & Opcodes.ACC_INTERFACE) != 0; boolean isEnum = (flags & Opcodes.ACC_ENUM) != 0; boolean isAnnotationType = (flags & Opcodes.ACC_ANNOTATION) != 0; - byte stubFlags = PsiClassStubImpl.packFlags(isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false); myResult = new PsiClassStubImpl(JavaStubElementTypes.CLASS, myParent, fqn, shortName, null, stubFlags); @@ -107,66 +117,82 @@ public class StubBuildingVisitor extends ClassVisitor { myModList = new PsiModifierListStubImpl(myResult, packClassFlags(flags)); - CharacterIterator signatureIterator = signature != null ? new StringCharacterIterator(signature) : null; - if (signatureIterator != null) { + ClassInfo info = null; + if (signature != null) { try { - SignatureParsing.parseTypeParametersDeclaration(signatureIterator, myResult); - } - catch (ClsFormatException e) { - signatureIterator = null; + info = parseClassSignature(signature); } + catch (ClsFormatException e) { LOG.warn(signature, e); } } - else { - new PsiTypeParameterListStubImpl(myResult); + if (info == null) { + info = parseClassDescription(superName, interfaces); } - String convertedSuper; - List convertedInterfaces = new ArrayList(); - if (signatureIterator == null) { - convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces); - } - else { - try { - convertedSuper = parseClassSignature(signatureIterator, convertedInterfaces); - } - catch (ClsFormatException e) { - new PsiTypeParameterListStubImpl(myResult); - convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces); - } + PsiTypeParameterListStub typeParameterList = new PsiTypeParameterListStubImpl(myResult); + for (Pair parameter : info.typeParameters) { + PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(typeParameterList, StringRef.fromString(parameter.first)); + newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, parameter.second); } - if (isInterface) { - if (isAnnotationType) { - convertedInterfaces.remove(JAVA_LANG_ANNOTATION_ANNOTATION); + if (myResult.isInterface()) { + if (info.interfaceNames != null && myResult.isAnnotationType()) { + info.interfaceNames.remove(JAVA_LANG_ANNOTATION_ANNOTATION); } - newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces)); + newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.toStringArray(info.interfaceNames)); newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.EMPTY_STRING_ARRAY); } else { - if (convertedSuper == null || "java/lang/Object".equals(superName) || isEnum && "java/lang/Enum".equals(superName)) { + if (info.superName == null || "java/lang/Object".equals(superName) || myResult.isEnum() && "java/lang/Enum".equals(superName)) { newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.EMPTY_STRING_ARRAY); } else { - newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, new String[]{convertedSuper}); + newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, new String[]{info.superName}); } - newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces)); + newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.toStringArray(info.interfaceNames)); } } - private static String getFqn(@NotNull String internalName, @Nullable String shortName, @Nullable String parentName) { + private String getFqn(@NotNull String internalName, @Nullable String shortName, @Nullable String parentName) { if (shortName == null || !internalName.endsWith(shortName)) { - return getClassName(internalName); + return myMapping.fun(internalName); } if (internalName.length() == shortName.length()) { return shortName; } if (parentName == null) { - parentName = getClassName(internalName.substring(0, internalName.length() - shortName.length() - 1)); + parentName = myMapping.fun(internalName.substring(0, internalName.length() - shortName.length() - 1)); } return parentName + '.' + shortName; } - public static void newReferenceList(JavaClassReferenceListElementType type, StubElement parent, String[] types) { + private ClassInfo parseClassSignature(String signature) throws ClsFormatException { + ClassInfo result = new ClassInfo(); + CharacterIterator iterator = new StringCharacterIterator(signature); + result.typeParameters = SignatureParsing.parseTypeParametersDeclaration(iterator, myMapping); + result.superName = SignatureParsing.parseTopLevelClassRefSignature(iterator, myMapping); + while (iterator.current() != CharacterIterator.DONE) { + String name = SignatureParsing.parseTopLevelClassRefSignature(iterator, myMapping); + if (name == null) throw new ClsFormatException(); + if (result.interfaceNames == null) result.interfaceNames = ContainerUtil.newSmartList(); + result.interfaceNames.add(name); + } + return result; + } + + private ClassInfo parseClassDescription(String superClass, String[] superInterfaces) { + ClassInfo result = new ClassInfo(); + result.typeParameters = ContainerUtil.emptyList(); + result.superName = superClass != null ? myMapping.fun(superClass) : null; + result.interfaceNames = superInterfaces == null ? null : ContainerUtil.map(superInterfaces, new Function() { + @Override + public String fun(String name) { + return myMapping.fun(name); + } + }); + return result; + } + + private static void newReferenceList(JavaClassReferenceListElementType type, StubElement parent, String[] types) { PsiReferenceList.Role role; if (type == JavaStubElementTypes.EXTENDS_LIST) role = PsiReferenceList.Role.EXTENDS_LIST; @@ -178,26 +204,6 @@ public class StubBuildingVisitor extends ClassVisitor { new PsiClassReferenceListStubImpl(type, parent, types, role); } - @Nullable - private static String parseClassDescription(String superName, String[] interfaces, List convertedInterfaces) { - String convertedSuper = superName != null ? getClassName(superName) : null; - for (String anInterface : interfaces) { - convertedInterfaces.add(getClassName(anInterface)); - } - return convertedSuper; - } - - @Nullable - private static String parseClassSignature(CharacterIterator signatureIterator, List convertedInterfaces) throws ClsFormatException { - String convertedSuper = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator); - while (signatureIterator.current() != CharacterIterator.DONE) { - String ifs = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator); - if (ifs == null) throw new ClsFormatException(); - convertedInterfaces.add(ifs); - } - return convertedSuper; - } - private static int packCommonFlags(int access) { int flags = 0; @@ -252,7 +258,7 @@ public class StubBuildingVisitor extends ClassVisitor { @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - return new AnnotationTextCollector(desc, new Consumer() { + return new AnnotationTextCollector(desc, myMapping, new Consumer() { @Override public void consume(String text) { new PsiAnnotationStubImpl(myModList, text); @@ -265,9 +271,8 @@ public class StubBuildingVisitor extends ClassVisitor { if ((access & Opcodes.ACC_SYNTHETIC) != 0) return; if (innerName == null || outerName == null) return; - if ((getClassName(outerName) + '.' + innerName).equals(myResult.getQualifiedName()) && myParent instanceof PsiFileStub) { - // our result is inner class - throw new OutOfOrderInnerClassException(); + if (myParent instanceof PsiFileStub && myInternalName.equals(name)) { + throw new OutOfOrderInnerClassException(); // our result is inner class } if (myInternalName.equals(outerName)) { @@ -286,35 +291,24 @@ public class StubBuildingVisitor extends ClassVisitor { byte flags = PsiFieldStubImpl.packFlags((access & Opcodes.ACC_ENUM) != 0, (access & Opcodes.ACC_DEPRECATED) != 0, false, false); TypeInfo type = fieldType(desc, signature); - String initializer = constToString(value, type.text, false); + String initializer = constToString(value, type.text, false, myMapping); PsiFieldStub stub = new PsiFieldStubImpl(myResult, name, type, initializer, flags); PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packFieldFlags(access)); - return new AnnotationCollectingVisitor(modList); + return new AnnotationCollectingVisitor(modList, myMapping); } - @NotNull - public static TypeInfo fieldType(String desc, String signature) { + private TypeInfo fieldType(String desc, String signature) { + String type = null; if (signature != null) { try { - return TypeInfo.fromString(SignatureParsing.parseTypeString(new StringCharacterIterator(signature, 0))); - } - catch (ClsFormatException e) { - return fieldTypeViaDescription(desc); + type = SignatureParsing.parseTypeString(new StringCharacterIterator(signature), myMapping); } + catch (ClsFormatException e) { LOG.warn(signature, e); } } - else { - return fieldTypeViaDescription(desc); + if (type == null) { + type = toJavaType(Type.getType(desc), myMapping); } - } - - @NotNull - private static TypeInfo fieldTypeViaDescription(@NotNull String desc) { - Type type = Type.getType(desc); - int dim = type.getSort() == Type.ARRAY ? type.getDimensions() : 0; - if (dim > 0) { - type = type.getElementType(); - } - return new TypeInfo(getTypeText(type), (byte)dim, false, PsiAnnotationStub.EMPTY_ARRAY); + return TypeInfo.fromString(type, false); } private static final String[] parameterNames = {"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9"}; @@ -327,50 +321,65 @@ public class StubBuildingVisitor extends ClassVisitor { // However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for in-trait implementation delegation. // See IDEA-78649 if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null; - + if (name == null) return null; if (SYNTHETIC_CLASS_INIT_METHOD.equals(name)) return null; // skip semi-synthetic enum methods boolean isEnum = myResult.isEnum(); if (isEnum) { if ("values".equals(name) && desc.startsWith("()")) return null; + //noinspection SpellCheckingInspection if ("valueOf".equals(name) && desc.startsWith("(Ljava/lang/String;)")) return null; } - boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0; boolean isConstructor = SYNTHETIC_INIT_METHOD.equals(name); + boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0; boolean isVarargs = (access & Opcodes.ACC_VARARGS) != 0; + boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; boolean isAnnotationMethod = myResult.isAnnotationType(); - if (!isConstructor && name == null) return null; - byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false, false); String canonicalMethodName = isConstructor ? myResult.getName() : name; - List args = new ArrayList(); - List throwables = exceptions != null ? new ArrayList() : null; - int modifiersMask = packMethodFlags(access, myResult.isInterface()); - PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, canonicalMethodName, flags, signature, args, throwables, desc, modifiersMask); - - PsiModifierListStub modList = (PsiModifierListStub)stub.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST); - assert modList != null : stub; - - if (isEnum && isConstructor && signature == null && args.size() >= 2 && JAVA_LANG_STRING.equals(args.get(0)) && "int".equals(args.get(1))) { - // exclude synthetic enum constructor parameters - args = args.subList(2, args.size()); + MethodInfo info = null; + boolean generic = false; + if (signature != null) { + try { + info = parseMethodSignature(signature, exceptions); + generic = true; + } + catch (ClsFormatException e) { LOG.warn(signature, e); } + } + if (info == null) { + info = parseMethodDescription(desc, exceptions); } - boolean isNonStaticInnerClassConstructor = - isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0; - boolean parsedViaGenericSignature = stub.isParsedViaGenericSignature(); - boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor; + PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, canonicalMethodName, TypeInfo.fromString(info.returnType, false), flags, null); + + PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packMethodFlags(access, myResult.isInterface())); + + PsiTypeParameterListStub list = new PsiTypeParameterListStubImpl(stub); + for (Pair parameter : info.typeParameters) { + PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(list, StringRef.fromString(parameter.first)); + newReferenceList(JavaStubElementTypes.EXTENDS_BOUND_LIST, parameterStub, parameter.second); + } + + boolean isEnumConstructor = isEnum && isConstructor; + boolean isInnerClassConstructor = isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0; + + List args = info.argTypes; + if (!generic && isEnumConstructor && args.size() >= 2 && JAVA_LANG_STRING.equals(args.get(0)) && "int".equals(args.get(1))) { + // omit synthetic enum constructor parameters + args = args.subList(2, args.size()); + } PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub); int paramCount = args.size(); PsiParameterStubImpl[] paramStubs = new PsiParameterStubImpl[paramCount]; for (int i = 0; i < paramCount; i++) { - if (shouldSkipFirstParamForNonStaticInnerClassConstructor && i == 0) continue; + // omit synthetic inner class constructor parameter + if (i == 0 && !generic && isInnerClassConstructor) continue; String arg = args.get(i); boolean isEllipsisParam = isVarargs && i == paramCount - 1; @@ -382,115 +391,121 @@ public class StubBuildingVisitor extends ClassVisitor { new PsiModifierListStubImpl(parameterStub, 0); } - String[] thrownTypes = buildThrowsList(exceptions, throwables, parsedViaGenericSignature); - newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, thrownTypes); + newReferenceList(JavaStubElementTypes.THROWS_LIST, stub, ArrayUtil.toStringArray(info.throwTypes)); - int localVarIgnoreCount = (access & Opcodes.ACC_STATIC) != 0 ? 0 : isConstructor && isEnum ? 3 : 1; - int paramIgnoreCount = isConstructor && isEnum ? 2 : isNonStaticInnerClassConstructor ? 1 : 0; - return new AnnotationParamCollectingVisitor(stub, modList, localVarIgnoreCount, paramIgnoreCount, paramCount, paramStubs); + int localVarIgnoreCount = isStatic ? 0 : isEnumConstructor ? 3 : 1; + int paramIgnoreCount = isEnumConstructor ? 2 : isInnerClassConstructor ? 1 : 0; + return new AnnotationParamCollectingVisitor(stub, modList, localVarIgnoreCount, paramIgnoreCount, paramCount, paramStubs, myMapping); } - private static String[] buildThrowsList(String[] exceptions, List throwables, boolean parsedViaGenericSignature) { - if (exceptions == null) return ArrayUtil.EMPTY_STRING_ARRAY; + private MethodInfo parseMethodSignature(String signature, String[] exceptions) throws ClsFormatException { + MethodInfo result = new MethodInfo(); + CharacterIterator iterator = new StringCharacterIterator(signature); - if (parsedViaGenericSignature && throwables != null && exceptions.length > throwables.size()) { - // There seem to be an inconsistency (or bug) in class format. For instance, java.lang.Class.forName() method has - // signature equal to "(Ljava/lang/String;)Ljava/lang/Class<*>;" (i.e. no exceptions thrown) but exceptions actually not empty, - // method throws ClassNotFoundException - parsedViaGenericSignature = false; - } + result.typeParameters = SignatureParsing.parseTypeParametersDeclaration(iterator, myMapping); - if (parsedViaGenericSignature && throwables != null) { - return ArrayUtil.toStringArray(throwables); + if (iterator.current() != '(') throw new ClsFormatException(); + iterator.next(); + if (iterator.current() == ')') { + result.argTypes = ContainerUtil.emptyList(); } else { - String[] converted = ArrayUtil.newStringArray(exceptions.length); - for (int i = 0; i < converted.length; i++) { - converted[i] = getClassName(exceptions[i]); + result.argTypes = ContainerUtil.newSmartList(); + while (iterator.current() != ')' && iterator.current() != CharacterIterator.DONE) { + result.argTypes.add(SignatureParsing.parseTypeString(iterator, myMapping)); } - return converted; - } - } - - @NotNull - public static String parseMethodViaDescription(@NotNull String desc, @NotNull PsiMethodStubImpl stub, @NotNull List args) { - String returnType = getTypeText(Type.getReturnType(desc)); - Type[] argTypes = Type.getArgumentTypes(desc); - for (Type argType : argTypes) { - args.add(getTypeText(argType)); - } - new PsiTypeParameterListStubImpl(stub); - return returnType; - } - - @NotNull - public static String parseMethodViaGenericSignature(@NotNull String signature, - @NotNull PsiMethodStubImpl stub, - @NotNull List args, - @Nullable List throwables) throws ClsFormatException { - StringCharacterIterator iterator = new StringCharacterIterator(signature); - SignatureParsing.parseTypeParametersDeclaration(iterator, stub); - - if (iterator.current() != '(') { - throw new ClsFormatException(); + if (iterator.current() != ')') throw new ClsFormatException(); } iterator.next(); - while (iterator.current() != ')' && iterator.current() != CharacterIterator.DONE) { - args.add(SignatureParsing.parseTypeString(iterator)); - } - - if (iterator.current() != ')') { - throw new ClsFormatException(); - } - iterator.next(); - - String returnType = SignatureParsing.parseTypeString(iterator); + result.returnType = SignatureParsing.parseTypeString(iterator, myMapping); + result.throwTypes = null; while (iterator.current() == '^') { iterator.next(); - String exType = SignatureParsing.parseTypeString(iterator); - if (throwables != null) { - throwables.add(exType); - } + if (result.throwTypes == null) result.throwTypes = ContainerUtil.newSmartList(); + result.throwTypes.add(SignatureParsing.parseTypeString(iterator, myMapping)); + } + if (exceptions != null && (result.throwTypes == null || exceptions.length > result.throwTypes.size())) { + // a signature may be inconsistent with exception list - in this case, the more complete list takes precedence + result.throwTypes = ContainerUtil.map(exceptions, new Function() { + @Override + public String fun(String name) { + return myMapping.fun(name); + } + }); } - return returnType; + return result; } + private MethodInfo parseMethodDescription(String desc, String[] exceptions) { + MethodInfo result = new MethodInfo(); + result.typeParameters = ContainerUtil.emptyList(); + result.returnType = toJavaType(Type.getReturnType(desc), myMapping); + result.argTypes = ContainerUtil.map(Type.getArgumentTypes(desc), new Function() { + @Override + public String fun(Type type) { + return toJavaType(type, myMapping); + } + }); + result.throwTypes = exceptions == null ? null : ContainerUtil.map(exceptions, new Function() { + @Override + public String fun(String name) { + return myMapping.fun(name); + } + }); + return result; + } + + + private static class ClassInfo { + private List> typeParameters; + private String superName; + private List interfaceNames; + } + + private static class MethodInfo { + private List> typeParameters; + private String returnType; + private List argTypes; + private List throwTypes; + } private static class AnnotationTextCollector extends AnnotationVisitor { private final StringBuilder myBuilder = new StringBuilder(); + private final Function myMapping; private final Consumer myCallback; + private boolean hasPrefix = false; private boolean hasParams = false; - private final String myDesc; - public AnnotationTextCollector(@Nullable String desc, Consumer callback) { + public AnnotationTextCollector(@Nullable String desc, Function mapping, Consumer callback) { super(ASM_API); + myMapping = mapping; myCallback = callback; - myDesc = desc; if (desc != null) { - myBuilder.append('@').append(getTypeText(Type.getType(desc))); + hasPrefix = true; + myBuilder.append('@').append(toJavaType(Type.getType(desc), myMapping)); } } @Override public void visit(String name, Object value) { valuePairPrefix(name); - myBuilder.append(constToString(value, null, true)); + myBuilder.append(constToString(value, null, true, myMapping)); } @Override public void visitEnum(String name, String desc, String value) { valuePairPrefix(name); - myBuilder.append(getTypeText(Type.getType(desc))).append('.').append(value); + myBuilder.append(toJavaType(Type.getType(desc), myMapping)).append('.').append(value); } private void valuePairPrefix(String name) { if (!hasParams) { hasParams = true; - if (myDesc != null) { + if (hasPrefix) { myBuilder.append('('); } } @@ -506,7 +521,7 @@ public class StubBuildingVisitor extends ClassVisitor { @Override public AnnotationVisitor visitAnnotation(String name, String desc) { valuePairPrefix(name); - return new AnnotationTextCollector(desc, new Consumer() { + return new AnnotationTextCollector(desc, myMapping, new Consumer() { @Override public void consume(String text) { myBuilder.append(text); @@ -518,7 +533,7 @@ public class StubBuildingVisitor extends ClassVisitor { public AnnotationVisitor visitArray(String name) { valuePairPrefix(name); myBuilder.append('{'); - return new AnnotationTextCollector(null, new Consumer() { + return new AnnotationTextCollector(null, myMapping, new Consumer() { @Override public void consume(String text) { myBuilder.append(text).append('}'); @@ -528,7 +543,7 @@ public class StubBuildingVisitor extends ClassVisitor { @Override public void visitEnd() { - if (hasParams && myDesc != null) { + if (hasPrefix && hasParams) { myBuilder.append(')'); } myCallback.consume(myBuilder.toString()); @@ -537,15 +552,17 @@ public class StubBuildingVisitor extends ClassVisitor { private static class AnnotationCollectingVisitor extends FieldVisitor { private final PsiModifierListStub myModList; + private final Function myMapping; - private AnnotationCollectingVisitor(PsiModifierListStub modList) { + private AnnotationCollectingVisitor(PsiModifierListStub modList, Function mapping) { super(ASM_API); myModList = modList; + myMapping = mapping; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - return new AnnotationTextCollector(desc, new Consumer() { + return new AnnotationTextCollector(desc, myMapping, new Consumer() { @Override public void consume(String text) { new PsiAnnotationStubImpl(myModList, text); @@ -561,15 +578,17 @@ public class StubBuildingVisitor extends ClassVisitor { private final int myParamIgnoreCount; private final int myParamCount; private final PsiParameterStubImpl[] myParamStubs; + private final Function myMapping; private int myUsedParamSize = 0; private int myUsedParamCount = 0; - private AnnotationParamCollectingVisitor(@NotNull PsiMethodStub owner, - @NotNull PsiModifierListStub modList, + private AnnotationParamCollectingVisitor(PsiMethodStub owner, + PsiModifierListStub modList, int ignoreCount, int paramIgnoreCount, int paramCount, - @NotNull PsiParameterStubImpl[] paramStubs) { + PsiParameterStubImpl[] paramStubs, + Function mapping) { super(ASM_API); myOwner = owner; myModList = modList; @@ -577,11 +596,12 @@ public class StubBuildingVisitor extends ClassVisitor { myParamIgnoreCount = paramIgnoreCount; myParamCount = paramCount; myParamStubs = paramStubs; + myMapping = mapping; } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - return new AnnotationTextCollector(desc, new Consumer() { + return new AnnotationTextCollector(desc, myMapping, new Consumer() { @Override public void consume(String text) { new PsiAnnotationStubImpl(myModList, text); @@ -591,7 +611,7 @@ public class StubBuildingVisitor extends ClassVisitor { @Override public AnnotationVisitor visitAnnotationDefault() { - return new AnnotationTextCollector(null, new Consumer() { + return new AnnotationTextCollector(null, myMapping, new Consumer() { @Override public void consume(String text) { ((PsiMethodStubImpl)myOwner).setDefaultValueText(text); @@ -614,22 +634,14 @@ public class StubBuildingVisitor extends ClassVisitor { } myUsedParamCount = paramIndex + 1; - if ("D".equals(desc) || "J".equals(desc)) { - myUsedParamSize += 2; - } - else { - myUsedParamSize++; - } + myUsedParamSize += "D".equals(desc) || "J".equals(desc) ? 2 : 1; } } @Override @Nullable public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) { - if (parameter < myParamIgnoreCount) { - return null; - } - return new AnnotationTextCollector(desc, new Consumer() { + return parameter < myParamIgnoreCount ? null : new AnnotationTextCollector(desc, myMapping, new Consumer() { @Override public void consume(String text) { new PsiAnnotationStubImpl(myOwner.findParameter(parameter - myParamIgnoreCount).getModList(), text); @@ -639,7 +651,7 @@ public class StubBuildingVisitor extends ClassVisitor { } @Nullable - private static String constToString(@Nullable Object value, @Nullable String type, boolean anno) { + private static String constToString(@Nullable Object value, @Nullable String type, boolean anno, Function mapping) { if (value == null) return null; if (value instanceof String) { @@ -700,31 +712,98 @@ public class StubBuildingVisitor extends ClassVisitor { buffer.append('{'); for (int i = 0, length = Array.getLength(value); i < length; i++) { if (i > 0) buffer.append(", "); - buffer.append(constToString(Array.get(value, i), type, anno)); + buffer.append(constToString(Array.get(value, i), type, anno, mapping)); } buffer.append('}'); return buffer.toString(); } if (anno && value instanceof Type) { - return getTypeText((Type)value) + ".class"; + return toJavaType(((Type)value), mapping) + ".class"; } return null; } - private static String getClassName(String name) { - return getTypeText(Type.getObjectType(name)); + private static String toJavaType(Type type, Function mapping) { + int dimensions = 0; + if (type.getSort() == Type.ARRAY) { + dimensions = type.getDimensions(); + type = type.getElementType(); + } + String text = type.getSort() == Type.OBJECT ? mapping.fun(type.getInternalName()) : type.getClassName(); + if (dimensions > 0) text += StringUtil.repeat("[]", dimensions); + return text; } - @NotNull - private static String getTypeText(@NotNull Type type) { - String raw = type.getClassName(); - // As the '$' char is a valid java identifier and is actively used by byte code generators, the problem is - // which occurrences of this char should be replaced and which should not. - // Heuristic: replace only those $ occurrences that are surrounded non-"$" chars - // (most likely generated by javac to separate inner or anonymous class name) - // Leading and trailing $ chars should be left unchanged. - return raw.indexOf('$') >= 0 ? REGEX_PATTERN.matcher(raw).replaceAll("\\.") : raw; + private static Map> loadMapping(Object classSource) { + if (MAP_INNER_CLASSES_BY_TABLE && classSource instanceof VirtualFile) { + try { + final Map> mapping = ContainerUtil.newHashMap(); + + byte[] bytes = ((VirtualFile)classSource).contentsToByteArray(false); + new ClassReader(bytes).accept(new ClassVisitor(ASM_API) { + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + if (outerName != null && innerName != null) { + mapping.put(name, pair(outerName, innerName)); + } + } + }, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); + + if (!mapping.isEmpty()) { + return mapping; + } + } + catch (Exception ignored) { } + } + + return null; } + + private static Function createMapping(final Map> mapping) { + return new Function() { + @Override + public String fun(String internalName) { + String className = internalName; + + if (className.indexOf('$') >= 0) { + Pair p = mapping.get(className); + if (p != null) { + className = p.first; + if (p.second != null) { + className = fun(p.first) + '.' + p.second; + mapping.put(className, pair(className, (String)null)); + } + } + } + + return className.replace('/', '.'); + } + }; + } + + public static final Function GUESSING_MAPPER = new Function() { + @Override + public String fun(String internalName) { + String canonicalText = internalName; + + if (canonicalText.indexOf('$') >= 0) { + StringBuilder sb = new StringBuilder(canonicalText); + boolean updated = false; + for (int p = 0; p < sb.length(); p++) { + char c = sb.charAt(p); + if (c == '$' && p > 0 && sb.charAt(p - 1) != '/' && p < sb.length() - 1 && sb.charAt(p + 1) != '$') { + sb.setCharAt(p, '.'); + updated = true; + } + } + if (updated) { + canonicalText = sb.toString(); + } + } + + return canonicalText.replace('/', '.'); + } + }; } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java index 2b9f44090593..5aa36a6b9580 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java @@ -17,7 +17,6 @@ package com.intellij.psi.impl.java.stubs.impl; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.cache.TypeInfo; -import com.intellij.psi.impl.compiled.StubBuildingVisitor; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiMethodStub; import com.intellij.psi.impl.java.stubs.PsiParameterListStub; @@ -25,7 +24,6 @@ import com.intellij.psi.impl.java.stubs.PsiParameterStub; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; import com.intellij.util.BitUtil; -import com.intellij.util.cls.ClsFormatException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,39 +43,7 @@ public class PsiMethodStubImpl extends StubBase implements PsiMethodS private static final int ANNOTATION = 0x04; private static final int DEPRECATED = 0x08; private static final int DEPRECATED_ANNOTATION = 0x10; - private static final int PARSED_VIA_GENERIC_SIGNATURE = 0x20; - private static final int HAS_DOC_COMMENT = 0x40; - - public PsiMethodStubImpl(StubElement parent, - String name, - byte flags, - String signature, - @NotNull List args, - @Nullable List throwables, - String desc, - int modifiersMask) { - super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD); - myName = name; - myDefaultValueText = null; - - new PsiModifierListStubImpl(this, modifiersMask); - - String returnType = null; - boolean parsedViaGenericSignature = false; - if (signature != null) { - try { - returnType = StubBuildingVisitor.parseMethodViaGenericSignature(signature, this, args, throwables); - parsedViaGenericSignature = true; - } - catch (ClsFormatException ignored) { } - } - if (returnType == null) { - returnType = StubBuildingVisitor.parseMethodViaDescription(desc, this, args); - } - - myReturnType = TypeInfo.fromString(returnType); - myFlags = (byte)(flags | (parsedViaGenericSignature ? PARSED_VIA_GENERIC_SIGNATURE : 0)); - } + private static final int HAS_DOC_COMMENT = 0x20; public PsiMethodStubImpl(StubElement parent, String name, @NotNull TypeInfo returnType, byte flags, @Nullable String defaultValueText) { super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD); @@ -97,10 +63,6 @@ public class PsiMethodStubImpl extends StubBase implements PsiMethodS return BitUtil.isSet(myFlags, VARARGS); } - public boolean isParsedViaGenericSignature() { - return BitUtil.isSet(myFlags, PARSED_VIA_GENERIC_SIGNATURE); - } - @Override public boolean isAnnotationMethod() { return isAnnotationMethod(myFlags); diff --git a/java/java-tests/testSrc/com/intellij/psi/SignatureParsingTest.java b/java/java-tests/testSrc/com/intellij/psi/SignatureParsingTest.java index 93ecdd6436b0..71f59f04e2ed 100644 --- a/java/java-tests/testSrc/com/intellij/psi/SignatureParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/SignatureParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -16,6 +16,7 @@ package com.intellij.psi; import com.intellij.psi.impl.compiled.SignatureParsing; +import com.intellij.psi.impl.compiled.StubBuildingVisitor; import com.intellij.util.cls.ClsFormatException; import org.junit.Test; @@ -29,8 +30,18 @@ import static org.junit.Assert.assertEquals; public class SignatureParsingTest { @Test public void testVarianceAmbiguity() throws ClsFormatException { - assertEquals("Psi", SignatureParsing.parseTypeString(new StringCharacterIterator("LPsi<*TP>;"))); - assertEquals("Psi", SignatureParsing.parseTypeString(new StringCharacterIterator("LPsi<+TP>;"))); - assertEquals("Psi", SignatureParsing.parseTypeString(new StringCharacterIterator("LPsi<-TP>;"))); + parseTypeString("Psi", "LPsi<*TP>;"); + parseTypeString("Psi", "LPsi<+TP>;"); + parseTypeString("Psi", "LPsi<-TP>;"); } -} + + @Test + public void testMapping() throws ClsFormatException { + parseTypeString("p.Obj.I", "Lp/Obj$I;"); + parseTypeString("p.Obj$.I", "Lp/Obj$$I;"); + } + + private static void parseTypeString(String expected, String signature) throws ClsFormatException { + assertEquals(expected, SignatureParsing.parseTypeString(new StringCharacterIterator(signature), StubBuildingVisitor.GUESSING_MAPPER)); + } +} \ No newline at end of file diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index dd451323226d..1d09e4d18c56 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -302,6 +302,11 @@ java.max.package.name.length.description=An upper length limit on string that th java.correct.class.type.by.place.resolve.scope=true java.correct.class.type.by.place.resolve.scope.description=When resolving Java references, use the resolve scope of the currently processed source file +java.lib.inner.class.detection.by.table=false +java.lib.inner.class.detection.by.table.description=When 'true', IDEA will use "InnerClasses" .class file attribute to resolve \ + binary names (like "Map$Entry") into a source form ("Map.Entry"). Some compilers though do not populate this table correctly. \ + Cache invalidation needed when changing this value. + documentation.component.editor.font=false ide.completion.show.better.matching.classes=true diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java index e48a87c9c172..c269e7de8a01 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -20,8 +20,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.impl.cache.TypeInfo; +import com.intellij.psi.impl.compiled.SignatureParsing; import com.intellij.psi.impl.compiled.StubBuildingVisitor; +import com.intellij.util.cls.ClsFormatException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.*; import com.intellij.util.indexing.FileBasedIndex.InputFilter; @@ -32,10 +33,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.FieldVisitor; +import org.jetbrains.org.objectweb.asm.Type; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.text.StringCharacterIterator; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -123,8 +126,8 @@ public class GroovyTraitFieldsFileIndex private static Map> mapInner(@NotNull FileContent inputData) { final int key = FileBasedIndex.getFileId(inputData.getFile()); final Map> result = ContainerUtil.newHashMap(); - new ClassReader(inputData.getContent()).accept(new ClassVisitor(ASM5) { + new ClassReader(inputData.getContent()).accept(new ClassVisitor(ASM5) { @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { processField(access, name, desc, signature); @@ -133,6 +136,7 @@ public class GroovyTraitFieldsFileIndex private void processField(int access, String name, String desc, String signature) { if ((access & ACC_SYNTHETIC) == 0) return; + final boolean isStatic; final boolean isPublic; Pair p; @@ -151,7 +155,7 @@ public class GroovyTraitFieldsFileIndex return; } - final String typeString = TypeInfo.createTypeText(StubBuildingVisitor.fieldType(desc, signature)); + final String typeString = fieldType(desc, signature); if (typeString == null) return; final int delimiter = name.indexOf(DELIMITER); @@ -178,7 +182,20 @@ public class GroovyTraitFieldsFileIndex return Pair.create(null, input); } } - }, ClassReader.SKIP_FRAMES); + + private String fieldType(String desc, String signature) { + if (signature != null) { + try { + return SignatureParsing.parseTypeString(new StringCharacterIterator(signature), StubBuildingVisitor.GUESSING_MAPPER); + } + catch (ClsFormatException ignored) { } + } + + String raw = Type.getType(desc).getClassName(); + return StubBuildingVisitor.GUESSING_MAPPER.fun(raw); + } + }, ClassReader.SKIP_CODE); + return result; } From ad5d26fc8e1e198eac8551a5d913d329c83501ef Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Thu, 14 Jan 2016 14:16:14 +0300 Subject: [PATCH 074/825] Test fix --- .../intellij/designer/DesignerToolWindowManager.java | 11 ++++++++--- .../designer/palette/PaletteToolWindowManager.java | 10 ++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java index a35be4d28697..5ebc2a4c94ef 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java @@ -33,7 +33,7 @@ import org.jetbrains.annotations.Nullable; * @author Alexander Lobas */ public final class DesignerToolWindowManager extends AbstractToolWindowManager { - private final DesignerToolWindow myToolWindowContent; + private DesignerToolWindow myToolWindowContent; ////////////////////////////////////////////////////////////////////////////////////////// // @@ -43,7 +43,6 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { public DesignerToolWindowManager(Project project, FileEditorManager fileEditorManager) { super(project, fileEditorManager); - myToolWindowContent = new DesignerToolWindow(project, true); } public static DesignerToolWindow getInstance(DesignerEditorPanel designer) { @@ -67,6 +66,10 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { @Override protected void initToolWindow() { + if (myToolWindowContent == null) { + myToolWindowContent = new DesignerToolWindow(myProject, true); + } + myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(DesignerBundle.message("designer.toolwindow.name"), false, getAnchor(), myProject, true); myToolWindow.setIcon(UIDesignerNewIcons.ToolWindow); @@ -110,7 +113,9 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { @Override public void disposeComponent() { - myToolWindowContent.dispose(); + if (myToolWindowContent != null) { + myToolWindowContent.dispose(); + } } @NotNull diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java index 3fddf66eaad6..fa30fcbff759 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java @@ -34,7 +34,7 @@ import org.jetbrains.annotations.Nullable; * @author Alexander Lobas */ public class PaletteToolWindowManager extends AbstractToolWindowManager { - private final PalettePanel myToolWindowPanel = new PalettePanel(); + private PalettePanel myToolWindowPanel; ////////////////////////////////////////////////////////////////////////////////////////// // @@ -66,6 +66,10 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager { @Override protected void initToolWindow() { + if (myToolWindowPanel == null) { + myToolWindowPanel = new PalettePanel(); + } + myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow("Palette\t", false, getAnchor(), myProject, true); myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette); initGearActions(); @@ -100,7 +104,9 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager { @Override public void disposeComponent() { - myToolWindowPanel.dispose(); + if (myToolWindowPanel != null) { + myToolWindowPanel.dispose(); + } } @NotNull From 5b730b20f9243daae2b503c4ffc648cb26d30e56 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 14 Jan 2016 14:38:48 +0300 Subject: [PATCH 075/825] diff: compare file paths, not their presentations shouldn't affect anything, but presentableUrl can change one day --- .../diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java index 91c1c2b7958e..20f632eabf84 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffRequestFactoryImpl.java @@ -129,7 +129,7 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory { @NotNull public static String getTitle(@NotNull FilePath path1, @NotNull FilePath path2, @NotNull String separator) { - if ((path1.isDirectory() || path2.isDirectory()) && path1.getPresentableUrl().equals(path2.getPresentableUrl())) { + if ((path1.isDirectory() || path2.isDirectory()) && path1.getPath().equals(path2.getPath())) { return path1.getPresentableUrl(); } From 20ba3cc3756c5eb8e2e0f56379a0740b05e2d686 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Thu, 14 Jan 2016 14:47:13 +0300 Subject: [PATCH 076/825] artifacts with custom linux jdk for PyCharm (PY and PC). --- python/build/pycharm_community_build.gant | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index d5d6f2a84f61..9baaff86e553 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -180,6 +180,9 @@ public layoutCommunity(String classesPath, Set usedJars) { if (p("jdk.linux") != "false") { buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildName}.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.linux"], ["jre/jre/bin/*"]) } + if (p("jdk.custom.linux") != "false") { + buildTarGz(tarRoot, "$paths.artifacts/pycharmPC${buildName}-custom-jdk-linux.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.custom.linux"], ["jre/jre/bin/*"]) + } String macAppRoot = isEap() ? "PyCharm CE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm CE.app/Contents" buildMacZip(macAppRoot, "${paths.artifacts}/pycharmPC-${buildNumber}.mac.zip", [paths.distAll], paths.distMac) From 48139e0d54bbeafa8890e3596806b0c46ccccd05 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 14 Jan 2016 14:57:48 +0300 Subject: [PATCH 077/825] logging for EA-77200 --- .../intellij/debugger/engine/PositionManagerImpl.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 3c0ed6780f10..2b46e1ac1ff4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -41,6 +41,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.DocumentUtil; import com.intellij.util.Function; +import com.intellij.util.PairProcessor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.EmptyIterable; import com.sun.jdi.AbsentInformationException; @@ -432,7 +433,15 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio } } else { - LOG.error("Local or anonymous class has no non-local parent"); + final StringBuilder sb = new StringBuilder(); + PsiTreeUtil.treeWalkUp(psiClass, null, new PairProcessor() { + @Override + public boolean process(PsiElement element, PsiElement element2) { + sb.append(element); + return true; + } + }); + LOG.error("Local or anonymous class " + psiClass + " has no non-local parent, parents:" + sb); } } else { From 1df6a01247b9d351d0cb16dc7084097e811bc99f Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 14 Jan 2016 12:58:32 +0100 Subject: [PATCH 078/825] Revert: both capturing process classes to listen to the progress manager and be cancellable --- .../process/CapturingProcessHandler.java | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java index 13331d11520f..d37946444b95 100644 --- a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java @@ -18,9 +18,7 @@ package com.intellij.execution.process; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -67,34 +65,15 @@ public class CapturingProcessHandler extends OSProcessHandler { public ProcessOutput runProcess() { startNotify(); - if (waitForProcessListeningProgress(this)) { + if (waitFor()) { myOutput.setExitCode(getProcess().exitValue()); } else { LOG.info("runProcess: exit value unavailable"); } - return myOutput; } - public static boolean waitForProcessListeningProgress(ProcessHandler handler) { - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - while (!handler.waitFor(300)) { - if (indicator.isCanceled()) { - handler.destroyProcess(); - throw new ProcessCanceledException(); - } - } - } else { - if (!handler.waitFor()) { - LOG.info("runProcess: exit value unavailable"); - return false; - } - } - return true; - } - /** * Starts process with specified timeout * From a7cb6d8fe52891aa2db902654289bbbdf944eb4f Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 14 Jan 2016 15:30:43 +0300 Subject: [PATCH 079/825] unable to start with empty config (IDEA-CR-7815) --- platform/platform-api/src/com/intellij/util/ui/Animator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/Animator.java b/platform/platform-api/src/com/intellij/util/ui/Animator.java index f23281871aff..99ce196f9631 100644 --- a/platform/platform-api/src/com/intellij/util/ui/Animator.java +++ b/platform/platform-api/src/com/intellij/util/ui/Animator.java @@ -106,7 +106,9 @@ public abstract class Animator implements Disposable { } private void animationDone() { - ApplicationManager.getApplication().assertIsDispatchThread(); + // NOT ApplicationManager.getApplication().assertIsDispatchThread() as Application may not be available when e.g. importing settings + assert SwingUtilities.isEventDispatchThread(); + stopTicker(); paintCycleEnd(); } From acc79a84209b248b90daff225426119bcb99202c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 13:45:28 +0100 Subject: [PATCH 080/825] [groovy] correct detection of trait field helper file --- .../typedef/GrTypeDefinitionMembersCache.java | 13 +++++++------ .../lang/resolve/GroovyTraitFieldsFileIndex.java | 5 ++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java index c21a4adf0fde..9030f80ad513 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java @@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitField; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod; import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; +import org.jetbrains.plugins.groovy.lang.resolve.GroovyTraitFieldsFileIndex; import org.jetbrains.plugins.groovy.lang.resolve.GroovyTraitFieldsFileIndex.TraitFieldDescriptor; import org.jetbrains.plugins.groovy.lang.resolve.ast.AstTransformContributor; @@ -308,6 +309,7 @@ public class GrTypeDefinitionMembersCache { LOG.assertTrue(trait != null); List traitFields = new TraitProcessor(trait, resolveResult.getSubstitutor()) { + @Override protected void processTrait(@NotNull final PsiClass trait, @NotNull final PsiSubstitutor substitutor) { if (trait instanceof GrTypeDefinition) { for (GrField field : ((GrTypeDefinition)trait).getCodeFields()) { @@ -315,15 +317,14 @@ public class GrTypeDefinitionMembersCache { } } else if (trait instanceof ClsClassImpl) { - final PsiClass traitFieldHelper = JavaPsiFacade.getInstance(trait.getProject()).findClass( - trait.getQualifiedName() + "$Trait$FieldHelper", trait.getResolveScope() - ); - if (traitFieldHelper == null) return; + final VirtualFile traitFile = trait.getContainingFile().getVirtualFile(); + if (traitFile == null) return; + final VirtualFile helperFile = traitFile.getParent().findChild(trait.getName() + GroovyTraitFieldsFileIndex.HELPER_SUFFIX); + if (helperFile == null) return; - final VirtualFile virtualFile = traitFieldHelper.getContainingFile().getVirtualFile(); final List> descriptors = FileBasedIndex.getInstance().getValues( INDEX_ID, - FileBasedIndex.getFileId(virtualFile), + FileBasedIndex.getFileId(helperFile), trait.getResolveScope() ); for (Collection traitFieldDescriptors : descriptors) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java index c269e7de8a01..568b1cf9dd71 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitFieldsFileIndex.java @@ -56,10 +56,13 @@ public class GroovyTraitFieldsFileIndex DataExternalizer> { public static final ID> INDEX_ID = ID.create("groovy.trait.fields"); + + public static final String HELPER_SUFFIX = "$Trait$FieldHelper.class"; + public static final InputFilter INPUT_FILTER = new DefaultFileTypeSpecificInputFilter(JavaClassFileType.INSTANCE) { @Override public boolean acceptInput(@NotNull VirtualFile file) { - return StringUtil.endsWith(file.getNameSequence(), "$Trait$FieldHelper.class"); + return StringUtil.endsWith(file.getNameSequence(), HELPER_SUFFIX); } }; From 8b13206ac23f73e86441aff34cbd16360965ddc0 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Wed, 13 Jan 2016 14:34:45 +0300 Subject: [PATCH 081/825] optimize imports --- .../com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index 0f45a543a43b..a8c0082f9d99 100644 --- a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -6,7 +6,6 @@ import com.intellij.facet.ui.ValidationResult; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.FileTemplateUtil; -import com.intellij.ide.util.DirectoryUtil; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; @@ -16,7 +15,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; -import com.jetbrains.edu.EduNames; import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.coursecreator.actions.CCCreateLesson; import com.jetbrains.edu.coursecreator.actions.CCCreateTask; @@ -53,7 +51,6 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire return CourseCreatorPythonIcons.CourseCreationProjectType; } - @Override public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, @Nullable Object settings, @NotNull Module module) { @@ -64,7 +61,6 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, @NotNull final String name, @NotNull final String[] authors, @NotNull final String description) { - final CCProjectService service = CCProjectService.getInstance(project); final Course course = new Course(); course.setName(name); From 0f52c9c13cd01f256e6eb7cfc4cc24438b022fd1 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Thu, 14 Jan 2016 16:38:21 +0300 Subject: [PATCH 082/825] corrected pycharm PC artifact name. --- python/build/pycharm_community_build.gant | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index 9baaff86e553..9241b5cd2a4c 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -178,10 +178,10 @@ public layoutCommunity(String classesPath, Set usedJars) { String tarRoot = isEap() ? "pycharm-community-$buildNumber" : "pycharm-community-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildNumber}-no-jdk.tar", [paths.distAll, paths.distUnix]) if (p("jdk.linux") != "false") { - buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildName}.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.linux"], ["jre/jre/bin/*"]) + buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildNumber}.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.linux"], ["jre/jre/bin/*"]) } if (p("jdk.custom.linux") != "false") { - buildTarGz(tarRoot, "$paths.artifacts/pycharmPC${buildName}-custom-jdk-linux.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.custom.linux"], ["jre/jre/bin/*"]) + buildTarGz(tarRoot, "$paths.artifacts/pycharmPC-${buildNumber}-custom-jdk-linux.tar", [paths.distAll, paths.distUnix, "${home}/out/pycharm/jdk.custom.linux"], ["jre/jre/bin/*"]) } String macAppRoot = isEap() ? "PyCharm CE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm CE.app/Contents" From ef6711a76073642a4ef5c84ade85837f2a337170 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 15:06:05 +0100 Subject: [PATCH 083/825] [java] inner class detection: optimization --- .../com/intellij/psi/ClassFileViewProvider.java | 14 +++++--------- .../intellij/psi/impl/compiled/ClsFileImpl.java | 7 +++++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java index abd8fbe389d6..449aa574a47d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java +++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java @@ -31,6 +31,8 @@ import com.intellij.psi.impl.file.PsiBinaryFileImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.org.objectweb.asm.*; +import static com.intellij.psi.impl.compiled.ClsFileImpl.EMPTY_ATTRIBUTES; + /** * @author max */ @@ -60,7 +62,8 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { public static boolean isInnerClass(@NotNull VirtualFile file) { String name = file.getNameWithoutExtension(); - return name.indexOf('$') >= 0 && detectInnerClass(file); + int p = name.lastIndexOf('$', name.length() - 2); + return p > 0 && detectInnerClass(file); } private static boolean detectInnerClass(VirtualFile file) { @@ -75,22 +78,15 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { @Override public void visitOuterClass(String owner, String name, String desc) { ref.set(Boolean.TRUE); - throw new ProcessCanceledException(); } @Override public void visitInnerClass(String name, String outer, String inner, int access) { if (className.equals(name)) { ref.set(Boolean.TRUE); - throw new ProcessCanceledException(); } } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - throw new ProcessCanceledException(); - } - }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + }, EMPTY_ATTRIBUTES, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); } catch (ProcessCanceledException ignored) { } catch (Exception e) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index a563e8107b56..431d1611e5da 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -69,6 +69,7 @@ import com.intellij.util.cls.ClsFormatException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.org.objectweb.asm.Attribute; import org.jetbrains.org.objectweb.asm.ClassReader; import java.io.IOException; @@ -595,7 +596,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement try { StubBuildingVisitor visitor = new StubBuildingVisitor(file, STRATEGY, stub, 0, className); - reader.accept(visitor, ClassReader.SKIP_FRAMES); + reader.accept(visitor, EMPTY_ATTRIBUTES, ClassReader.SKIP_FRAMES); PsiClassStub result = visitor.getResult(); if (result == null) return null; } @@ -629,9 +630,11 @@ public class ClsFileImpl extends ClsRepositoryPsiElement public void accept(VirtualFile innerClass, StubBuildingVisitor visitor) { try { byte[] bytes = innerClass.contentsToByteArray(false); - new ClassReader(bytes).accept(visitor, ClassReader.SKIP_FRAMES); + new ClassReader(bytes).accept(visitor, EMPTY_ATTRIBUTES, ClassReader.SKIP_FRAMES); } catch (IOException ignored) { } } }; + + public static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; } \ No newline at end of file From 1e2e2f77d3e8e6638f6caaf2cce00d7af23e6922 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 15:08:09 +0100 Subject: [PATCH 084/825] Cleanup (forgotten catch) --- .../src/com/intellij/psi/ClassFileViewProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java index 449aa574a47d..72017210db58 100644 --- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java +++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java @@ -88,7 +88,6 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { } }, EMPTY_ATTRIBUTES, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); } - catch (ProcessCanceledException ignored) { } catch (Exception e) { Logger.getInstance(ClassFileViewProvider.class).warn(file.getPath(), e); } From 05253be08ad59320942551733db14d2fe12c637f Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Thu, 14 Jan 2016 17:46:28 +0300 Subject: [PATCH 085/825] PY-18203 Redundant parentheses quick fix produces syntactically incorrect code for tuples If parentheses expression contains binary expression where left and right are parentheses expressions too, we check if left and right contain tuples --- .../inspections/quickfix/RedundantParenthesesQuickFix.java | 3 ++- python/testData/inspections/RedundantParenthesesInTuples.py | 1 + .../inspections/RedundantParenthesesInTuples_after.py | 1 + python/testSrc/com/jetbrains/python/PyQuickFixTest.java | 5 +++++ 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 python/testData/inspections/RedundantParenthesesInTuples.py create mode 100644 python/testData/inspections/RedundantParenthesesInTuples_after.py diff --git a/python/src/com/jetbrains/python/inspections/quickfix/RedundantParenthesesQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/RedundantParenthesesQuickFix.java index 7224cccbf4d9..3c4343420c54 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/RedundantParenthesesQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/RedundantParenthesesQuickFix.java @@ -72,7 +72,8 @@ public class RedundantParenthesesQuickFix implements LocalQuickFix { right instanceof PyParenthesizedExpression) { PyExpression leftContained = ((PyParenthesizedExpression)left).getContainedExpression(); PyExpression rightContained = ((PyParenthesizedExpression)right).getContainedExpression(); - if (leftContained != null && rightContained != null) { + if (leftContained != null && rightContained != null && + !(leftContained instanceof PyTupleExpression) && !(rightContained instanceof PyTupleExpression)) { left.replace(leftContained); right.replace(rightContained); return true; diff --git a/python/testData/inspections/RedundantParenthesesInTuples.py b/python/testData/inspections/RedundantParenthesesInTuples.py new file mode 100644 index 000000000000..668372db89b9 --- /dev/null +++ b/python/testData/inspections/RedundantParenthesesInTuples.py @@ -0,0 +1 @@ +print("%d%s%s" % (((1,) + ("", "")))) \ No newline at end of file diff --git a/python/testData/inspections/RedundantParenthesesInTuples_after.py b/python/testData/inspections/RedundantParenthesesInTuples_after.py new file mode 100644 index 000000000000..31ac4040ce02 --- /dev/null +++ b/python/testData/inspections/RedundantParenthesesInTuples_after.py @@ -0,0 +1 @@ +print("%d%s%s" % ((1,) + ("", ""))) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index dded82dd8930..96deaf719141 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -244,6 +244,11 @@ public class PyQuickFixTest extends PyTestCase { doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true); } + // PY-18203 + public void testRedundantParenthesesInTuples() { + doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true); + } + // PY-1020 public void testChainedComparisons() { doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true); From a06214e2525d005b633e012a676917acb1aa6cd5 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Thu, 14 Jan 2016 17:53:20 +0300 Subject: [PATCH 086/825] add incompatible plugin --- platform/platform-resources/src/brokenPlugins.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index f00526448309..7575455aba21 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -1,7 +1,7 @@ // This file contains list of broken plugins. // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 144.2562 144.2131 144.988 143.1138 143.1088 143.769 143.751 143.516 143.381.8 143.380.6 143.381.11 143.380.8 143.444 143.379.15 143.21 143.110 143.250 142.4426 142.4100 142.3858 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 +NodeJS 144.2986 144.2562 144.2131 144.988 143.1138 143.1088 143.769 143.751 143.516 143.381.8 143.380.6 143.381.11 143.380.8 143.444 143.379.15 143.21 143.110 143.250 142.4426 142.4100 142.3858 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 com.jetbrains.php 143.382.38 143.279 143.381.48 143.129 142.5282 142.2716 142.3969 142.4491 140.2765 141.332 139.732 139.659 139.496 139.173 139.105 138.2502 138.2000.2262 138.1751 138.1806 138.1505 138.1161 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 From f7312cf0d809b606d43e8b8c61e50b750a0322dd Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 15:58:33 +0100 Subject: [PATCH 087/825] [platform] update info XML validation (EA-77712) --- .../openapi/updateSettings/impl/UpdateInfo.kt | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfo.kt b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfo.kt index 76012065b95b..f782fc00376b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfo.kt +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -20,12 +20,13 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.BuildNumber import com.intellij.openapi.util.SystemInfo import org.jdom.Element +import org.jdom.JDOMException import java.text.ParseException import java.text.SimpleDateFormat import java.util.* class UpdatesInfo(node: Element) { - private val products = node.children.map { Product(it) } + private val products = node.getChildren("product").map { Product(it) } val productsCount: Int get() = products.size @@ -34,9 +35,9 @@ class UpdatesInfo(node: Element) { } class Product(node: Element) { - val name: String = node.getAttributeValue("name")!! + val name: String = node.getAttributeValue("name") ?: throw JDOMException("product.name missing") val channels: List = node.getChildren("channel").map { UpdateChannel(it) } - private val codes = node.getChildren("code").map { it.value }.toSet() + private val codes = node.getChildren("code").map { it.value.trim() }.toSet() fun hasCode(code: String): Boolean = codes.contains(code) @@ -51,8 +52,8 @@ class UpdateChannel(node: Element) { const val LICENSING_PRODUCTION = "production" } - val id: String = node.getAttributeValue("id")!! - val name: String = node.getAttributeValue("name")!! + val id: String = node.getAttributeValue("id") ?: throw JDOMException("channel.id missing") + val name: String = node.getAttributeValue("name") ?: throw JDOMException("channel.name missing") val status: ChannelStatus = ChannelStatus.fromCode(node.getAttributeValue("status")) val licensing: String = node.getAttributeValue("licensing", LICENSING_PRODUCTION) val majorVersion: Int = node.getAttributeValue("majorVersion")?.toInt() ?: -1 @@ -69,7 +70,7 @@ class UpdateChannel(node: Element) { } class BuildInfo(node: Element) : Comparable { - val number: BuildNumber = BuildNumber.fromString(node.getAttributeValue("number")!!) + val number: BuildNumber = BuildNumber.fromString(node.getAttributeValue("number") ?: throw JDOMException("build.number missing")) val apiVersion: BuildNumber = node.getAttributeValue("apiVersion")?.let { BuildNumber.fromString(it, number.productCode) } ?: number val version: String = node.getAttributeValue("version") ?: "" val message: String = node.getChild("message")?.value ?: "" @@ -110,13 +111,13 @@ class BuildInfo(node: Element) : Comparable { } class ButtonInfo(node: Element) { - val name: String = node.getAttributeValue("name")!! - val url: String = node.getAttributeValue("url")!! + val name: String = node.getAttributeValue("name") ?: throw JDOMException("button.name missing") + val url: String = node.getAttributeValue("url") ?: throw JDOMException("button.url missing") val isDownload: Boolean = node.getAttributeValue("download") != null // a button marked with this attribute is hidden when a patch is available } class PatchInfo(node: Element) { - val fromBuild: BuildNumber = BuildNumber.fromString(node.getAttributeValue("from")!!) + val fromBuild: BuildNumber = BuildNumber.fromString(node.getAttributeValue("from") ?: throw JDOMException("patch.from missing")) val size: String? = node.getAttributeValue("size") val isAvailable: Boolean = node.getAttributeValue("exclusions")?.split(",")?.none { it.trim() == osSuffix } ?: true From 361154efec429358e11e2efb67693ee9bdd8b2e2 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 14 Jan 2016 16:06:35 +0100 Subject: [PATCH 088/825] [util] minor optimization --- .../src/com/intellij/openapi/util/io/FileUtilRt.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index 5dc28282a90c..38ba86d3c58d 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -18,6 +18,7 @@ package com.intellij.openapi.util.io; import com.intellij.openapi.diagnostic.LoggerRt; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.text.StringUtilRt; +import com.intellij.util.ArrayUtilRt; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -616,6 +617,9 @@ public class FileUtilRt { @NotNull public static byte[] loadBytes(@NotNull InputStream stream, int length) throws IOException { + if (length == 0) { + return ArrayUtilRt.EMPTY_BYTE_ARRAY; + } byte[] bytes = new byte[length]; int count = 0; while (count < length) { From ea7c3845b87174d88310732a05686d168ee431d2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jan 2016 17:35:27 +0300 Subject: [PATCH 089/825] cleanup --- .../intellij/util/concurrency/BoundedTaskExecutorTest.java | 4 ++-- .../com/intellij/util/concurrency/BoundedTaskExecutor.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java index 3ddfde6f5e11..1f39d04bd016 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -173,7 +173,7 @@ public class BoundedTaskExecutorTest extends TestCase { Future[] futures = new Future[N]; for (int i = 0; i < N; i++) { final int finalI = i; - futures[i] = executor.submit(() -> log.append(finalI).append(" ")); + futures[i] = executor.submit(() -> log.append(finalI+" ")); } for (int i = 0; i < N; i++) { expected.append(i).append(" "); diff --git a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java index 2ea538cb54fd..339a2f94e990 100644 --- a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java +++ b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -19,6 +19,7 @@ import com.intellij.diagnostic.ThreadDumper; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -71,10 +72,10 @@ public class BoundedTaskExecutor extends AbstractExecutorService { // for diagnostics static Object info(Object task) { if (task instanceof FutureTask) { - task = ReflectionUtil.getField(task.getClass(), task, Callable.class, "callable"); + task = ObjectUtils.chooseNotNull(ReflectionUtil.getField(task.getClass(), task, Callable.class, "callable"), task.getClass()); } if (task instanceof Callable && task.getClass().getName().equals("java.util.concurrent.Executors$RunnableAdapter")) { - task = ReflectionUtil.getField(task.getClass(), task, Runnable.class, "task"); + task = ObjectUtils.chooseNotNull(ReflectionUtil.getField(task.getClass(), task, Runnable.class, "task"), task.getClass()); } return task; } From 9843d2e25039f9b79c78cee5c23eee41c9bc29a9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jan 2016 19:25:40 +0300 Subject: [PATCH 090/825] cleanup --- .../openapi/wm/impl/status/InfoAndProgressPanel.java | 4 ++-- .../wm/impl/status/InlineProgressIndicator.java | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 5f76c973effe..5bca3646dec0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -672,7 +672,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge } @Override - protected void queueRunningUpdate(final Runnable update) { + protected void queueRunningUpdate(@NotNull final Runnable update) { myUpdateQueue.queue(new Update(new Object(), false, 0) { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InlineProgressIndicator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InlineProgressIndicator.java index 5e7131a25f13..cae90155dee7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InlineProgressIndicator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InlineProgressIndicator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -65,6 +65,7 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di AllIcons.Process.Stop, AllIcons.Process.StopHovered) { }, new ActionListener() { + @Override public void actionPerformed(final ActionEvent e) { cancelRequest(); } @@ -163,7 +164,7 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di myText.setText(getText() != null ? getText() : ""); myText2.setText(getText2() != null ? getText2() : ""); - if (myCompact && myText.getText().length() == 0) { + if (myCompact && myText.getText().isEmpty()) { myText.setText(myInfo.getTitle()); } @@ -197,10 +198,11 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di updateAndRepaint(); } - protected void queueRunningUpdate(Runnable update) { + protected void queueRunningUpdate(@NotNull Runnable update) { update.run(); } + @Override protected void onProgressChange() { updateProgress(); } @@ -225,6 +227,7 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di myCompact = compact; myProcessName = processName; addMouseListener(new MouseAdapter() { + @Override public void mousePressed(final MouseEvent e) { if (UIUtil.isCloseClick(e) && getBounds().contains(e.getX(), e.getY())) { cancelRequest(); @@ -233,6 +236,7 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di }); } + @Override protected void paintComponent(final Graphics g) { if (myCompact) { super.paintComponent(g); @@ -272,6 +276,7 @@ public class InlineProgressIndicator extends ProgressIndicatorBase implements Di } } + @Override public void dispose() { if (myDisposed) return; From cc330da0e4bdc5d9d574506d1927252924205702 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 14 Jan 2016 17:53:49 +0300 Subject: [PATCH 091/825] fragment in debugger text field blinks on/off red --- .../impl/DaemonRespondToChangesTest.java | 47 +++++++++++++++++-- .../daemon/impl/GeneralHighlightingPass.java | 12 ++--- .../daemon/impl/UpdateHighlightersUtil.java | 8 ++-- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java index 0c47086d1d89..df6f45ea8c92 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.impl; import com.intellij.codeHighlighting.*; +import com.intellij.codeInsight.EditorInfo; import com.intellij.codeInsight.completion.CompletionContributor; import com.intellij.codeInsight.daemon.*; import com.intellij.codeInsight.daemon.impl.quickfix.DeleteCatchFix; @@ -112,6 +113,7 @@ import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.inline.InlineRefactoringActionHandler; import com.intellij.refactoring.rename.RenameProcessor; import com.intellij.testFramework.*; @@ -1284,8 +1286,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { ((EditorImpl)myEditor).getScrollPane().getViewport().setViewPosition(viewPosition); ((EditorImpl)myEditor).getScrollPane().getViewport().setExtentSize(new Dimension(100, ((EditorImpl)myEditor).getPreferredHeight() - viewPosition.y)); - ProperTextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(getEditor()); - return visibleRange; + return VisibleHighlightingPassFactory.calculateVisibleRange(getEditor()); } @@ -2181,5 +2182,45 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { private boolean daemonIsWorkingOrPending() { return PsiDocumentManager.getInstance(myProject).isUncommited(myEditor.getDocument()) || myDaemonCodeAnalyzer.isRunningOrPending(); } + + public void testRehighlightInDebuggerExpressionFragment() throws Exception { + PsiExpressionCodeFragment fragment = JavaCodeFragmentFactory.getInstance(getProject()).createExpressionCodeFragment("+ \"a\"", null, + PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject())), true); + myFile = fragment; + Document document = PsiDocumentManager.getInstance(getProject()).getDocument(fragment); + myEditor = EditorFactory.getInstance().createEditor(document, getProject(), StdFileTypes.JAVA, false); + + ProperTextRange visibleRange = makeEditorWindowVisible(new Point(0, 0)); + assertEquals(document.getTextLength(), visibleRange.getLength()); + + try { + final EditorInfo editorInfo = new EditorInfo(document.getText()); + + final String newFileText = editorInfo.getNewFileText(); + ApplicationManager.getApplication().runWriteAction(() -> { + if (!document.getText().equals(newFileText)) { + document.setText(newFileText); + } + + editorInfo.applyToEditor(myEditor); + }); + + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + + + List errors = highlightErrors(); + HighlightInfo error = assertOneElement(errors); + assertEquals("Operator '+' cannot be applied to 'java.lang.String'", error.getDescription()); + + type(" "); + + Collection afterTyping = highlightErrors(); + HighlightInfo after = assertOneElement(afterTyping); + assertEquals("Operator '+' cannot be applied to 'java.lang.String'", after.getDescription()); + } + finally { + EditorFactory.getInstance().releaseEditor(myEditor); + } + } } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 6a3a08b38b1d..cfddc716f0a3 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -44,10 +44,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.Problem; import com.intellij.problems.WolfTheProblemSolver; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiErrorElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; +import com.intellij.psi.*; import com.intellij.psi.search.PsiTodoSearchHelper; import com.intellij.psi.search.TodoItem; import com.intellij.psi.util.PsiUtilCore; @@ -199,8 +196,8 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP List outsideRanges = new ArrayList(); Divider.divideInsideAndOutside(getFile(), myRestrictRange.getStartOffset(), myRestrictRange.getEndOffset(), myPriorityRange, insideElements, insideRanges, outsideElements, outsideRanges, false, SHOULD_HIGHLIGHT_FILTER); - // put file element always in outsideElements - if (!insideElements.isEmpty() && insideElements.get(insideElements.size()-1) instanceof PsiFile) { + // put file element always in outsideElements (except file fragments where they have crazy element ranges: an expression might be an immediate child of a file there) + if (!insideElements.isEmpty() && insideElements.get(insideElements.size()-1) instanceof PsiFile && !(insideElements.get(insideElements.size()-1) instanceof PsiCodeFragment)) { PsiElement file = insideElements.remove(insideElements.size() - 1); outsideElements.add(file); ProperTextRange range = insideRanges.remove(insideRanges.size() - 1); @@ -432,7 +429,6 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP @NotNull final Project project) throws ProcessCanceledException { progress.cancel(); JobScheduler.getScheduler().schedule(new Runnable() { - @Override public void run() { Application application = ApplicationManager.getApplication(); diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java index 4ae0f8a6ea1c..36c2c1e007e4 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -188,9 +188,9 @@ public class UpdateHighlightersUtil { if (!info.isFromInjection() && hiEnd < document.getTextLength() && (hiEnd <= startOffset || hiStart >= endOffset)) { return true; // injections are oblivious to restricting range } - boolean toRemove = !(hiEnd == document.getTextLength() && - priorityRange.getEndOffset() == document.getTextLength()) && - !priorityRange.containsRange(hiStart, hiEnd); + boolean toRemove = infos.contains(info) || + !priorityRange.containsRange(hiStart, hiEnd) && + (hiEnd != document.getTextLength() || priorityRange.getEndOffset() != document.getTextLength()); if (toRemove) { infosToRemove.recycleHighlighter(highlighter); info.highlighter = null; From cd4031719b5e9398b7a566f6e190c41f6cbacdd6 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 14 Jan 2016 18:11:40 +0300 Subject: [PATCH 092/825] scale editor gutter areas sizes --- .../openapi/editor/impl/EditorGutterComponentImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 43d91537532b..a7192633f843 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -112,11 +112,11 @@ import java.util.List; */ class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener, DataProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl"); - private static final int START_ICON_AREA_WIDTH = 15; - private static final int FREE_PAINTERS_LEFT_AREA_WIDTH = 8; - private static final int FREE_PAINTERS_RIGHT_AREA_WIDTH = 5; - private static final int GAP_BETWEEN_ICONS = 3; - private static final int GAP_BETWEEN_AREAS = 5; + private static final int START_ICON_AREA_WIDTH = JBUI.scale(15); + private static final int FREE_PAINTERS_LEFT_AREA_WIDTH = JBUI.scale(8); + private static final int FREE_PAINTERS_RIGHT_AREA_WIDTH = JBUI.scale(5); + private static final int GAP_BETWEEN_ICONS = JBUI.scale(3); + private static final int GAP_BETWEEN_AREAS = JBUI.scale(5); private static final TooltipGroup GUTTER_TOOLTIP_GROUP = new TooltipGroup("GUTTER_TOOLTIP_GROUP", 0); public static final TIntFunction ID = new TIntFunction() { @Override From cae1a835025b2f4c1b011c378941a69a3f00a930 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Thu, 14 Jan 2016 16:15:28 +0100 Subject: [PATCH 093/825] Rebranded artwork for PyCharm (add missing files) --- python/build/resources/headerlogo.bmp | Bin 25818 -> 25820 bytes python/build/resources/logo.bmp | Bin 154544 -> 154544 bytes python/edu/build/DMG_background.png | Bin 35696 -> 5195 bytes python/edu/build/pycharm_edu_build.gant | 2 +- python/edu/resources/PyCharmEdu.icns | Bin 423650 -> 278515 bytes python/resources/pycharm_core_about.png | Bin 43746 -> 22873 bytes python/resources/pycharm_core_about@2x.png | Bin 114201 -> 49395 bytes python/resources/pycharm_core_logo@2x.png | Bin 113826 -> 69866 bytes 8 files changed, 1 insertion(+), 1 deletion(-) diff --git a/python/build/resources/headerlogo.bmp b/python/build/resources/headerlogo.bmp index c06099264961d8688a978a3357ba4d686d74fe3a..db90d347a71e4d0c0f67a1cde8a4687ef26245bd 100644 GIT binary patch literal 25820 zcmeI5c~}!?9>?8%c4_Ie$Fo&idt0wsTiZTvt*fm!iUJ9Ux(bMv)@ntLZhb%`SPxKC zyig87t7ws`t-7_PqSD$@2neF0hJ=~P%p_cakON2vD6RWr-p)9N5JQOFJ~7{CGV^9K z{PpqsJKmXjohBfb_G9!G>_@^U4L;-H^M`(eVBfD_4*dSp-_VCS0Xqp#l{`s#lCi2{ zg)zc$oM0qpM3N-Mh^A=;Bc)PV&8ViPrj}7%U0ppRl}gpXsIjq8&8UfyMx)U((lOHO z_05c07_~AoFfuY~V`O5~&Z>jaEmpT#b@KG{z51mG-TB=seJu~6gom(_hfvBQl(7h_ zx-$fT4rd4eyE8-pVb3u{0AbG}Z10I7u;eJ-i}2?j5dQMJM|kIf`4Cyrq7RW3?e-zx zgn+SEK6FZkMSL6f$%hb4e;Xe{H04Z)7(V1a%u41%v@w>VKni<)K4e1a-F)Z}AKDm8 z!HNjuLmx}|0AXw;A6jH+=EDcau)7Z*a)to`j`E@H3~jGVE&9;K(5%dAy<;~+2&DX2 zYR1q?Z(&PK!!;H?)upH?b=5S$^Z!wo+U`Rj*%L#qtZ~()vu4@hL+BDwL1Ui}9m3E) zA9Bqh44kGvymO0V*xQ zr6ejsL@kV^17hi*Sb9+`y`+%NM>WmmT1A$c{#Z}WH;{7;^jw2tu0iQa4 z`DRUnuBki2zVsGO$xwfnA>V}7d;DwI&4X0dS}Gup4iM3SqAu?RFVYswYbEBj-pkFv z`HjyFpy`B&o2gZ3G6+mYfvL^MWb!e!`?PoXwBPpb+B)Ag-RjN|`XBt&m2;Y^{F-n-4Jp*nLXA?OsTOEz1=>1+ zwqBrB`Dhz_w2eMGwYRRxTc`Eb>AZA$FMYFDi^0p-?rrMg#@`Z*ZMHD9eZJJ$eR$t| z_!U{0NQJJY1L72caf(GEa?xsR(W>i#kyjQ*lm&cn^5w2o47Gc zUg;^9d6HG0BtDZQW|Hz5BsGJiXHW`{u1yKs3}vlnz1mA}@HT=2JNet!&8nUlx@sEE zhrC#7o#9S8o~0KQrwA4)7RM05AKwTHEu6pfoPS8}oRD1qnFU|WC^+R&aAx{Xxzh^s zrWKx_TJ+tNqKlKo1(U?$N#f#(;?nNhq_V5iq*xcmmNq^>7|XSFE`}Vdo(8K{aW#$g ze7Kofx>gaiRuLShSRAKV5~mD_#+O813H+mj1a1T?@)<%hv^Y=Gmzu^Y?;qOi!`)=~ zT1bOHPw}ou`JPDmel#8uQMTw$4iW@aGln}2%@!HDY8o>`+RQLR9~CsKw0J&|&0 zta4d2zBK&uVmAkA2Bq}Y8wBm0+?KCXSY+t(p&7&T=WUFoM~H+C)SL}eph&q)r2H_p zdPOv`JmPYQJ1g$~Yxeh zjjaxgB0|G2FZ~Ov?&!EP>?PKYW(-%fbpSvYLk^Uc0dKz4dQI~caVUZEiKhkev~QeZ zWo&gslsqiF{DZ$cNHZy=kKO?GLt9#l+B!q~dVHs>X>4YA4nMt#n!Sngj;Dd7Ft$1} zN*)nb{^8>ek{QE7tsI%qvAu;;_V_%8*89UB@b5QMo|~yzn5Zpf~uocfuBB zG@$zy7V{yhOYLLml(AGS=IT=GKCGy^xs{x{g`Bp9oSsMl$ypm^o~ugcJ?kLx8D3O< zXN6&3>Qbllq0MzEJg&c;oW6~m3?#Rb)3%Zx39{+2B~u2oDrXcN9L%0DKTeo1AuB5j zUe5p{!DCV1eDlqM1q--~_zZQIM>S|_A4Dv5N+0%yVXE9WiJZ8NoV1Oc0wgy{r;3Uv z4rPTpiHL{@_QXBMB}xrQ&mYVe$ z-=DNGmVyrt5J5@gge3AEL~^rqlBjsXa8?LQWMm|J;_h+s7PN_j4Es{k zIHeB{XW7p147PQ*e9SKSKX=LB+$n!+n{@2@;xVIHA$n)doY}s8``*2K;gKph1Ktw~ zh4APhj59Mc*=sEvuYBvSD0DBqIYocz(bkejOyI*}H`8@NcZRMxZ?k;Zo0=vMKd_s4 zeYgA#L^7#z%zE(~oDjp+t5>5l6DLlD7kA-gQc@D7&|9k2aS) z0#-E0!ZbRqEevgc7Q-ohDEP>BAAX0QN+w=SCSF4%lPcd>FMe$dE5tA+CI+1tJ9aFx zA9yl5I~#rlPX+`8u$Olo!J^#Pva{|~k$Xd_y9OAR{#8$<_f(hmC6+p6K9unh-skz! zLhQ#q#LLOVsAS@mWMcGo$>@#ZQNRibG2Fj@|B4kWqN1Ym^YhV}<;#}?E7Vv(T^b)B z9~c-2EeKRU;4$bq(4Uu{btj7+QKOEUXlSU#{_y0?K~>DH)j{9xDhVU|eadELoB;qarhUB#c4eEOSv-(!%OI-{(XD(jM1=IWb5UiMqk4`0qAdI>C z78OjQ+QP6eHH}lo(vDulQeb!t6QtwMrQSiiNR^akW^x5 zDlsgT7@md?J6QF^5!t{T>3}aP2b`|#{~z_fNX@4an#1ARqhZ?PD|KJ4)Sd{}W`CkN z+N*a+UH2`xY6cBjTR9){O$cL)KD>li9Hes&R=xNuNeoCno&GCKj$~K1Ov8tKS~ZYi zIPipYz$t0}uPYyqZb)9GITWGE0(4>8V?Z)Ob7YVDtDYEIjHRx*HZz93eD4Wn%|JJ? z$}j1kvhk@I*b@xQE|Mt5?qjlLIzAXSV0c(IAV)UfxU7reIoa!&BDbvmW{l=AgYmO4 zZ4THnTby9uIXqb7*cx#_POdyJu!6ou$$#9ocR107fWr)hlrus z`}jBH(qq-%e}<3wl_Ulvp9Yu*z=u@>k7L6ss3ZKfF99Q7PbW4V2Y`?v#f=g>7~0n# zI%Q3h?69>jVa2_CMfvCC%Kg|N1oHs)#MihVUM+zYOwAa=#HmtMlic**k2L$M8WlY; zv=U40o2PL~hJA>oW^0>pYwlIhvSZb!v+*&77 z*2QqK)RwxGA4|;`I(DtE`_6g0VkyU1w9F2MTulQQ?N|#M@*!B!`WmzlMUfmkPvh)$ zX>WZ9l?|UE7faDPQ4U%A5-@gW*q0vPDf8jQ1kQ)H*QLmZ)?=wd7+UEqT(OjkrG2Pr z%zS8;4<8&uSC7xpLj(2Q`-iss(5yd%ln4MhhCmMigyp`h*QNIT-w24ItGD1tUVP1t cSc({0kEK@Dpyhgt-=3jU)-?b4N56jm12t1C@Bjb+ literal 25818 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
    #*_XE7Ic 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 literal 35696 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 L%Xa_2v)%s#Iwd4h diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 4b1158acb423..d10f04587072 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -48,7 +48,7 @@ private List pycharmPlatformApiModules() { private List pycharmImplementationModules() { //modules to put into pycharm.jar - return [platformImplementationModules, "dom-impl", "python-community", "python-community-ide-resources", + return [platformImplementationModules, "dom-impl", "python-community", "python-community-ide-resources", "python-ide-community", "python-community-configure", "python-educational", "python-openapi", "python-psi-api", "platform-main"].flatten() } diff --git a/python/edu/resources/PyCharmEdu.icns b/python/edu/resources/PyCharmEdu.icns index aa996284732da49da59c5d0573b9b34930c61d17..79f5663826d0c4873e413ef864e64c78d209bd40 100644 GIT binary patch literal 278515 zcmbrk1C%98+OWIJHoEMpF5B)dTV1wo+qP|2m(^w4wr!iY&&)UfoPWME_nx(G>|8ru zJa1&Yk&zL(R;H=Gl|2BI@79Ff(i{MQf&~2kEzo+yQ?x+;ZUtD<73AOAe@H-N(dVC^ zpO5yS|8fAEz12YfOZkr)RH60bH~mLx$NT3gK!QF$mk|Gh`=^TKv-eN-AO9Dsz`xB9 zxxbYM)c?%`3sk)RiT*<@LKIc`$>&%|BuO<{`cQHvg&cJ74Jdzt1Q9 zP5`#-@AFe|002V!-{;@(0RW`gzt4Ya0|QY1yy*Xbg=Rql(4YRlpg;Ln-~s5vf6_ny zbIQYDmFcb!@Ox4Rjfy>MP z_a5yc{4wQVahP@b|J~w$UGF}YqL6>{zt+BlXaYInvg1Z@ zzkOS$T#3MFszx2|*?EcKsUY)e)Io$6nX)Pgv=`ZQU83{?b(ZjpVCKsRpCTD9k)fo$ z$i_ZU8?xQJGjm7=g~|9t82u zO*e8R#l{?wz}gW%R9>L7mkHL!V%*E5`Ot^EQ$zG_m9y3jXm5Pbb(RK7C617tu0;&N zS=$G;8nh(T9qX|?4x+gXl!U~w$#(F!Sp7>OyqUsl{umu;xFX~r{Xk#Yxk*wTsAWTh zgm!NiFmt9OtxcCRv0Y?pPg|$dUZ)8ni)Yy!qWmIl#e{PxG8L9>e6c5UitemRNH@Uk zt-w_r+)+|V(5J*fr8RJP|4_XG*2j>TUx)}73`}rU4Qx$iZ=P+^y!H|HQ&*a^VkA}m zG7x?KxGcVPmbx@|3Z7F{Rg}1_u6Q+m7eK)hnEj>b~Jr3Ku(#^z$s36LvF!z`GPz z=v4SAsrA_<(wO&22Bfn`I^0v-6Pk38Urzubtj1S@dr}k{ z#&E9EF)0>AsR_7Wyxki`2H&FVB5sOz+QzgIBXd^dc39{Ou3BvVV4G}P@jQ@wO!Hwz zzQnXDA=%(SiwE+D8TW40dyq8>*KpU=Cggz>NkZvrWGl*)U=9m-yuFQamy9|)gYRhV z#3cYOe*1_&m9;Jee(ff{63V0KY`G>nw0>8St~fV=vewfb5?$+egF+vefFKrgmTv-%UYVpX&g@=NM)@|EhoRrHc9C|C;2iEnoh&>6!G;;aPxAB= z1Q~Ua`g#}(m-V>Cs8nYDt-hN2=F$)PbYY!fc+Y(wAJsC*yao-noo~FNc2KlmZS&* zP>Cv;epPsiUnS^7;&*WB*{S4E;c?yF$Z?55H)v16VMZ=Z>IB<-PFk7D7JR9S)0P0; zHUV0aO%{GTGIf z=Os%7EnYJN07+i0g{Pr(qOg~^cR~UU?iZ29>4u?GOow<_jyY60gCMon#)OrER)K&8 zS!?!hriEtPIeM5#=n;6iWf@NJ{jq)ME&OWCl#)Q_-8#K z@kQ+DI9{s6?KF*J_!Lf+GuGO47X0V0FyDg*I$mn;Od47zb1IKQwBAc5rtFN{KLH*v zTZAa}NSKwhqp)Zvt=jKJpFu>DpX|g&y1tR9XW55kv&oitTB@jAU=gBw1+t;-a-<8! zOcyt@x8DQFO2NH`eyP&#zuRvv2Nygj=6L00k@u{xBX?%pHwC&mTK(j{9Wzyw^k0mA z!hgA5);~w`vCo@fi_cB!X47BRNpQ|Jk6dP zCy4A3X*~3>xK^Fu8}?O?Ky<9_4CaedOVK^%ba#(|I6VZAfZMmJoJosVMPTZX0aCkr znS3olD5U3JohuUH^cb39xi!{&J%0wCaJQPE(n&5Lsf>5wP?fOFf3TZS_$SN-UMscI+aJ8wic!y$%M{nI?op!CcD%JN?q>xOha^+DyenO_}M|cO0cRLVLOg8mp8Gl z%dTdgedI!(wwDA#+?51Jn1z7n(*$^>P<{z+p(`Ovxnpqx;Uec^>||DxqP10ODND7P zt8Oz>e@EkFU?I-cG$Gf9uc8boM>ZJ7hqjmMQ^L>Fck=CMGI;2a3(5jzcxxpl`{c03 zXP;l@rJ#OMA$Lj~{Nhq-==5o#kVHwf(RfdRe7S-|sJo#OZC8&)R@vNo2lbMRiaI9- zghIL1&OOa2cc^ZaT$N5kO=qXGBI2wInW|k-N{I49v1Mes&oNKs7Wk8&k6$*jl^JAo%f~)ug#SmA$%$fx%=^py&pPnQ|c4>S^HVR*7%;nnyrf zKz=aqHtIS>KHLP3p$wA7^0g%?Ld*vgMBze>&1vgHx(FNAYCeTlGB1ZmTwzA72DGG( zkqmv445DpQ8{xr6ir!e)l{8*WQBriDm>`7W89wj%L%S%u1QR_{6=^dO*UJI*t)weF zsKzU0rzpi#3?0)fKD+80+$GSKPr23(6@{2T{ZfOdZnW0&5SPMH}uP=Ix%+~T|jc00^p_L~S=gQ``Q43udT;B}vpBvxvfnD>`* zPxG>t5!yf%!buvFX+z7-Ak39I}8MhOrw_l6!3x{9O}b0^f`YCRck6uMHe>gW!Zq$aX2V2t8TriqO7O=l_PwU~L= zj4)6ZTfyy6a9X~3S!>C|)%`tYSoS~q_WO1d8ls#RveIH_toXDZ_ZePap z{Vl_(m&OQ~tB>fs@57_qjI^CMNAtHH-6(8!6+@_X;bu?DqLAjq2xcYZBuwk7$==-I zCx=k{peMjD#Q|X`Q!poduEhf_Vnlin!fh@l4t1OHwk6wkv}J<(E&Qn3xbz`sd0S3e z`cHE#biBnE86Fij&BGzPaQ76JVwz7h5ESRtozNgL$FaAG(UH3LIW;<#rX$HGXfvK( zJgnyMlyixsuf<}_uC%r;a7r**bXo+sPc(R%Nd^<9cZN7anp z-I|%W;;0SufouCt{2%E%;Cn-yBR@tQL)r^waP*j_MM0>ug;vQ3j9f*9`Qb%ZNUHq- z<^)OeWZxgg`k4-CSKT?8qUB~uv**@~ud<{v_IRaV#cWo3a+ zsbx`h%VE}D_PL3$f%twMTobbJV55LZJ5JcpRwL@l>c##%f1wl4qZf*;raJrME02;q ziA5)Z+z55cuq*M^!ktSd81&A1Sa?;o3X${oS&Ml!TAm|;at?GY4Pb`}1P=`{>O0Fe zhxW)%)2~aVsniq|nL`-e+=F#L0ody1b>Z?O(>fp-yB>xu?H0*;3~muc7%v!tkB@rw zd^7%YmU){`T?&!j;G715QkcRWbns$Y+m(Z@Ma?%IHmn8LVUtoajt{d?b@+q_Ei$?l zV-Ze*qBN-l=<-IVu;!N0uZ*w`vFfpGl109!pWMae)Q6Hjafb+-h20jwNg&iMG&47^ zb-7kf<4({XrQ&p*7-h{LDjj(AZ8jts83|XiF}|D57@u2 zB&q;)o;03Y$#43DSVdC(DB+?RD8*Wt&C2`N6_xZk-d?yLM*%XK@2t}a7r{hDh(|U` z;Cj|B4szLX!h0clfjcBTjr%refw&1`MOaNE#a?yKrU;bLp^-;%@hBp@y2NQ?Fm?Jl z3_+7&SodP%Y2I|lxMWIj$xcMzW&oQ){NoQg`WmkN$vV)bY&n!#I-zW{Ih(=!8o54o zc^><<+XTUoiGgPwhSD3DSdCe{ZC|I0veP2@Pe%0`u7&~*MUg%gImD- z(;6z|Dg@%)IcX|^Glb8GRDgkK(rcnTh3XqJzJo%7F$mj%Y+rdJyc<~g6*2cbD-C?P zoq`DG&2KOZnm3r3@pjCJHf$~3ZRpLu6kW8(_$62qTBYV<0|=a-_ayS+h4H^W)syM# z{b71!P(*Tpb#c;DHke<8WF$E}`w{NZu$Mv~nAMYftokjOw><08pX!nNM%7RNmo3|5 zL;kCV5bfc2l}*0vt}$*}YLZWCCV#cn<|sl|Et(rSclOGH3npACwQ^ar@}&qCDMT&AY!^orZR21TUtfF#uE!8Ul)R40p%(J# zs3Erb=Bvhtffqa;e@y=@BV-_PfGVsLK#H1}vtK7U$>Kkm9#PLcV0+sbu)J&?PII9R@|jvlqn@I?S(&Z-%tJ?+$M4{lkk+z+bR3RS}(d_oPk ze7am4aO3{)#($K3oAu%6+Mj=+a8)IS#F=VyA6ANXps|e3Y={;X`Bco0O|cb!t3{r4 z);O6kMt1hl*B3;wvJK)^dr~CTc7D1I)kcfv4(oywHSwgT;mcaVzUvGLQfU*Xe8BN} z&4qq`urYsu#%&9*i8qXrSKb$0r`Y`(O8T5wlkP+_+uD4hq?fw%SNCe=hG}hvdZCR9%^VOo^oph5SzLswIx+;C@m?(rEA1!u9mT-WGaij=``zU} zORlD6!oqvh;#6@|I#+Q`Izn#-2WlTOb*cN%I1#Gpbz$UF^BxM+ zt*j@NTLHA`;dC1Ut>@hj+W;eWFO+X&-ZDkb+}0pv|fTDkpxpUNpT?&}z5v$H{a9 zfPcWoX)d_l%lAPi)DB9BdA%OV>X$S^?#XdXeH{)&r@B$dY;Td{Q-K(4~hL7Il zF$M3iur76_P;3oCWJNOj%Ly=Xe{=`qHmsA|bdFoVxoDQuE_<K(II| zRUO%?JK*&=GqoIK4`aC)5;ZT@#J#88{M}p&ihmob?|dH@c|(Cg$)ZUsNuSM;d<{3O<>I31&0GLLr;)tjv@unkcdc> z>-%!KE#cJqO|x$`7r*LcueSdA!qOW{#;8q@@20X@r+JEU86S__4;hzFL`{AWNP1{m zKImn6ja&W{s2HV;wd%8RQ@p0k1C^C`LFRX4W*8q#0 zLBl*n%A7ujFRfI#4h;5*PS+(UTzpbR0hAfD1xp-mu=#%bs|?ReN%+hq6l9 zmpWjkMVO06YxO|8(u4JVuO&wH%8LbwsmSgB_A2pF&8rX=2K9jEe|jv-dW*I@C&?Id zYB@c@cvsbHzT_1wQ45}akyqprZApdhBdR@A4<#cl@lD(pr4j*1}*I|{k4+&-k>|`l$4R4^EfgLAq+jR--+zx?o+|Jnh<*7Gv1Xc|#1~zfaEbAA> zs&GtN^0+L9WuOvW&R(9v&395?svkrvKqF#uN2G1Z`xk^?lNUF^-G2!uHm3Y6==kK# zt*A!usYP^F#Az5cyx9i?L}iW||8QvuHv*HlF)Z2YOO-fNn5xX zk79X{1eqv5-#Gz`MVhU;nQ$k83Vp21=F-db@M%!n0sBUk+=@etW;J-TgU1R3M?#`Cw~!bAT? zChoJlGhCK?-i9n<}4qL==V)yQ$Ckyp`WT$nvs z8InBZVa|R>Xb-p;5BJBs zkK>OUPA0D;Hgt?*+8_mnP>GhI9Jerue&tS4vY_HWut!#51?b;97quDJSe<2b77b&G z)hG%&KHI3&+nV(Bs6SlXsvB3m6Yea@3WG6k)Ea4=p76KnCzl~mrvNUUuWdGt9_BB8 zT3eO-RBJTWKd=NHXH;B9CZ%VWdk)PDu2k?e+|7x0%vu*h{Yo}Wp6rzTx}A^oc=Y7= zqnR{it2Fk*4pDE?R)d?oE9RytfoWXX`ViE;Phe@Tk)$cb19XxXRx)3(TTmajpZ>z0 zYEeb|6oq&HK!^(7ZC0p-~H8KI8@Sp!8C*2 zL->|N&EhAXf`xj<1dB9;-udlL3VaXeF$=F;W%j$(o`Ibl3C_hNvfq1D?Sor-?v@8M9RBQ_)ermQbU(3#KO@P58%ra88wzHUqw13M&j46*2`9@zm zWERO?#}J1bv@y2?o4M`&{LJkyO)j|mlQ7?!1lKX`41Hh4Jpz8#P3l>gD}CBvH~%R#QU(kbBQ5+=<2p(sQC62x$aM zc*&Mjm`y;^Zw0y-lW`E9Svk!$ZSLL|jr#?+0>D#Y6oB4bC{TJf-|V(}c3UUwDDs@Y z75N2MK~H@XlZ8CnFs`BSLlZ=Xy@82y;X7z2%5k78-uj6%B#>6% zv{(cz>uqB5Hw+g;0iSE#{AFi(oT&`#N| z5#Z5#PbcU!Y2@+u=6r&ml|>3i%}VaKjXV|7#}iCfR?hsPV$XIh?diUjd?QjKA z5E!{5f*!9)m>n-8?7ln)yJu;^GN3&X1_K>W^|e2byX~%trXLp!*3xA9;7VsC2V~pJ z`h71LHP(Jv=FHL}yiS>7P2VTV&Jq9O0~X{b>=hbTGY>1hafuLK_UD?v6RHEjO%kk? zopfw7GDAaeLidW*yUiavHc-C#bf4)px890+DNt6@4K+|R6V;ub?45S=!b`P%axTAq zjO-LjBwO}8jF;J&Gw}MhAMXehKBTu{mQ5DSeR)c@mh&S<^Vu)L2ldVzBIYHL@>^N- z?T#AV+7sb1<#0@EW+2l{U{vQQ)N>?C9JUmnv8xd;cg2_C8FSYp_G=SOK4_}B94asP zJvKy~*~^TCf$wCn!&^^jq`_K^>K^W#vQ-b327C|iqL0Vb#Vjl97O6$|v1FB;ak<#f zymeMRuZ~4KqFDPv5nP<;InUX7TGPELvQzhZ!3&+&UDL2NbSLtApqlwDrF?yMYC8w| z-H>U@Yx1N$EKKa{LGEDn`TUuk>>{0BLY(oHt!u5X9CfuqrF7P03RU**nw}7GHz|QQ z6R0#YimlvOQuUL>?S@wxRF$cjUvE{IaigH<`VAwfJim~9g2|O5Sd&bbB4x@r-xE23&@y?yf@D8>EXq&^hm_Sm}iV~@C7YDe6`dM{(9iMKKD}#j-TLUZoddpK(#3lMwh>mzvKQpXn|2Ng9N91R(}#f6bn@ z`YAZRWSa~#J{guXv@6VLs4lTA1_t(Hm9=S zp&-*;W8Ad!_pbojXgeTR}#2 z@huc^zHp@$LZcpL8 z3R>VWwbR1Z?ehAUOYku06dR0Ud7rUq|KoHit*I1uno$I{;E=iR(I%>xZQEWR)6 z_&@oN_!IaJp<@=2+uN@j(t{lIJ+^_f49AqLU!$cl2sYTzHK~Id){i@uDsOkgkARQs zkkUtk`-v~L8~dew2E86h;FPUkK+|LqjwS_S<%E?858z@f&MTiAUrNiM$O1vv2s-vnTYEJjQ(2E{>lu9ok6Lpb+e&ajeFr#V9j+Zh8CVlje#8NWo{b{Z8*ZT} z4g=lfp$?Vx57Bsktkp}7yXN4*`{JH$%h5W*9fvS|mjQ#DlP6z7DNz?eC``;7ap%~E zYVN9cI(a3U^bKUqyjfSBy#R~suDZ+z!ms^B4b-HRGMvC<0iaNa|Ixxn z`F3T4eq5t(8sigI-7Bk#ecY*9yCwkKWPH&H_fZNA&FcUp1$pGH`Ha|{M|yZJMSJ`` zIRgrFfd?Eka}}p3Q%oGxcTA!liQaE0_(stA`dNU zRrf8gW9LE~WNL|%e$$eQK|m^9N| z4yZ*0gutMMfHk8TqU(IYr&fARmEP!!N6E?<0@hyd@z;<4pQR!wR{;YVa8J@0gNV7in#6GSRmUplD!SLwFn@w)Ig$ ztY!u8>oA!v-mX4&-?qY@Jal%Dt_FWy>`SOzzyl;L-M%ClJFF|*s(6HymOuMsXfDY_ z?{ReO$c$U!;Y{&K9Ui?vqG(WaS;U&NR$&_1Z@@apIJT zw)b5$zSQhUzL%Rwe~LExaI)qqlv&`^bBUqrvJ!40x?lIgf;(RfdcM(PO9}MKPQ`+` zh1lICBkuE|Q=9}`M(U2K?pSx#x zD^q1nZV!(s%%ks*Ag3-xvWBJlj?L%1Rm2n5_0;fHIh=-5IvX_Cv7;vE4E=*99|0-6 zEtxo)oBf8UIW>AsBw6BH87rv8<^ zg4J(yS97E9=J7`wc>?YXoYzE^kWZ?Ci~4+`CTexD%&Tbk%rf6wer_tkJn|*S;Ke5D z;Nh|y;N9BzUN-0p_ATcOMYw(XWb|dx3eNlT6nhe)0Ky(Bt+p@I^=PAEer8M!i6V~q zu01gi4i&|ZFx&fR&ALhdnz(VrYIAs-rzR!D5=r@J_a7IF+GT~wZN#FEn|e*I zP@6w*&Tq4KBOC1=4U6_!6+H88bZ*>U=`-3yPISn4#Gcw`Q^CDqc2ensft*S_LyV%M z*-f0zIrv!NLmC`8qvAxHV58W>FW^njwOI&g@jO{p$9!|%7Zb3`H6SZ}+CoIVO-5;U z=O)oQi5O*rJ*q?`eYRS_G{j*vqnfN;AcONH?3k@ISQhF+j!rFYRM`QIonOok%RGA% z2^kcu<_)F(^nN#mL{JH>bb3dJcsDhF7O^zeyZj!ULXktO1%O+*;VrzWhRxkkcf=Fg z88(CTp?d#$#$;sUuhuutW^w3-gFJpxssQqJ6rDs8GjDod1EJfXjt5yG^QWo7OUaNYo0XOHqTPQVKx5|XAs{VE)900;*7 zsu(lM07_0O$iWnW1Mi76oCB6*jryu?YCzJRYSsly-1A&OH%%9V@Q+l1TR?>_X3ro; zo@&bhJQJ56T#xyzx2u=?*Vn0hTlz1TrGDkY<|uTX0vO$7t+GYUF^oiQli39Wc&6GB z!Zz1A{AM>V`zdnGE^X^%N37#7$#ZC41POV%J820!;PCmyykGh)ekg@V;N6K;AlDJ^;F_8rK6r+{eiB>qih8D$Cx76OX4M=FFkHVyx zuORX$sTdI2D2?rUy?@Zvy6eFJ(_He_2mQn!q1g(QxHtw|1COZ}BkvbUelM%M^Dk*m z_jdLc#{9nUi6`PO3oiy_{-m}4vj8r{TlRaw_Q=dB&-#T22~~4^-grZT79n<#qMW;! z@ZOLTI#6e6`~&{2q>4Ggk#*-U=J2j93-aO2ZFH$SEQ{r5PzJc(j;a=XU$jB7QsB@CiDE24-^2NrBVE8%R zdmb9T)bbxwzf;h3%(9yMBQ_)wjZ~6|!_4xcx#*QF0JKr(J;hy(x8q?bG;O@{OUa z`ObRg>P0c%+W{&7qsDL-vRW|G0f;K50z((`N? z(?>3!>xSUOt@CmVbOR-_0kOEU9%2U8(fgSjm9R2uuXuq%35(Z6>fZHkHqZ+H=7`)c z`8Bwa-)~bIhF;xWgIAXcZkW00pgPnoPUdN(E}@Jy^LAO&TT@ckD!4T+=o{SVVO4D$ zN&U--bhbqbp$qo>@IibO;tVC+x$jycL3Z**uzx8P33wQUMA+RZTF;1Yo=hB?yIrn& z6Xwbq$A(f<{3!V;m6=74mx(`T!H#Vx1#HbL=J>T8%%co+4XH;8J9GMEQ!m-NgyPYH`WE(51l9fvu+vjQ+E$dzAI}_p%7Y z2uE%$)O#2RTeFxJ&Y+R+c|9OOw2P$zCrrI@{Zl%Hq%edOB0u0AK`^Y&A}p6n@ohyQ zEn`tO#D2dc@ohnEk>V@F;nUFBJj!C=bjTTfdL;ep>eibZ{U3#(nm|9~4!$4FY4iz6&>zi0TAhD)Ir z7d7W@9%}}=p;$lps^)qo=3~Twax9%94uMS`n|Njs*OQ%omatVK771aign|oe6$gWo zmo_{&i8)Lu1D#zdBz7o34P+MVU~T0<@#wN0BN7KgS&~WGh=FbvNZtd2#|P=x*gftn z17tG+o2@BUWn9Dp`36N@zLvnl;|A#1I|d4b^^ywHMuk}xHc1P&t~ApbRjT+Y9hWh* zs(umam~O8My&lQS#32zw!DgPs?D(aISiDg49`zUk#SK-y3=*nP#fzA=gykoYRbqUz z^Yv_elPPYRt7yjyJwQDPqLDQ8Y%IR12|2N#?CGbmu(}OA*_1dZP{>9f62`hqmpqp{ z+WDJ2|EJm!5}GyY3*=<&^(DbLcQ-rf#LL+Ba1}Rx!diW}F3DKqdy@T6Kre*;p_#t; zqFchfLuNq%dBOMub@)^ct8b=q-xj5r+U@fS40^vId5Brep50J>0*=CmY^Zj}5@6@H z7w_WrbwpKLLxvmJ!A-I=(T$2gFFj1hh`=A=Xt^{C%k1vlN`paqX?s={_55t0pRt)! z5mKnI>Dxx7<{UL%$8(+m(TULEuwdhw8N-Ik@ww3tsk#Vk+yF5Hnh>kmovC&!FzW8$ z?kRZ_#?CIXf^ZBR|B>ao?$~VVM{Ia=iYa>l7L8B*+^p=3cwy2{8;Jde&`E)G=>e)H zpe`Ed1pbKIFm+h8_Oew;L2uJ*e&t)azzY3YJ#pQs>86et+V7)txSt$UZCeIcEgLJj zC5o=?_c@;=;_{k6D5V5Ns60ZNiFoEd0LGiAI|Vt+@W3S-T^qR*u;qD@A@In2M`1L( z^ayHdx~lG5`h#VL_$x96&4?(2c7IFHTjt9ZdKba6nZBr14#f&#JUxQ+I;D6mO?z)| z7^|NZw5b6&;(B3gfrAo%sDM<`6X)aO z#xi_Jii5d+hY8Gn>N{|=B7dOIJzh5ByF~2go|p&)=4{&{75w6w$g0qFkm=wCK7K2P|!`my$tLo zlI||1L>fcY>#5oOk~ZDDVfk?@?xCVH#1Fz5bwLKcgOd*@E32JZh)9o$r1j1H`fC+5 zI$?*?wX7y}v!%Q#^f{y{ZWt7i*)>&P3gcyifuwGaKqI{)$DqO8kM8QvWy=UF@*HI=3*|KYGf zT#wp<$=Ku_5%&}N36slW-knZmdK?nF)H{NaK2%@r9V65Ct1n~BM<{OyK0`aJ+;b5-pDJ$1~h|rB0@MO$}hx9gsz;TZp9L?Db(@c+O23}+EiNz3?cBo z+=7Hb)os*leY?}VaO;)7sw@5kE2`?<^8luk?PfY@RoyA9wjB;3-Z6RHmEQ%?;x@tB zqq9{9n1Jk8>f)kDHEg}MwXagYohD)NBSIq$V@5!cVo04@S6!ASx9gU&V{-O|{;YZjfnbVq!(lR$ml8=#PlX{yB zHq{4zDqqPsE48B7%T(E)GNQu`c9Y-Nsrt@#o(lJ=By$7q$rqQFmntk##B?AGO?&xH zn6@_oIlPw=Uj24tM^^)^;ViqOoj|pS78m5OjaEOz3tk%a;#qNj-K5x7MNE_)?Ds5x z4@;+d#faZVx<7#jG}a=3RD)EFafq9KGYUF+?ZGhxFTRRACctO}O2`or9IW5)3S>ZIAnQ?pDENtH z(nF$WdnE~O9?`a!S$)7nHXujmfD^%(42Cecx*FlxUOBkEq7rPgKqfS>#>58$c+E^^~&&svIjiEZ85ENrN7(( zkBi-8q0B;q1{oeTvWc9LGQa<=Y1Rs0829N)nLYRO)=)PTI!^_P3&r--T;%Fmao|(GId+|I@_tiB4H@S=y1368003z?eRQMjwV@FEqHsrwR@{31iARxgc^r&mU3&x z7FTIvy**h;o%0C2!#J7T!mDb`J|E(cG?6#+f}n#tLD|Fhyl5CDfchM$RfHXMrQLDw zTTwEJ?k7HSf~+r^oxGZ(r#4s=A4VfzDmKeh7uX~e%%L-!1q*(Eu$uT|wvZ`B_uy{3 zOT=v>EA?qNKCEL5m%#jqNg>g~eUYnd+xsyg+GRp|YR54d;))CYl{UEc6E6v7h7Zc4q&y+r>5GI*}wU##K(4XZ|o6!R4 z35a4LG{aP&UwO{!yR+}?yct*#)Ayvhd+)8xXSU;taZhR|p!JfwiD@@Q8)8oNG>b&@N>h7_J?tfIMrc!)QvQuf3b~3~B{cGLZ zj z*@IIgaN^hzP`z)~JH85N6&3MY_VGp%-x|RET(7WP2@Tjh^8KN!^u>LBpXBh1hcp7n z7nyBw(I~2w=5XzyFO*PL*1ACr4#$#T(5TKS=97t&?moJBc=^B-!Y{gNfT&yB_$OuHSd_u(WiN^B&lb*I~dl- zOlkX%?Fv%FzmK(K53nYOZjNz*nC2ZX!-s4VolDs;W5d@o3FwEW(gCIo3YqY7aphUX z_MW>9p9&AP<*=a)Cd@U+(;p;&)rDPf1W)W`_G+6B57KaUu`o4s;d?SzSb+dmArCC3 zr#t|C))IG@kvU-HC3%KXda1iliva5c9_II9C!@`E^t!J!vIvF5S4&-;qMKQDF=Xo0<)H1oEd9n;$>jR^WH=hX8oWFL0{2l=}nj#1W|EXVvhn&JDO?x z&W~np+6e<-+ys9S>VfZ9bZ4n{O2_EwDoO`9(o?}RJ)eW6din7gu#i95N7_5Z&-)+X z^Arb!*E@%m^iHvex!p~P*>xA0 zJ~{5i*vq$#4^$)&txy8`SjXOGvNmRv0y746Am9tVHLMfniyn;LjS`lqNNa;#Bg2!x zDKX;)AT_h}4da8(hiBp8h3y%o)R$~MUiJ_u^X*!-suQoD@US{Lge4oF%t}D%vO``< zi!!r`jO#N%ERI2Lh`ze725OEmk>?$VX&@fO`lBn-Xq?L|WYKUsPL5>GrB2fD9+;=? zG#_Pye@b2eJ(_9cIh<*BsWFNy6&o}(VCTU2mmNLHp^^1hm zkyis}xFpn$>te*~48+eZPqu1Rz+m_?KqF1c%{Y!_*!aMgfG@lM)SRz3)PMTfUh%xQhjo&9%Ame9Pxu2YF47k^M_mZj zzTPBNgBKm*RwrSG)@e!BJ&KTU9Or=4OjH)L>Zj7q%dXiuYSLd}g4*RGiy({`+)7(J zgA?kEFCq;)!~~3$4Agl#U67Ko1g9jY)*NTa*A^(zv2gW_QUG*mLjTa;B`In~_+8cS{l>Qnk^;ELM z&vuLOVG8f$q#svcFkgs!wO>+!h~2J79aNkh*s{vME1my805d?$zl67}LXI@M7-`*D zNT#?*Ioe#v#zE@!7ufS~~rJ#;# zu%d#J%iD?w&En5IY)Ps9vpMD19oWk$s{x1i$JCvq)tM}sU<`fzw*Xx&iIaE>+YzuUCgEDcjyS2eEb-OAO&B<+&n3K}&$ zyywBz&Cl(rm}o!Xtv;$IW;|x!?1-iUc?*QL>i{tu;U5!s+hwBEqTv`!<1s`~>IX;z zK3oZU{`gtbkm_4fYB)xus}l)t{}SF$uh4y9@PLywSl@hW{i#(=lb`gc^%tg7mc#}& z5i1E7pg_2DHTVs|!o{I69#x6@i2xMv!ri{Wh1h4R7BJv0>1yhjo0Y`rYeebdE* zfG*se&T|-T?RN?TQEraupD92RdAy(qi|_9DtxPZ=;=~d&mhqwd9wi}vA}9*_k4T*~ zn7&|Vgq|w)=k*oi;vXBEcJ&CPV|{A=iWT7297GR#Phq^UjEOErP4JUjwFF#6OFAu_ zZTNBF;)jj_^Hneo4Mk-%X=J% zYp$ljK2lFaESQl9+7HZ?H9Rh|FqGsl{Pb?xEu91LeNkt_tnX9!b(K7!^;IVnfEl7~ z2%^EXM;5|C>mA;IFIpSYhN25EQbj0jGhPF$r%I?x^2z4_oBjKYr#?iC_rdp8X*f2=Re=i#7ht!T z2B*u>h^r^rvTbsKueM9OM;N;~Lea>r*bBdXLMF~ro!f|^54D{MRKYli+H*E~{Rn@> z->%B`CoNd8SJZ@)MPO5mG z`0XY~-5uzKDSxp@Ph=!RCJl|eUF5og^)$JwRPr<^t1JvVBtfi`zw1fMX@^Xdv#CygLo!O#pt20l9x4{d!{K&K*U0G|E;{ydBo}o-Vk67Z9 z=<}#v1aERt31HXPs)bLzahD7i3EBQ>#P5cH$OQR|N6jNX4%X+=dPg(3OaDP*-f{ie z=vZfq;OI$V*XR@aZ)plmF<-xXPZi8{qcF(G7dR^$S3sz=e7S=_v{CibKHGKU(3wn{ zD8U5+#0et_IN$#taR+FH??Fhf(zk02Q>bsqZmR%)+5~cv>HZTkEg#xLyWu5^n-e~Z z{<6B@gjc7*h2!ZO=_ufM1Ha~}ND-y--|ukU11$S0zEGQSD3xaCk4ai|@~((aU0(Tr zMTluj4!Z}Nn6E_4Yx3*yhrS+;RkbeV$3zj(NIS)TbtqPqhp780QZ28pz<>lfn1&!_ z3wvjGjmt`+6X@;o23znb+z2D zS81Iv`kIL*{>!k+<2eNX1SQ#QJ_~ZfAhD|BQjv%~EP*P#A0!w3JM=k}r6C~EN5;H9 zq5ev)ON7x7GM4ulm7{iXnmGV3Zx!T-%J54OB=cup)rb(9&b{2pB{jv!dZ<@HX^D3F z;YsDL{7j4JI&PAp4XgCiqYN4AIMgKk*#Vuv*Gc1_iF8_OY)QiLD8#+qYYJqd+a-2W zVGNBpyyu1$16Ob08{r|_xPgxgz_@F0o`q~_OUo@aRaP)wtceq)l=Sxoq#IbAH!lTZrWQ8EFvc0;xFr7WgDI}_^j$1tl=;}A_3a_km| z|6p%N{AWjSOVw2Kwt<*8UCg9lUVYw9sy8aJ#%79c{AGql3Eu8MqclV7O{o(g| ziW1bZX)h&6E{i;tJ@vh?7(!|*rTj@%W*DVO(i9sz@g>behgFm`|9)exe_#>!jA!-Z zebg2Et!wpH&b0U-++`(S%c9*mH@Yka)bJBABEiM`BD2eTgfYQV zK-2@a5P>bvOgyRKlUR=)Fd1yy8(koMdi+aKFByKXVCANgx3UtZ`*UgPmU+=6&5ZC| z)igJ^K-TIU)~c6$`lOw$T>NQ~41!82=SlO6`*Ns#GAXlecF#&Ml?dUyr)RXi3PGcF zo+U?JM$ijY>^_yrf43)bkvLm0+peDP^Y9ihn3gWH1)hLbwm}qBw+oY}2u(x663>lW z_Tz%hj7|y78V(Xk0}io!5J7z?OcS?{^LH!@lzr=g3YPg zfqcJ6$2d;>TLg{CtF6!)yT-mP=%8v@mE45n&?oI`A6oJFN9xcT&{>(Ta3{Uz`yc_x z!P(nORT|IP;slz^H`06o~Pv)L8MX4x~}-FqO{tO=q+#Dy2R1ipnqQ%3v$F@7xs zdm*QX1f5gZ7F)%3aQ5gMJ46)(C+!0VRT~BBAs2j?v@p%{a~!rTL!7Kzdp{0}2oZq# z1ws&y!4FGx6m#h2VV5!-3d<0~hzAPyUYzy`ws9$HhD2R+|RT)boP=JM0NQ zDy|bO5^`W3ADHt2;8!n*?b4&SAIIDb!tcHpp^gOftmu&<>kI>~4kRaGL17}q>a-Us zi!st$u_!;ou@jOZig%W4#URSYX=1{hSo-5Ml>PGYJ?J%GR}qQOSb@ly!B-;$*cB58 zY5@#+YDsn1t{Y~O8(hpzLH2yBwaLzneMcvz_4z_*d`Jd@Y@hsqbomi;49yc$<8bmF$%fNwp5-&~%3|)tt9Dpy z^}Xj<%opCVqIjR~k5+HL4j#M}Vyo|glcank%c7@lJUaw(*l*c&b?0mf!)mJm%c*i3 z=H(QUd*Ohr+b$yiL~uWmpkpNX4$Y)OZz-)_fmQb3H5Q56PkkR(BC%D-txnwG1L#2W zxVz1;b(r8w)9yDd{rt4Zp@wtZ>e~LUl~LU-&P=bX1;Gfv&B;}p2dNm&|8P_h-NucI zHI~M5-%z7EM-=eGNN>$u6foV5?@^+5U1Ci2M|mw`_Z$J{M2nhhNk6i6=Aq=@85&!d zX!BgOW-{XO1gBgkhP?NE-0u^CpdK3@@(Wje`{VkkMG(&P#V@;WHT7N{ZDH02#$Zd@ z-Kf^9x9W2?B_87_YLjC>yH?2Vh&B7g*=LTHagAx7 zt0VKcK4z+smtho;sm>l^{brwOSPZ8T(iO8RLS}nak6*pPlQ5l|Mw+VAanoCP=UtO6 zDqAoABIpDO^Nt7q>!{&Xst-AhN&$U(x7;4*TC$!k`GTR%{y~ zr*NqAT>AP3fJ*hC+UY^7Br4+1e@|05&VcDUwgODW(7Yb|>YF(Qtk*8pIJZ?@g~VZ% zX>nm6;P!J+(6GCct3FrmU-L+{R&CUp**n6Y<)N5OD)fK(^;tGwZQj`@E>Zdog zZAXqAChcR}7cp(FFGx)e#MeXvrs(69PLDT62!cOwpkTb=-6$X@R>BrwT;Z4On!&s^ z2}6n5H~UuTjg{_u%Y|SDy}ap>f~0zk7hw0xIv?YBTL-rh%QAV^(SqfAjA&%+uy-Hm zOg6iO3)#~*!xtWTM>baE{sFAa5Ot5Apfmhswq{7UB$g}mDYG5fNr;L{f2+v0F()sRzf&5oHxrtx0r0_i?6kgCN&iF$4=Xm z6_6(ol%HUOVdXZ=a8#9_Y5#WZe>+Ir^_6cHW6u47P5ukyI%1A7Z#!?tTwbpEacRg! zc@DoqB&Ad+=&FfU4YS`mL^KvpR&E%;8wcDdWDFW#tp2v4Hb_Qqg4~YG3!gVdn-v$n#p;0R%l2#?od~Ah!5I)~JF%!=k>YTM-)j?2mkI2;y$DXG7tn3y` zyW_nNv@Tt9Z2cf=`EQs$uGB_xafvtzC%S}OT8VSoi4HrW_S=9koCzpsxy*)SXeGx` zU>|)LwS|Qx_G=^6!8|+gvg#?CjQsQg!Mz$doQ`v1#Ovb}NdDvrnS-Uw3F4_{?K#1k z_Jff+i>vSRYb!*WNJ?sxk#Xm8frQ03!xPf&tF$kud(K__gNm7&$idt8`g1Dk?`a>v z8#yG5Wk$%}IWR~>Q+Q5Atvs#dSab82r^Ltz%$%*tK&ND9J3es%muD%uy;GgXet#Y; zJ#2lW$xQGUtK6MDn83Ful`7nQdQ13)^4{qFvCG~T0(s=iU|E*|SeRWMn+~>hY7!%p zxVhB6<+XQGMpU;B1T_NzuzKEdC`Tqh;bjgSQFrMgJ4fOdqxe2CWqW6|VxfM3FI=}g zs}*RzLoU&-J;w*f_o@jp2cz_pLEV)F58?@R7Nomae-4Gx{le^qjn`rw{ShWbO|vAk z%hhn`Pj?J!$xjWyT=3o9bN+E`I7WfhXx0r3g2FTX*~E6g(IP0wO*l20k_y~JuJJlo zH(_n?MU4fD?>kc%Wqfw%7(j6gY2yR*wsR+dS6;8bDIF&a7I{&IcV zuT6&vkfdx1=%_OH-N<3^TivjY4z7bkpje5N^ZEDn8|OJ8Kw55f*e1h6h0dT9OvYL9 zNZL}3Vd)v_sWpGj_jk?VuKM_D7WSp@!xSl@UNG3N-lCvftR&^JtH-#k(&QA#>ZyM^ z*a8p03olpe&;NTen`baC%xUcZJLrfM0D{Sp+;phxC1fEDdI z*o>;8@00=!@8bNV<<-W_G^I;g54Gj3(FJg*iVK;6?JZ$0X8apnqys}^)z`XU^%$VrcM)I~WV1(rOxOz+al41rH3dT32_F@|C-1%Gos&Yqy|s@&UC z;p(DE0Z2_>rXkKe&1xAEOuEP~wZgm88A>Yv0TIB2_4x`~mNRswK3gAl!H}Lp^Hl0! z*uZz%ZP@YP(zgClIjeP=i#e5pU`%t;U_cS4c(asgt9`IYV*@pu*v;ucg#Jmxck0A+ z9u&gqT7u`GCD}NM5ub-{9r4^{bG~fyg<+CocEmd4hVru7kU+8Y*X?e4Zn143v$sSInUVu1;#LX@C zmZ2f7|0mfa@uef%hFvFS%9=mR?aR4e?<1=ldAE6lTD_`fJPiki^0{#~!XaNE8-}Ul zZ#Rv$ie$`#!!UPCYFkOzab*GL!!LbNnE-YFSfsx%D>VMI5l>oiE0C(pX$lQmXctOuvhEcq35WS)bs zTc%4syJD#oO4`I|1u!A=o&a?n%fOejUA=rK`9(z+{OXS@vz zjdN7mgb-K%2%GjhEf{D()PeHYC_oHqQq@do_P*;}u;?Sd`KJ1zw5#?Fo|z-fID=|fhg?KZ5k$t?zJ5(Yt27%8(w!d zRz2SRul1r7onIT6Mhg6wrVZK_xG*Wx;v6Fm6CvI->q;>ZFuuP-2$cW;03t++RzO;k zBdEjHSe*nd`sIL&T<*%nmHq^OVJ&_pdr1Y3H;^EF#Axns1d?>d)U*FK59{?wL zev2Sug4sP{n|^=%3INM?Ru2Urm&nPqL$5AmggtD-t^M_Nx~_SitO5&*S5o%Io3~n3 zyJDk}f~S>DTn0KYg)zWj@tSg?V`3umrq=!^m&Zqmg49#D6_V6BObVgg9qG7t64 zL|ifK$wX0K!3e7s?%y#|H{SXxf7B_mCqK z1lV`~G;0c_a}cmYV%tnhfQY=swK$Qb<^^riG~NZUZoIiq7j4Op5qCx^~T=SKa&4c5MYAxr@xh88AD5 zUWR!z;-$9_9tbKsOv;E49zZiZ?MMEqvii&Itf&hgORbFpR=Ijav70}v3>)x+`wIyX7bG=S!u3!8Y7xXP zsVYh!vy~sAZxB1$*a&ChIoLPw?zLVr^Wg1a+}p9F z2W!x$Yc$!dwCE(E5)3PlQ@8EK{JRT!*V&QwNlx>oFVg>i$dgevXQp5c3^?p`F8?fT zbXHP62(Y}&rFy9Tywc?jJxli=vbdsf5-sAA&hg4rDyTD*GAe;4Rm&B@rr(=Co0BB z;dQ*>%iMJ1$}WVJLwyZH$s&D+Ggyyc0q94ZA`(PM&vF|l5M~FAYJ=!_@as)}Md24u zm#*WGerHL?e={lSb(EO|>(U1LY#VYl8w2o#cb2Mn-R-+c)A`N=7HVa`Tp_XB$i6QM&d8FY37wZEn+!+j_&)y zZCH&xO9tTJ`Du%V`^CsLc|`CT*e1W^XV$%!Ik`JM3w>Ehj0Si zEwj|7;~OgIgRxb`1~1Yd)BVKBhWANYNo8Q@_5}zDmxAjhxO}T;wN%=E`a5<#H&;+C z;mq6v23cWq5K6YcMB2Z$^nw(C=lLYz|34Qd&f%xfqV9!hDJZ1y+?{Z{ixw_;uFjJA zhf7S*Ao_Lyo%8=@t={qeKu15HN}@P@V=l+y6W7Hz>&CQhoWlEt3AigaaoI3Bp%ndi zQ>`YIgCW5^!g&>jCtJ7O{8GtXefB z64&YVA7-LI`=7m5P}zv8gA0+9@mu&YPz4vvFzxKlfM>ng9+!Sg{DsWTS<-3>NH9NB4)pkMC=^e#k<=j9P@wIv;&Z za<|=@$2vSbtbxf;zqz8{EA55~8*im?FXYrY1nkBm;naXlR?~D$DJhbUU@kMlX1)A0 z25!f@0B87vf zIVxx)g$(gUtU$b-1?^lLK88Q{9c^>0Pxl%dF?nV5({G6pxvPK3gF9$jBud z5~&TX9{r=#6szkW(}q7WYk+~49brKtcal;9%E>E?FOEDE{|u#<+Gy*r z@z5c>kUsChNy-os$nwT_2{SBd$|yqZMObyvHoJ+2wWc&nhF9m}Nia< zuyB)2FWSmPE*!%HuB@$J8VBM z$nPK16WCNR!JNG9G=V5Fe!=4}-rJPH#J`Uac)&I2m>*VIX|_(X|24r`lhx>|-+d>7 zr+4aAF)_3Z<`a#rcu6AA(&kuw$_WU`iS9-*lg>-q-oWqU3A+Y3xC%V`gd0Ou*L74X zU5tF__ropVwPYQ+(5F46RtW{4dV)ndkbvZrU?3|ZYM{)|Jr`jdar~mV;ufZ=jO|}t zHsP9(#iQksqk``T5{_wF@_}F|dm&>vf~{a|$?<0-bjycTRt*h=QERjQAikec+(c3I z&;Ly_gN?T#mtluKA^{5Ivb8h(?!>jEzoTJUYl5IgN8|7hPjGbJnx>rtrSfd60Om3zEDWnX?B|$-s2m6`Q4V*fq(ga335YqT zzKZ+?eQoEns>9nFU_G~a4+l?q?n>_*`L}g;TI7lW4ls7yo5e2h0Bl~?FphkB@iLF3 z3kh$FvJaa$!;{79S$g%NxUzmx|yZ|9t=f++pv2V&nZ@&(XU-0lyJ2yPyvV!L@0-y zC{a#V*(s`W#{EYmT`f?bpv88uCs7;H&_S|~H5e7SxtR0USk+xHsGM|7&IEl!FKg)8 zkB+kc7_Lks69JcYmHisR)@PCo-hrn>J;vbPOJ7$CwEWssV4R(~L^XyA92Tp$$}K|qcQv?C+@ExuZe zemvnK7H5ZfP(pm4Pr>;xw!U{l9WsiFQCWagZV(j7%8aSZ#9$|6K|RA6jz1yuhNm_q#3kwqGMCU!njiR*oxU$D5(_nZ*Rf$B{QqNu4$u(uhzCFr-nM zn$b4Nh&7Dr^%C4>^g+9M(i$sV0CN(otm(NmqF{ui$jDJu3kK8fbRGEZT-+K}tLp|7 zVmMJYe7V2#_0{f{lrP}+(ED8@Aw^tV9946 zj&2@~quT8}D$>kYMAF2XDaigNf_S~ONiuiMs|+w>Lj2u7LSU3cCp9OG8%&*;&y2uRz`e4EwbC_9_1h|%fxvV z)h*tPyTLgBUd;ap`YQl}tWc?^N@KkQ?zE=fMT`G`kD`q^day}5m1>W02U*>*UR*COS>JB~o0iEI6>Qr9cT8rCMyr-w73RKsIjHp)5X%AnVW z>gnG+XZoF+Ytg2rFdJ%%Qq&2c5+qUAW-7EP)mnadyeA2+v$f>qbU0o>)( zx0<6h%%%aIpN0vrQM(um6@^4`BH~2&mYja~0i4C0{WT~pDYOf8D*^YJJ?PY>^Mlo+ z81hl6E-#-m1*&46x9KULJrqSaJ*Lw}ERyr&%`^-r}Qe{vW+}SOoq&gHSFi z!;g3Fr=O>@vW?WXUX=D$>#uPHKVODSacu6!eb#Jl@Ttd+VFkCdgJwI}sRvIB5ss>Q zMX}=gh)dZ_Hh7281MLc*xtCu6$jUCD3T!Q9jXM!?oP#KQzK|$d`m<4mOvlK9sQ{ZJ zkSv}9*s6fpCBrF75pIA=*tZI3VUNGM!;Dh8RCZ9pIRp3pA`Ebaj>}>5k$o;*c6{U2 zyNYzLD58Jm?3bIXa?eWtH88yQm495m=fRP3#9>Hnkm$@cw5V5UCtf&mA(tvZgFh*% zDMu=e(0iVCj3W#gCq+R)r{82Qmy{BR;{xSuVb3^JG_bgPcf{MBkkiAZKEBrYUp^6z zU-h1?@cGbw2t)3>?FQZ*=-w`EO`g)l^#?;tq3ST_zAiX7uYu(403jf`0Vx{Hx?uom z4c^4Zn5X4CAw`wbrWh0zzy9pixG@yukm$Syp3;01_;`&vfHYqGhKPqU9oXyEf6`?j z%Uv3I3f=FCou(@}c#ErpSrPTrEIz%hZh~Nf%_c_a3LaT&%!ZO#`6S+qN(`axoj_{E z;|J@y4xKZ(>h$(3o1`m-xmp8j{F6kEu+xvpMNM+|Jn_UaZ@T|6($`E*1rRjqIL-cE zNhg0E`j#j&Hb>3u|8MeRH@N`he7JuN9}U$*eYR&+Ra6`75l&m0&;{^$3KwXIRerW> znJs6nRe7*u)Xk{+V5CcKOhBFV;_jC)x(_F`AswxD3DLL&nBGoEO`eJs!?5cW?2rmz z-*>lYhXz77Cvet<9b6<oge8#tdwMF0}@;jC`^$m9qHdbCy$h{ehjZj)X}~`tQXG zYuTA)BCEG!gBTV60tO#~gw`LGd1&KJ`P&j;_(P-JbPo~phOmR!+vzk5j!y-vDeb!h zv=nkyT3(B;soj~642>FfPKm1VU3q*=MhK?7->D_Rw5%Wx4R?0H&_RPTP?2^zR7f(A z=zpcRwwgTB|0$usVFHYyp!a=S!!5ChO+>?+$LaPYS?;l}uItL+t!!yuY$1kJ?CrNH z4+)@m+>1M_k9|Lky61PQz5W7UAsyrowJM?CrIwGwc11U3Kn}!Mm(-Fg*L24J^J2&79Ur3@rRuox*_loWcx0wW!rYV(-@)V$ySFAin_PW8 zA`So{i3@z2p6ZHoCl@NTRcLx~Jjvx1A7I89v?*%vfxI>(3OC1#Rb6d_Z0T_Cm`A%i+5c}Q0hj*WVRz_K=&&Avv~ndykthlTJ&~!s z@Lu_K8)#!-L)o?)?sHB<`L>0ilIy(OYuDlak`-ti$z|-$l@Ji7MuJ@2peBYJ_u8LC z+kT(~JuTlt=F}qORao6L)6Eb|q0~-_Q3R>lL{rPin8xdl}}Rh%=9%E30-Zon#KNb7GSATd}*BUr$VmN zgAkV>Q*|m+`~F}|kv{Ir1RgJp@7MHdH-;&8@31<*gvJk57W0rF$~YXY(3>;nVK<%) zMYvK_HLgGLT@a{-`oM2)o!sl#dNg5&%5eSZlR|4`k2T5t%ScD(20zy%?QSK6bVKnY zLd)$vReV%ZAM;Z*TU16ew-b`Zzc>H`7#C-C4k@RO*BitGrz4yl-GEbL=3T)D^hm+> zf0kvv=|z#6)W9fbHfXX8sTW6(>G%HdDq)r%;%@%^i1!p0-AON;B$#i*5wD`>#G!57 zjK(n1;<5H*nL_w6lGt>ONl5Of#|7CGP|OIv3_VMt2YIuGDop*t$jTuS zb0zG$LO>7u5s0~tH+)i3lMaD~B=79&RU1@_;#A;>ixJ5k#4Y4C(>(KR%7m=EotK55 zz5F#k9S9f`7xzsr)MfP|9O~YVO(aj*6KvcabCg+(Pp?4 zF2a|)%|C!>k5C*oyhgE-76Rw_*<-4|s-?WXO)g>Wx^-hAhl9i%gT#T|&;>Ex2N&yz z=A!14FSA*8E(axRD5D_~NRNGqlW>yThnR?Uan(oa45OCJtjKF&m*_yLj8XIL8U(sj z6pGd54*PtxO;}kmNj?HI1_(7D3(Ru|HA?p<=p=K=ccDJn#u<)aAA%^p|6)f)uF8ct z)f*a&k{n&RMHWem?>m$Lr>HS7#c-!KP`cSVa>^=@D_-E?9$wJ!Y{5E3`Eo$ThTNx*|c!3PB#FHY_53u6;JsBanmFS(*l7v>(;9 zRyjGz#{h1Yqkgk)`uere(}Fhrf?U6no=o@6q*AXSA12Ayc>!H7;E?UT`u388Zsc13 zGyF_pMbNM%07WIxtXUkxkU-^&_Lig(xnoL6RfoNCI-WKzX%F8SJ0-)i14niv`$Xpg|`1)YIp%&^;-!=2Nu9E*%cw;QHPEFt@m zm+0cu>GdI^GLzz&q8m^V6}*5G-YZ5#c6t)hWZ|!icig&e-y*B@kB_`68WR0}=;FV? zm(f{?UoJQN_+fl>O7-52R)5F>aRiE$+j3_roOVp}Ovo&ZyM9cAjVDlwIK;1|8cl$6sj(_+&uZZee#}KqJ2$f={6&wzgI5#|lHM$(s zFg4l{RlFn9rzgXHFi9xbTEMNn4_adi?4GJ&;25GvAU0tnkt0Ge_d&yfGL}R?@&dLn zd-Yc0mdfauEbLFaE&g{xX%}QhfF_~WV)kb?{@&?aH3KKV4(jdp^{7k}mxqQT9k@+=Ay9m`%E?&YvIxbR+N18B1u_h^tPU7RVebLqnP(!ARj zd6pE{c-MCY3amJ)TC)r9)$udvO?!yy*rL#p%gZ7Z<*d8(fY-=+)eD@NU_jux4h1|U z*ngb5hwn^p> z8hZuG1;613u^&)->@-wwD;l#1HdsxYut2E1Zt8$`Q+( zf4SLue(#Lx=@D^Owea}Mo+~9)7WkyclQ@feR#gz$@-ryN^>(zB0y}7kLFhu*X!MnU zm3c3c4ZagwPB-y>(iN10kfQrxPWt5Hfie4uvglfAPl#_Ec5`9N-Y&2>3oC{k(3g&S zW;57Ax@j{Nc`Z9hdKlp>hcBB^+7uoI#IzD)X9UDBEy<%j&ZdLTs^-NI_+g4)^ZCsk zJLChO2c9!BYRkG7K0^4rtgImtlFA)60)&%XmM;x>B5W&?@lCNrl(#joE+sHD1C z;${i+ePa6;!~z^|8C9d*6*wNI3G?djIY)(dc8CNpB)}uw(Ozx1)X{(A_V2&#-COGE z)As7VKW^@R-NwGImoKYZ@V>2s{kui*JNsevy^{37s#1Rhfw&XOlY=G z(6$ZmtOb)b{hV}02YTzsMPS*CRUA3jtyH|k zP++(!E8;i*dHA6@g+rK{*6`V80ZORa?RVgE<-%ovxobZ37={lnZWw@;)Z zVoG6o;-DjHbIF$fVK|U|)L`hC@}m$Kiij%47I$4Y+et}6^QmhxiO-o%srH& z;NO6zt3nNZWhn-P%z|a}H-b{GcQS+ODLw(HqfkSlv1!S?wJS9N(8%)4GOD#^$vmRZ8J8Vv_tu3n&3*>!# ze{iz+{bJ4frEwrTnSLw2T;L?hZFJFyp#X#05F|%{IYg$35Rf160<_5>QV4C`mVjOa z{WBp~xw$k@HdEVF06IVj^+0Yi(I1j!*>Wlf^iBTMTQZ(JQ5f!3%L()yfMHBO#!IJ7 zF~C|im2r-!AjmG?@zgESaF02hUsLhyHG<<_VNZ>{A^~FGP)-p-&Y`ot{g};Y_%M6_ zei7-{f`-Zzh!jMt*P=}dI-SobV(F{q;*qAPT~parEN zlRsDZDS%`-jm^c*E|#V?2w@WW4a^uuH-rdYn%aQFtZ+;fm-dAOL3LI!qA>!k3rXA^ zez%byWT0f3j;+lVOfAmBkya_W%{6P75|;t2Yk)Gd=bPFbW)2*mbzEM5KFZ!OYo_@0 z{64>cR$uwweR`+G7iX&!ZQF1$>KdZsMdinee-@JYH=8-OjKBIz^F5)}kBNaF@WrZd z?(|~zX=hwmM{}$2qv3SP1Njb~hladleteIf3dsl0gObT3n)=yt(P`&mx$t zBFfa!5#kVTS!<#!=*T7lP-X!w&Ee3EZDNjFeZK*a7l3LVOlq2gW#;H3>(Ycd;HmHy z=(`ay18@5{2WAR3A1#d-(ec2l1V=I?Nau}lUu&C;x?lWxG#H5&=|FLnfNnv_`yPXZ z-_0gElWB;TH%^0ZJoQxV04-)n*_1`d$dKcV@!r?_KHz&hdr_^h2i_el;l@LMueCx4 zdt}u(j0y!Wuw%*e`hcBgjzajeTh;57!rzIA=nI2p0c7zs_7wE+1p-32ep1{(7VHSQ z+C@sJa-?P=f+g8tFX1k@%Z|h$MdP$_HdnUzW`7~8Ai9dG(GjB5{WP++@0p}daY;Nh zlk;_Yok6Q!h{bRcq*tiPjsq4LQD7GKyq)L^3ro6{Klp>2RLxj3E`R253odL_VW9rZ z*@b06F~nNfq#r8>;yl~T-8fUIaDxp9^c%gEG8?;B-D&kZDeK)s8{trK(Mi@Kze(6A zVApgg8bg_G+`3JSFc5Zhm8<1S!ZM$n<~Jpv*7}0CPs6cIH~idNFO%5pEfp-H=aX<=|N-=UVWcGlq=+MiB;Vk5hT6i!dMY*dBjk{_BiUqGz*5W7rT2 z#%m;t@yUA-jQe&n%pdQ2#=D2LK~A$KMWVdht}$m_74j8z(>rKylV3L>e|^DnKvL13 z!sU$1R0XBM;TdJf6Zp(E3m?WMW+o=noN?@MY4}S!scBj!rrk~#R+Z4ZYuIK~f(aq> zEctPf!_M|GIy^_;&?2R2?9)0Zz|Wg`VRkCZ-DWiFM7@RRCIz6U5c$Q9Jcv~%7egoK z|59-jYEr?}^JU;Dwgy*!ADjzJnD&s87(|t-$=JEk3m3BCq!*2NT)QWyU$5JmiWV?2 z^G)~>bNM?CDUq}KbOr{6=?8!WynJA+SW2-I^5%RrfJZXRrdr&3prKGt3gE9tk{Mp{ zkfC2f54ZcP4EzWWx8MQ03|T|0Tiq}wWtP8_Xbg9j0+GL3HPnkkm7CXGPMgtw=CeJl zMjF8|o!(_#tWm|OriRj3yOkcD~p0^>tX?Wk+Ur`G~uee?-tEF#KSNL}3^dsl5^!ZFzeu ztZ%H&rGk8tIGC7uAs@bclEUI942Q05s%?WKLcloJz5qz3kji?;q@R618)VKHRRN=ar6X+n z;n_~t*Fq*18K@eJY4j=DDWQ-O)7;Vg_=&-wMuq+I60oDDDJv^>w85jAjaeKb##VlB z>CquB#`Uvn&Zt2yyqu9Yo#n3%Ukr*K9#oWra;(9)0M8WDC#dl~-$IEanix;z^vl>O z{h?Qa^o)dCQym$^Ln^rw`e3h6_(g4lo58aIDUcflZ-LXwECz_hc(590FzGa7wi*}$ zi7<}i7q;ZSI;CkL*@&M*=(B`o5Cn#L+3Bu0wr-N{CE%%xj#6!np2|!h5!|VAWveIr z=f`;u;=THvzota>d%#D#7PGj#q9^ipU7ZFI50i&xY0*9d?4 z*3K*BJUbG-n9KTs@V`r@phgJ_wO!Z7LS}JGYC-sR3Z`W}0Y!iun>g)wn+B;^GUTkW z#myV(*Suu5`Qa4D{Udcxts~)_2LCSJsT{@7p=Y62k10hN!R9)J%azZlx0VP6b!GE% za#SD&gS%78066bEne(V$^;F8hU(*76XhU!X{L0--=6Z&6CE zgQucB-Gn`l9ymh21B^)njnQ()kC)*;=R^TMfZpU#rk*WqD+4=IhuN&{asgK zKqVuK%?crXO3NLs*_2}Wt~1CPQgy;)9#vDB!hEM|tNO!M!hiIR`fxLtGtVs@I3&*PhJ5f0Tk)}E@X9aX)nRAvnu|hH7Q$et~2_dEoH={f8^ghpJY!J^zbPABx zY6ts3P)<2l;+h(p0CGVk*ebm9R^nnke`Q}kHJCBXJhF(kULJ~o8$!W+J7ph>S_;*lG4wQPP@uT6`CfLbID=$(Y@JEh_M zyGJK^+?2LQ5+Bh{RykCikTps*u826TiSZ{z{TwSPtEr%KBA~?j;)RwH-r`24OLKc{ z?Z~U)YB@OHVj3#}tF75umt$wr1D;*IP1Z;HCi>JH(2$mIRjJt$)~a%}pp@CWH~>Tj zyD;FaqnT=gI5StZhoXAWm(NN4uBH0_AzoLzV4VpV7}n)Zmi~wSKtyAG2#EtiDh9g; z+0|Okbjaj>ty*bKx;GeTCBrOiQu}3Bg%E}EczW1E|lV?G?pi5204EW~@V4vg0k_$wJqCoF$Z&*0C?@f)V zv#u=qx7NonaErd449%&s3*+yKvc_YC{bd7FU~`VG;&vhyBQRO0Cjw`;#K@=-NO_}x z6Hc6RsWHBbzZb=~2q3V-_91(m&0w(MR8i^6`9U-rQy5TsF%4XWUU)U@pcC!YH=R&d z$+T=Ld3iLz;WUSa`z~p>k6{gK6E?(pG##OY?c6BR#`S?-x79wgQ%k~r(E{AW;S;db zLB~TkGuODZG4Nk3?5B%+VbqfSt*)Gsj7XG&*pNozUyC)pMu| zB4oF_f0)K)Z$&k3V5_rjn>=4q3Sbz&sQIgckZlwl4}{rPQO{S`g}{SD=7wO&jCFyF71FyDD>gith_wbvn#Z z8M?fJ7$yH&$PAw=SMRNqD8>p$HvxEiVZ`*tuTq8MMqjB-+Sqhy#bRb#_3BzFncen0 zQoog+cBy4@>z0 z7ZL3inm{;i$6Sa7<4Ect=lZN}>c9Ox69D8$jGQ|c3fIQ(P%7+zkcv+8V8$Nj5KL3fxd+nG2L=hgDo@ z)f}8J*WivOt0)m(36jwKA?ijJP?&(LL9(uq2&=|)9P?v<%#Z#!v{Vq0l|RePe=XWM zn(m=@t1*8$(yzX=a`v#`;J=`=jE`D$tn<5LXdx%?5w7XoQqo^^h7bU(Md4Xm{ z_2iDyeLX{HmN&6O`$byx?d8Kk4vbl;L7oe!`L~`piB=m4-Cu4dC|j<7LpY~XQ&qND zO9s{dAkF0gU)r--N6rK-6;x;wuM3HgLUgze3!JPO50sLfV$|)ZdbJs?&g@cC7WZj@ z|Ei)2vlZ1eg_eG4sN${6BAXQ_GtZ{zKByLU_6b9jF;awBG5A>su2t>GYh$NQ= zs&n#ke!P0;{6Z%p&?W*)GqkD=pFcK)Hq(`-7a4BOECzccLwZ=fA{><^C}m($UjmD? zBK1H(V%B-{G=l3{4?Ytwz*v_Oq*w3z$*%cv$TV6J&)CS40HpcDMK#7M@ z>yy5Xzi*_bszvr4wdaXK;Hs*O-)yi-2OHR|`WxF~KMj7A&>iqpM)%^nwVZ}!RpIcn zd@DjW$I|i(^~I~~fh7>VTyD&oV+_A(t;j@Zcm%f;3Xt{9#b#1bU%uAy4BaVu62KK- zfg;Qq>gd{|but$c`Ie^6SihY~Mj)JY*|rf(oAf*S+|Qf+W8}^V=@j77IUE$ua!ymB zew42UsOhv{Iig>K?j{befUy9~{-gGFErQLGo+`~lAiCbDVmQ3{9^wRnN>`T@nItOj zR*f+AJ{~(pR)yOJ8BiJ~1o-O4D^x3&#AQQMM5_f0tCZu}U2=06#bbf%!3_rbZz)K( z1?K98b9v|szwCL0i$aZwIyb;uMc{*py#Np_^J%;W9jRKpR1spHI*DgqC0BV3 zDxNMCF=8{BO-`X8+u=($Vc3~Wt&jHAb1%z3;%aK7y3KrOq;;7{VI0{=N$RMv{xwRy=+$bQyd!bkoPx;<%0aHO7X0j_}0!+-RpRbxFRk&b@7#53%4lJ9XuJT{XlvvW+ItaL_w4u=v||5x7Ron>%{ssMNnlJ zwhQCM7g_^C_X%kO#Qx~LB)f@1+zJTolo2w@e3_wEnIY@Xc0}HOWLxxz+!VR4y~o@$ z=hcUQZ%XK~m@0Y_C{vtkREfy~8*rsGf}2efcovU1O4xP!DWjM^_7>zi+H4}rq%y=@ z%>wh5%^`5sMY$7;s!ZnEY0^J9o%y-*6S2JGu`Z`dXQ!QKC@+WEF>W7*s_w5** zFLKq7&i!G^D`sJm(TirZI~TDo#nB#UF5+ae@pVAX(HI%WksEWRx+nZ}2l;>w(ze96 zCAkfG%nJt}w;$Wp=zJ)vqT zy_G;%xt1ndf^h2xJ+=)bNjr1tAF{eNruqgv-A)QA(5zdY3iC{f=2UN?m)Sjx8fbzn9Q7RNc%+n0b z8i2$aZ^@U!Ws1vq+{U{ua@BmBd{By$~6i3XPMddLzpS);Qr?>(}!Dk!L`S&uz zv!p{eCUPn9#urP|p!IhbBKs5KtH113AeJdSf`hhklF`IAN0wKu)yv`nXZ)7>JT_(p z>N|abV~CK<uZwnw@d%tCYZXa{}C3tX%nSyl6ClMCBK^I-z?y76AC!B zpVg3t<;39FghjLvGkk2wQgH(}p8NM#OMdJ^X#DY_l(5zB`v`+N)&1kvkd_*AKudSj z>!WL{pneyC8=H11r-w+IMHc()I3UgMp*~|5Gphnvb1+wZ59F7K@3meWs}IuxB)P{X zFj&@kdmo9dW)|u5w}1>(!XIG4hHYhxYm>$_3q{j2XS=c2Q2u(b@3 zWc}+mZ;oQIB@E#VS@iavt0kzFY>EhRnqku0A*f4Bbowh~DPXDmOg4VUn`IuL)5)z8 zo%0Xe5y6TY=)t_2Lr0U^p2xA_L?N3Z4lNa9``(7gvK18m5TGn_z)p zFPvnxdhWh8&o8Rw>1r_Nutmu|DY*l2Rpu%6zd{Rb5Q+5;QlfgfmpJB1btr~R=V5$uVKDa;rNg%?{H0ekxie#VdqQ=eJ1$!D zQYpNgM3-^UGyz6i$w!@G(1@!L;)D{K{)R9|2jh$@E)6pnco5d;AUA&&-=Y(9^fI6{ zh-H9{nP#c4rOwB2(fZX@vfUo2ufKLT+Q}^fkc|b^P-+0AG zoFgVo$+)kHd@QPTzKgKv%&o4Oimk<5WzHNJii&fsrW*wX8l}y=SQi_APg3+6V{}I{ zBgNL!E0H)rFzU-@J%-+LQZD>scpbSwQ9?1FO!|OUx(Zil_=PWceK*yh;)ooJ1|KH- zI2)dg6w$P8C1P6EkPr!dKi5<5Vk#eUP;k6z8!?+-6XYmN(%@ni^}-cX5U1;k8=)Gd z{qPT?3@iMb7Q^y=!{UW~4jU?_wNEyCR5fr9ds*V$S) z?LCdPm4|b|hcv%*VXNOuF}%go;wg>e?>>A6ca8WIk5D0q4x^44nsO*CF3t47zZb4C zAAIKNM+cLhk8{#Y{$RksWaw276TqJto}t$)&0o`6dJ;}p+jUGlFucqnOTRcI%JH?p zq}rNdU{1)Yyts=tqt{=)O^}BKj8#Nd?s8U#uB8$Y`jo2JpQ-B)EBQkoSxdGpNHJOo z>><8KIZ|1hn~%62j7XOn@s!B7dAupV+nq zJ%tE$wJuJ#m*DZN4a%mkXTFAkv*aKSnx&#(@;wLvy;0*;aaW7$;_5}3!h6~8KdrET z2#YH%)#AygN5Mooa{^wuj5U;Hg62t9LC-~T7B>IzGS;LR@*?Hy5~5fr^(Ge=ow>!b zWc#;C5|S?8!r7Ekjg@xRfAh6Q$xtmN-iCYX5WOSG)g9eA&ULTZXt<3N?A$DV$cgA^ zvLzwr*+ppevl7^WZl-%;FMXWinaurN7MI@u-UkMdc)8Ih<vprcNsw zxAu<<2N*8gnLm15K~a<2rYg<f)g9@VC;;-9=lZc--&i%X%>Mt2W71Am<_oODf7_}>W*&PT%N zc^w!yEg6y1>|KD!H93Z|9@fu-QE=2X?hx3@bG%y|+(K#=uDuz0K=eHK`d`6;$@1;B z0}E>0by;8hMLZxwreg04Rs)l>UU=G(cIKNHvVM~*rha8DiA#QE4OJl@YzOv0mZSU3aK{KTkUBfoCY3*Gsv_;}OU-jPLs^KNTg=Y~ z;38+`)+afH7&#!E=N}7DSOxn#O2KHl12r@iNp;wnucko+$@*R9ma$NBF~Q+-z_@vq z_O{3-T@-!uOM>+QkIr)`xc65VYBG2oy+A& z2e;K4?tsoW_2s!JzMsf~nIZ>S68$|%Em7?;xt4X~$8U1YH|Z#ZQoi+>gR(yO^oAKb zO0tT{ymK&z>qKQX31nBonOHjNv~?FJTYZrwoLox*1M$TgXuL#qfgY%cICWd4QY(lL zgC+l)SvL^XCZw%NO~V>y#06oXQD~PeU?gf(I6~WYR`FH|R2b{Uardu7Xpm-b3~he3 zS|S$6m$2CV4R%rl0|B2y8eh+;9+~RiLkuiGioNJti5r@}EQ9%GBepEo)Q-pyv+?+) z_fc!`V`yY>yNqHwb&Vm}pqT%|)L6@uYU90kJr8)I~snnko&OjeGSxt}ZouXHmG|H+l z80iH5iDF-LtYdsUdYk|*MZ=chx(^Wv*73DSin#lLib+R5R}7p7Y!<=^iGqaFJ&r|& z#@UD!kf|I(K%*|2g}uB&(`>?un-_ut^j4h2a1^_oJGusWL$t&s_qG>&p9t=S3jjg2 zx*UxVdd!6p1`hj4)2>WTTBC|1z93H#b??9pt!}EAj_0y|ZB9=L6iuWCP4I{fSj61Z zaDozQ`u4T?_em^12uB}8TEy;Xx*u^|y_@VsyW3r?j0DzDVi-?Ft6T$EdqAy9{GA`o z%6(#kR+tL6OVGDd`jW$Fq3TXq%bb>tP`-rPF$s9!(QW}6+Y36^J=SR9e)S&N7OUF< zzl}*S#^Kt5(w3QCfNL#`DC_HgGF|l7qaB*0r;IH2S(Qkq|5Xb2!&#`?0*H&?9#$uS zmq)XpP_Rrd9?ZRdu7wU%^eqSK`Yr!X4*QT{hKXrbSfb1O>xn`bNyJI1lic^vokC9k z(GT$K+{5Ldrbey5%R`wBM2MW8)+-bAU@KZ=S>K_J+tmJfrAYf%bc?9pG7 z)MF+hygf8ZrO%aW=D0~%$Uv(Th&%H>Q;O@H>34}^R_Gr{EpUJCwv~7NXd50|wh0(? ztpo{XHAgJ`sX_cAutnnx;OTy7tw&qc(}WUJK6w5)U97PqT|<5PZ;z$`?KQPz6l@i7 zlySDmUn*z|V=O1OkEhr)wwrhN^yaVCazJ8k>%4)H75Pn)vVppN&)6s_2w`~w9|UcarG0(4va zx4`Z8fk)Q@nVO0F=AJ&^xDy>@KZx9{6B_BMluC4s{HJowp4J-x(v zc>7X^ymJZP$mW*=8#`gIzPDns^d%=$M_4K@^6rKLGxn7Nxe4XD{(Vi^FqIdl<3+n! zr1RpeDW7QY#voUJKKL!guBYz|btu>{2Jfm$&z@9?`$0cmob79SuUlLq%{Pe_H+@C; zqpV8SEzAyoU#;+KBAs4Z=3ktZEj1&)vhrOrDt;-+A>(TNj=hK4J-@9s`1|U&?forK zu+s3HJbj{RHjS-`qxsET5iyb?yxlbwcRSs);|+s64>JV%azzNJ-Q1_8Xc0OK2YPg} z?brkpPT$YEr7;610H8GRZ=pVnl>z|)EL1quuZ?2n;^|=Jz(nwC1N@&+{&%$ab zOq>7!fPT&24gwDTUl;&*V|yDX!2g&CzgHq-6H_w)kpK9A0RMF#=syv_0Kot80HvaT zr!)SM|4{^B`Y+V~neIOU|AP+#4hZ;v+m8|e%r6EI5EKLi0Psf#09imlLPFvHZ$Bmg z&;Wpf9+rkSmd-!%0RQz+fKoWWXk`FMK!E=ps0)As_}?Rc0YLu`0Q5fsfd3x=_`d^^ zcKyNu5OFU=PL*MIWVUkq$fe3?;AmwfMceU?gYEvk0@9`OY(msIg<}Qp5KLbu7%{$l zr8>E=GLLF=uz6g`w`hbyORhZMJiw8!ewZLh3I>*t=Hh7ZS8{|HX@RWc@F( zrO$I!G%z4jPkKlrB;h`G5z;uJ?Pa#9iUdy7odjXH$D@w_YZDvH>bTLN-JV{6{l?1*GIxbQosv%+9 zv#SQx;s+z5QPiZaUB%$7+_|I*2`40<9icDjCj{1w*e`9aY~d-AzB>^1Jkd@Tp3CvV zD!jG<>|7ivjt*0196*54IdHa>&$0sjE3?uBW^Y2`qxM zd|#cHy$GJq0?uKwH#a*EtaoGk8@mlN6Qbm3Fz=Q1B&3Q8+SaF$__dXZ@>l1JJ03%F z*VhC;`JzFXWA+X}e{;?3+aeE4UTyaP!No~;Vu`tP?|^6WIgc3CtUo-cjmj%@)}6i{g}<(J#UMs;&2l1i;gNcvtlip9eS z$056EH@Os9Q(4BMt8?hz8`KV8SoC!5=w09L-({GLG`K$-^|0qLauul$zaoM|777Sw zNvB-h;$zh6UV53=V&9ccItoEQk9?4bzl(?Q#Z!$nlvC* zk0QhQeL*c7kU)~tmYEd*kg- zYWJ;|l!C<=H)4y3KjKJIe_$kVE`{?doJgT<0a+ryR#=*dF1NKX!0ue{LY{9PzHhYT z-5|;+o>8#>w0*1aiv7!!mDtz0WrFO)81YafNExqwlkhiEMy#tcUt)AWd->H!I}L{&6UaY-eOaPdi$3hz+`S=03E8z9yB zEe2F2Ce+L`Tn%=H^ko}flQy0yevm9Y1uPVp$btWS)|a)IMF=Go@JfUN^l;2}6;~4? zm680``VPA9XC+^yIS5sdxyB z6!F*^ve28hT!Xa1k5Km+(8h&JDq0@(iWHO>hzXVpFro!4>>CDb8L#@`*L@@A=L&D$ zdDCY|BAa&(?-S)@jpI8Yl6y`B96^R^XOHbK4BACwc7A8TRuh5#Gn*UC&hw>&Z;g&L z7@IAy&TX)U9B*%{NslH(g*{VelfPETdKUOAr2Xyh9UzO@wt+_?hd7jh=qA-9s(Qvz zeph^JLb^yT>f9)THYDT=&sO;QBW{KNFI@CX+rrm6YC>Fxvi`^9+Lq^n{W2&|y?-Q# z;>>Esn|{#dCc>Y>oJ(#F3G)0RVDf9)7dwf|Z_k@BT`2__(Xwszej!33o!o2rZq>Yu z?-}Yv(<#QzK9^ong7YocTh4Q^$zU0=qsViIGMY!+90H7hf@N-9SmC7xMFFMjW`Q!s32?SJeQ7lfm&3ZBPB=nBk>{oT>=88Bv#2$euxZjiCWseVzW$6_n%wv+5}*}J$97B?Tg zz@kS~RAkT>;cgP82`*ZSGmNV4I=_gpxLY4!I=dK+UGX@W#PW5?4-?LqrYE4*eQMfE z|DMLrFGRCwYG$1Q$xQS}%pXC#j!7VK)@5clhmr4{kMEr!Di?~yMWBe%(RcY^d62IX3Uq05($>BP#6joss#0VP+Gy8`YFVQhCe;E`BIS2o)wWnkefVeLn9nwO=Q zBYPcfU=c$3y0Idrw?VByoJ=T}TwUt2pR=I*E{ENB3{RyTOE^Gd91m45d$7D0tf`CQ zetAHPL#hjet^h6Lq|e91`7-PtWX2?29yWeqCU`8B=nJD0?7hQWu~^npo4_vzALrc5 zBJs)!#wSfKs6N)!&$11);JC8K1U zN4Pq7V|LhMm9zr;21GU4C1n3UAgQ(@po&whMl&`|vL<3VQupR{o}MCpy!v}YP(B3e zQ=5;N24{=tzM=t+rH<&Krs!QbZcElYhbG9rkaav6Jt{UB*LoHmXm|BEyxVFVptPqi67!VKvtl8ol+kOM#zqSmq(FKb?rettcD4gisSazpAJNb7=ci5B$9@I&sjpL4caLKS9MvfqQz&jEC`! zfnEt9INXoz7_w*C+?SN{UzeTK;JDac-)T(1X^_`#0l|~tU+&da7mhpg+P~JNLsWXH z)F;3jxFAUx{zO(1Ff@46Q|{RgmWWx|n7FBT#;@Ys#q{)E_+^UhRi{&HAN|8|i1PA- z7oGHd###3V^UzK@3EMJ0>*Tubf_ACTv1U4}y<5Vrm|1LV$Xpp(;gi5)Af|cT#g_ z<7w4zszxNk4wvVEt~?N(nD7Y&MfaEdRF`1`IuzZX-xHj8-bA95As|+tp6hxIE_qpB z2`VB$QNKzt(#kgQ*nt2%#2~_(i4#-W{w}c6=KV+tf9hb8>M@q<%y%k;+l)K(^l5k~ z34CdV7rC~%p+e197f1ZCM}Rifkw@Fl)ZpW7G*NCcdq$=Zac-W_F6{1nCjDcd$ge3Y zigB33#RBkdcyZSaY?{#aBmd(@Fml8eNhM2PxWa*K=O2h0BGS@P(S)jw#!YCU@L8e# zn~TN}7G^@bK>i`quA(j$?fxzQs*saJo~(Yd$R1Mx;}=lk4@gjAe#xwS$cM2%KvM

    0PF$o+8F^pH#8D$TnX-A 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%0A9r1y;63S~znF;;( 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%0Do z64@?ySS#1H46Qg?=bQfQ?elxoMAGVE+Lo>><3%7R^Jj)5!a^F$3IlBRd%XDmVVb2F zd~b4=<-nrUQhlk_MTqd}?~nFO5`6f@AT45_SaYE;nM947dd_-=F_SMt$vMKXgr2}d z&2eSDOZ|8jizWnIN#sO-{%X2P?+ECqZ%I$pt6@i1T*pgH|CTsw&@o-glfCjz2k()z zwA;f|F9Idf*PRGCj05rnF0z0qbjik&G==1n^{yq4fLZ^X(t~A;$yxz3I=Ca&QUvY@ z0ws(ARr$XaAn(QNG+qIBEsh<8uO{N6OBU3drtKE*@km4dd=y(iIPk- zz!{==vuBlS7`OmMd{M&LBOo;xTJA&62vPu|3jWix>A`f-P*!>2AXW=bhSs{Qs}mB9 z=XXc&qv@YP#A~;#39okMs1CtTD@E3WkjuDPOaV`rgC{OjX@wqGGaepS-^etm`?2r# zI{}~DQ`K5=X8o#D2KPNtDi5N=Diif{V^Q*qFyy%l*#p0kIHsj^yRUj&6H>KyVa=~+ zr)P&=Ddj#Sf)=eDP`b6(gcY6Ww{ZB53oA3+b-Afecs1fLc{m`VSQH}Obj=Zbw3aUM zHf*hOe>!;}?WMDo=)f_-H#+3^nJ_-a@TKDNxe;%8r*dNU*<59Fa7#|W1ZbYIJ(ka! zK3NR;5r;rdgpHL1J6IJ>p-Pz!?o?@QKj0(gv~n<#awgiY>q*X~pu5UQ_IVp(Y z`oWGKZx7L$gRPY z?CusbFp#_cWC9t*J0(yT-S>%*sijdHI-+8a|8>AY-B(f{B<|( ze+K=Op`FEa({9E+B3yoD1mvwDiI3!ck<+WkfN0T(Knp`JzvHe%sAdAfn|GRc%|W4j+&)0@sRjFi#zN(XH3~B- zO|Up?SyO#u0lnlR@Ob$e{4_7kvju7r00ky(WjF{7e6FAf{B>jp?C(L@Abh4p%jS0M zfm2$Or?D=@y!+#Tgy*6p`v-Fxpr_oAt;D!hjy-U2Q=xcG*J{ zStjuqK)F@~F4>0MmjY@fR{g9tPd$tFhV1KG)s$_Eoh6Mu;FmZ?b4r4@|lVn!~ym^ywg8sK_QFHXpSQ*^pamLN;P3{ zC3dFKeD}t-risl}WRBP6HxBF@;%ZW6Oi1mspbJ>K-X-p_{Q1osxp^>)riU*0-!p`3vvVe(ADtR%p}S2OwF zYrx|^a_l9P)TjcO#zbFD>6co9L7ya&qd@vwCTFf2quyPJrmC;0@P0t{8Jxb=Kd=|B z^bPvd1WPAI#XQKf0AcruaN8m~j{nJjsMY0kfYA5L*fIq=C9f}po1f6I@qG-ZuIS37 z177VUilU1nGD;f%9vy1>KIZmQN%vpST?{bTa z12A8&a7V_Uy6dr#2P1>;B<7*wE66hIuBQ zcu2(tFSvxEjC!yK$V%kBQ#G?iH1s?-v>pKwEmDxgD!6k4W4><+TnwtM1@76F0q6L` zP;y~a$Pt7&V#dvBpDhta>)Qj=F~5Dy+}uM;k6VB!QgVhBec+n(L12eC+%pqw0Y<0F z?_;TUwEBXiJ`t$iPEk?n>J>}! z6&HokrYn$i8Wqps&+aDE=WAb04U8LsK z`Csj8%)lq+6vtSiEx)!G5lOOucjJ&d%xIuxI5P=|7%VaRmC7Ev#nV&q#rGPFpK$Cl zvb|P)CgcJe7=qj=I73JkVa`Gn6f9g!FPgjNu+D1(b=36Cb+xnX%S|l~PYg79Ri3O^3LL_9NpC26E|ADQNuwSh1M@Myl{VRT zpb-Zro7r_CYTy@`R{Q9GWe>>Z)+>_PoA>uo~D( z%^GA)GE%KzAr@yzoU0su%HbdN~&lF&U~ukqUVnzQavu3;|;})tdBp z^|!^lES~L;?4ab{jA6aEYn|=9Ds|i6yI*}70jKL`zT;5ors6EvZWrNDAoRYKJFDnL zhunDSgeXf>w*%V-0S1LeQUarhn6Xopj@K*7a}PF^a4;xT*!C!L)p8znZ*-8ZOKRIu z83UPfMvscvT1>`qjn*E4^5@g;3^fQIqB`y;$f%4!c{9&!lY{miIaa?@8wWkyT|@_b zp&^&=Cz9zMn(iXm7R|Ga%>n4$5*okHPvk!=^1}u4L1P20Gma39*^*m54czetBV5(% z2Tm>fNNL(wYlREFO7Z0~X{v%BsKwV}mnxtKSErDAbhio+Cgogqwc+5Lw?};Xel8(ZP2$qIM?! z-xiD$aUcn`!)*?Z6g*)?_g~Nav}zrEXBA8NBX<6?Pml6LtYU8Yg9$aFh!a$!$y6Ra zFWY-9hqb@p!2D@A<5PLq2=Wueavo|8prm!Vc}Eqv@DBLKk-PgeQqBff5I>f!VekXC zT2RfY8E8tv52i3T|LB*ES<~dK9Rv+AQ^-0!?M@sj?L*G?mrS4nbtG@4e(hR)3nTWTzL z7jyGdQ5h1kTSV?zF);VikIZGT9)?<1lx|%JWiIovWXy~-hbJLsE4!d5Nz>hd2$wZI z#3CaZLOKjJ>`S|M>M~$oJku_|XuT$50c8!^Aaf|-7_%#VqgpAqORIOj~2Nq z;8S`w*O_@jd4Dhdh^T+GsIQP%Maj{ZgR(Z)SoQ&@-o-Zp9!|RleqJ=!<#H)9?V(el zXxy3Je2A=0asBs@&w22m=B2D0N<+p=%~fc}V6tzfuq`C4P`ILBaRX2*4L5!?3<_=zO^nTFaoRKcB$KNhs%2{3%Lo7~M0qRv@fGk1-Lua?TlUnE|>;nd<5|cjZ9zKjsAlIJkl#;k1o-fe&0AD z%Pi#JXW{+8J{!7#)Ut`1sR7{EW!~XZG~Zb*3UOssl~Mh?`bGy*E|?*IZo#Jgk`{LZ z6aT9G42>M#7D;QKf-yIBJJiJ`5ULa2<2ufqT4mRMUH{!PV|VepC@?-;gsnAqJI5;1 z$8yUW3uQiar}h-hik%U>WzFSOs$3-kZ(*L*sq(VYY5r9%42|8o*p{qF>A|7$s_sDL zwOM%lg92+y_E6rqew8tsmtU3sbkL_GbCzIBD!(%4wSL(XR-gUYs>>Lg7=QQ`d--%^ z&a=I%R8}1Gg%9n{BPeps(R9fBsf?7fVpD_|)9UWF5o;77=GpS#UVbDPRc@n>ud3=50aJ_MCC4-J*Sr^RZr)wNV#K^0p z)TzqjzZ1j5kW*tVG7=t;KTtPR@<(}!6{_LmK^Z=tAdu_resQqMC~lG1-`V$!=McurP8}5+^=?`1*wZl*4Qr~|Ks2L-`nty)6($#0NzwTY+ z$%lt2YGtQkdN;OZuBCTTSHPv#AKM%ZIX;r%b8vR-Y1(k(_|uZzrvrL>G}!I%CnL>J z?Ul8B2mK~+=L*W=Xz1MniW86(V}M+YKWRU^xx=?%UH-u>lDE%ReP{Y;mMY`Igg#Dx z-2I{YZ}`(mES+6|Mtx>Eo>!`i_M*S=&e(UU>Z~FgRBoha(z8lU93};*Vu+`;j@Y+S zL5-~>EmA9iU5vP$sa+SC`(gm6KskPh0qAKI?$pB^*) zxy9A~6H>O}#xE0PYS5e%J-v%(W3R6NhEwvZ>)POhq;nWSMDBR!Cvf}SZ9_hCe18cvig2~;#XwC*DRFG3fUzKmuw^ormSQwHu+<-pMG9& zPgRE(JB19&!$>C>SkH_L@2)}$_8sDgjR#Zt9A465pSKyDG)#phd&x$DBAG1dF4uZ{|OJ@*`i94Pk5B8M~0( z0Ts>eWHgr`2wDm1L$0|;!+%f(sJ-3&0Mlq2&pb;1GDUmCt3Y|5)3n-D8yz0fPy_4- z2f}$w07|$Gw>HEJyBI)aE&Z|4#s@WfIBl@*9TJJ zPsd2#IY0WLE!>I4Qy-`F-^srHXfrwh5-}=1GYbx5ehF2dtXa{$->!$I+IT`#7@tG# z(MBypnILQq@c?Nsc(W?xSK_Br0T7hXsV4qU6Nf?>O{m~L7grJo9rvSC`1pE~SOcM(C#i(%O=|~lLFE8}lE#w@KJ}nSM&nG>Y|R|}zc0~K+3fsxhrM`5U2CWR zhroHk*HtA40Y_fyuB(z!Y3eHA@o@H#owcQ>AL|Me>s@%Ewg2aq;a@-Y(9!_jtvsnm zf#NUs@OWNx(MUW)4Y1pk`pkCf_-a3}pEpSu?OHls0YEi)f&hNGpS%BebF8ZtMgQCXlY*G3T?+frL<op7xiN-_^4+WFaV}sQ%(Ft-Sx(ukoJt*ew0nF+$GAS%zGE=r^xy zltok2%yZlA#Q$BL{Z9?=(Z>>@_XY>_w4+RK1NHlbhMu_<7WsH&H-zUcb374#7X21V z0yQN}+^In$cD_bJ!FXfq#w6GO#Av2S#8IqSAE=+^3LOT1eVlLtG%*(~7{C5(>BO`{ zD36ZT;L#aEdH zF_RrY;PnGeJLf)qG8!E4AIQmUTF}IYU}Zhv4Wok~HR|bBbHSAnK_K{84y&_Gl~Zqc zq{$C68#@h+v?jN!w3ox9j1GUsm4qWrvkWNUHrc*(sN!hWBbTiua`64F9-hsJ+yv(R z7Tg|pUk-62=c5zJT{+WLLX1^FWm*8JC?KOQ7QO}uaep`yl?_YXSVDtKc{W@}25a*o zUtWl&y6oFL>XnVW-y`%f>xjIovbnw}{jKb8^{_pu$#b2)JHbJkm9*i~7PQinztW9Y znL${cI?IB#igZ-@^XTft=5Y=Ny)3`hK#Ra-x{pR(tob?KDCqeLuKqvCqkR9dVj(Xt zNSPRq;V+y;0Rp{~d$WUnR{HznOr|@^*-K3mQZhkyDg`#aK>0_G@d$N-k^ZXwrc9b0&; z*k5)hvn0NYOPD(lz^fYVGW!&fHm2q%<&_OSx@XmcRmg&ZVo3k18YEQ6uL1fC z#JUKh&#shrllO(b`Jo}5|DsSbES_I#=-E(E>pgU;d5Xsu=XlrSx*zudr)qZnfa9Ij zJjo+uSc>V<(9_HzpGVV8KWD2|doLGE>V)p}oIU~3pBhUq(yrPLKXa=rET6CXWt`T2 z_emIPC2dLIi!_-{`|9fb;#SZ1*Tq?s*`70($g`J&G>x`IYntilXE|w*%pOYraXv-7 z5oa-QPneZrsCHtiMeFdg9B}1J1sZ``{jzQxl5IjePcxntQcm zDf|+~R`SXKRC6Fc@SNw(^PiATQ*S(n5R01)o$gZMk=GDawH&n(aqPeA`kS6LqKIjA z9DM<@hCa99l5r@y&Elaxl&9eg6|DL%UZ~BO_ik?a8=Q@ts%@k84tRjGS`W9Me*Awf zUe61{8$sJ0OQ@i&g2__=)$tvx*+IbWj|>aYC0_lf5{kThxD)FP!ql?f`7?Sg=p(2S zj0e0!xi8}kqd(x-|J=MV#^7hM&CAXDpJxfqM`cb}od9g21IM2VY$)+qPahC1Q$WQ; z&Frjc+{L={GMtRy1g?L=WZubF5aQtO?p|QbDe|h`?Eb{|{(riA38CcM9vmsJLemN# z29n;Gv&szK*zvPD#L*J+_4EAUVqU*om&VKHP==Fv`6nOOBW)bZdlvcmMMbywf6ZNb zt#>f=e>X^g0B1NRg!-75U~_O%kPT#a(&Ui&c0&yKkin#|=C<35=FI@p^rajp^cwR2 zW9qx(sea%8U*|aX&L$ltqX^mioC>APNFjS>mpzViqEHcKMYimjB)oA5+1V?5uk1a} zIlouY=lgs8;U5pTdtJ}#c|Gszx^JpO&NYNzlb!|2b)2wBq#$z2WIh47Rjl_j(9i1Z z!Z$QYA}m26ttzyN-p$B9Utbo?%5uw}Sr1nwKauI2$VmR|O5)IO_<_yvpZmEK?J%PE zOUA9&@gj0)Eepn`53l9zZ0`i$JHOT2_}%VdecjrRi@`r1lO1*c zX25LJZf7ij-{)|YU+_PNw9d>U*!}SSiBrN@UFZBuU?X!3B!WP{)aVPH0pF`Pt^Rs= zag(+a8)))@=e`*Xqcd+ayO$xAP(y~yTjETxD>HpTJ}%Q~auYGWI<3gk5>FQXSQd74wk^!dTnSAlKaqdpm$fDViSe;CB9#5$y!QkPg_mOdL6ETu^ax zdSNFDE$e1?Jt%8|-`Y@6LJ2)J4m9It;}1t1zh9h!p{R=mAB}&kWaXr%J7%!neq|U# z-1h4L%Q{Mf|C=Es-Xer`Fyq6JUQdG6cCAho9h|&RND;gZz~0u`g~jmzUQec2e+mow z!gq8#w@Ke8ElfCb3=aLGzL01K*!?Jwtg0K)6VgFQ~X!@A3UF z@Z>U4bkDP+`!*BjTJp*DS%D2&*-`W(RX1(-oD;cM%r5`h`6SkvQ2lH%b5Iw^8o8{^ z{05LsRLi6W;C$z-|H!XxtQq1cHu3-nL=Seoj?0@nY4QL=?x?A*pNnK6x4lDG=+Lcgo-x(sMD zMu9K&yI-d621)8=O?P_Z)4$W~BWiM9f@JVx4fAnF3;o~tL1|ckvD9@O$G6~A=T*_} zXaGER(owtm=d{)gY-L+(u%X6-cqOLnuyz(qA#y55H-o2nq}g_ki#Nv)AIO~Aoj7rW zFz$EER2~Fat5Xcb!*YsAkjX1mv_^w5%sY}o*Dm}BUDVL+N34K)uVi8N_Q`6xH290F z1`ktPeYegqK=qsZy(cWA3j|*caz1a}JAjwf^WxR^mjRh?4x2`J{7{Y;^7Kw_>4CuX z{Y9KUB32sIM6WG6_LX+$$)D|lD735V5fkN`m;Q^B%o62)JX7mCcWAArI_BY+%h5UD zx5(f|$#-qr>)(Z#pag%DwM?6GLUF)i>hjYH#2J&_x;NO^!{=Oc;0H4##nk!VEV&DK zC3d}&s=cxxBmqoLfuh2b&QzAo>RNAn)5s4VdyrAkQ1UGngw4L~Y^yyLC$trf{LC`2 zG{|Iy(oLVx%gxiGnAE;_F?C=lt!So2gIw5Pibg-WcEV5=JnalQci`->d~#mh% zq+&_^f~?;=;ogNC19L?6m!V##2TAeFl-u({0D)=k0os0%5QQmK0i>SZ<$QFFl>?8%7qh9Eiooa z>6Ezgr*P7UOukoO+E$ac@7>kse*zf>Fl&L6^cNN^ItL^Q!j|XL&^1M5XH2_-7Zyrb zNz5{#S;tHWvmvj4N(9L6@4{6{Scy@p!7smrGWG42)z6P7Dk~IABcw8mwV2jg5|DMz3eQ2(QGcUp^}M@{i{QW{DMq&yHHbp^I_QCSDkU7m zj!*PfroUzcX4{Q@rujk>bBwB(aY6gW8kR~d8gJvJ)HN=do=`nKQcSnLPXM%6iBI^Bg!#oO-&hw`=dPoW@)>Yqc=nbhN?!BL9v;J_n$R58lxRi zELDN1W9akCudc>IO8<&w7uoOqlKmL4(Fp%A-*)63*I&sWV!Y^qdM?y! zuoo+p1WsirC7n!d;oq>0Z>*Zo9rSOL_aGf1E2*KtEYO8>vPj;&$>19N zAFu!D6=lVl^J@s9uqk}~RRd4kZmd`5r8OoZsM9%v(lcxCwerxz`W?U3XTVbezn*ep zK9r~d2Z`dRH&mohKi?&*I~RN$e$O5>3Ymg8#ExUB5@*ZZtJ149mkw7X%zcy^Q-KV@ zxyegF8%?Zz$1pDc6)ft^9k@|H_5P{0=Q;3g5GX-De{H>ij@d4a=ySy_`)!*Y-6mfS z(Nn;P5*C&zdd4%F6)=*{#0$Nw$_=i#l8n=rQpdt4kaFMZfF`+&TDi#0pBw9ZCb7Hs zT*3ZimaUa9PI$S{6JNS7pq*T z#Kc>fPP8s_JuZBG>%t$jE0n2Hx)Y>8in8 z4F1ZQ@BBu}qCIHF+ziR+%8sv)aM#t;C!B9`3=1$u4D>$L{4d~^LcQ-y2pF7Mu~NR% z$v>c7cT#ct%=oNMg%6i5ix)rY6gkL-5)|tlCr1>aZRYHM4;M3azS>cR11^*s#6O6{ zAhkZAW1NO3p-Hh?!4U&wm^(UC?mG6&%Ct<~(TaP4^|(3e{q=Q?V34Rsb8uP6s+{_2 zbq*tz5&YV^v4>;=c;|@@5r5ickk62pd{@HNPcG;ohD z%B_;(p9T!QLpdAt44SOEpik+!$^J*mQu5x4Z)5g=deP0O z0#svVT-*Q`k2%Y63+L#7dO-!&e!AO(T%oh^A`X2-sBn%<_QqS_K7lgx6Hj(bP!0HK zr-`iV!VEUIrfG3o$tOhY`f23rbL|>)l@RHoI24l(F>k&KnUwo96L5NOK*0}LW4l6R zIK8vndx`` zasez>pDiZJ+~eDbHOo&Xdvl^Xh7BX3bT!}`*p5c&D=grr3z*I=vL3$zV#BJoU{zFH zf7D9#|Lhuvh$l6t9`AlT?+>qQgOJ2FGGdUF(xAFbO!$nAaFE7pl<0da_V zSMqflUq-yJuM)-;y~#pBC4Q-v=pXk3smB+>?2qlT@2EzPZxRscb6l4n3;?Wh?_QQv z^bxsqi56Q|z%#)lAPrLb%&||j`|xpVRp<1m+Sh~@KIrV@>$TggMDpZkZd)b9>In~!ppi84#}2Jf_eOd)%mTAprq z)MLF%NZtnwkn`z(H)E;UO3ZuQGmJ|)^$3pf{(W*xvHf1ybv0BDsC+u*oBd#R@$poY zzc_MymYJ*aWMMdb=!Cpas2UV_G8fIRPo|-tGC;h`%`vXYW>SC8wbSk@W6jMzcZF+? z)nxyTn@J*nfCkv;o}SXb@2Ngop;!MpgI4z0x}eu5CcfWo{^e-eo8N)0;?7ilA6r<} zD0uH9G{EU^Kp|c&t}ck$nt#(7?8(Cz!SY_62h5C;_Aqz9l{dI6S;)_MQ`L<~7dOL+ zjPMwy-H&BB2u59iB9+}z8$(Rv$jB-oe-^ddt@7aeT{Jr~8An+;Xu*gacmq`O!o-d2 z<-4y;?S1twmAnmJ1y!^xd@JD(bisEIDFI3Y4xSFwIGR-r1{?cp9JZB$?H~V}G}*Q3 zf(O2wc#`fv??$tuB z@Rp56`7gHcd`&ao%Ld8D1=rr_{|#|20e?7)|B?F0JbpJhStej}5=)rbAvOSt$A6tf z90V^+)Cmt=D7gRu--C>rX@8hd3YJlw()u%3 z2m@}`9?Wa^%&=4ah46!W|E^0wg=f5wBK={?fV@3AsFz8dOt0`9dlI1!^cz?kPM`$KkhL z^#cDC`)Se@*GHe!MgH|-iACPJIeS-Qu2tX)=4lgeJM@9TlP`k2sek)>f<2k z?UM&IcxtoM!f$@exHpJPT#5aMy^i3HeS11yiWQ!P2Zaq@H-;V85Lh?TC@W~~CM-_b zhylzq_$*#}%~8yYhTtl{@pfNqAe`)1A?fp^6Wl$ghs>Odm%Lcpm5_akhu(kDhq2GE zqqK-Nd%+Fvo<`Rx~e9mc)QxI{-=qe=M6H}PER%YK?&|vWRNPThd5}g zm~*>bbJ3!6th?Yy10CSxQexfA8@`_s*MJGbyvbllAi8i3UIRB%VGhaX1s}9#MM}uh)vGlVg)Y*bj?9kf0ySKq4 z!mTk?^D~TRaNq+3Z5?gD-@m+Qed^0YemuxiL0?3EOMx5j<0ynlrFrv|fiaC2{0}L1 z-S15r+Dpg}U#XOwU&c=@6&HUhx)m&O4wXyq7Ou!G@mAFze!5Pfg>M)XcXMKsi58Zz z3%{Pt3cdkbaiRnhal%w?JOay-8^Q49!97<;u5Dyb{z33iVyOq9bxwhGuNj@KGweDs zQ%KuIP|tV?wc5SD*cN{h^<7;4c3SDiIw*{0cI25zU>RzOKk-~(L3^08g3%J*XQ z38e>mWk<0S!8DYV2EGoA#0-$Sf8tQkAL2r|0u-7tW~ ztSKX28r4|vqYDq|)mWG4xkbZ{je>G*nwGi;Q;eAN=9N9pY80^CNtu(Ka#b{6X+&MwEv! zicy*NK>=rFa@SzlHwm&a|Zk(lZBQx*Nbr!l@0-c1!n zqCcfQe^_ZfW!xQqI%-|z-`DMZn@#sIo!Mi0PC8f}G2~+=NBo*1DkirIozN;sTHBqsiYiV7G)l@oxPk$qXlS13tHtXYRRY-s$&LG{ZKNe>vOK&UP z%D>o;pLpqk7y5J@?8VqcXU|BZ6-_A}O&_6HS-4AUdY1_J^I`nW-1-o{b4u4jO_VQ2 zyIeSeJW69w2b4&Y`h)W#mF_(u_kRoY;Ce%SsdG!XEU0Bl19X0NJr`nw2zfA){cQt? zsNWu%Mc`)0o8CW00Azc_6j#X5A3?aT zW|1T3W9d-q53A#@pr8NDUeAOuOKd`l>BBk;uBY-gvmeQaKi^}i17`@g2@SRagU z*#tYJ{>C6WsTS>J$H+~8zu81NPrqw~9Mz5TcaVmDQAu)H&pHmim~mUleL(k@@li8l zUV*&|Ch0=xX_tV?m%A&$Wh#oVWua<9q}N*4U|L=qHUr@g6q41|4k^WFI)!5+nAdS` z1Y1^_>1#cJ{Z;3BH%Vl+{-<*|bJ$rcudmA*kjp{a?Y4yz2G=`)t2~au3k?m5$^I>w zSJE(hlBiz{2X{4b>Rn564VD}UJe>*noaQZh=W{^obWJ=!TrDw542 zr~OBUzY+TIOJ!IesOp9Q?wPcJ&`j?w9i`9#y?NVK6S~5|rCNlbz31`CMpqU_#Xtc+ zLVHJUM4KxE!TclYY;}Rf^J2YU9iyD~lLxPxPN(0~@%|tQur8pCkHAV2>LS(;##F3e z)dVZ9P@5sdQ*mr!O$Yrn#J~y?cD!_f;5$ajSpXh!jC0%)*ZbQCRM7>#Uf1a!m!Ac-2c0`3|qc z`Av4+hrf3^cO8J5Oaq9a3WoiErUMiBk=H#1=+J(US-04+7Xx%iFnu?EKKgl8!g)F_ zQI^23IO+0I*i+Yv$gkhgc}c50NnXphN|Y_J;`EFaiOuI~`izHjHcv1N)|vd~bx z3p1sj&kIpG2xEn4>1O$o?Do)55%bE<#!aI`j-{7wghhSX+W1+ks2eIs4+x7KMIZPQ z;NLHVl_M|V*5MPvcW>MfEs~7{>68rcnYe8*(sy6%*O$$g72uTJyIYCYO*b|VC+r1U zvO=1rPm!vYrlxbiZ!3}ye&ZyI5J#JO%=D22IdJ1G>Y_c3{&h~eZuHNvZX9LceTd$- z{k6`#HZ4-06X7f=-1zzHz%A0#R=V_m$~z_u(gH=1KJszgUq~?Rb+d(HPir^Cxzi%; zI=il-6(6QN?7^k$K0-dogrBRlhVArrJ#YSpw_<7)Zbx|m6_BC(rtaOZ zKEK*UEOXG3XIQ*e@n8?`mi#65J!Y{HTw9N@3i93EsL0(2(til`T2y>C+5d;Wj{7v} ziMRd|YLFJGp9q|@qUsQlzW=eX1j9RY>4CIno$vKAL<4A^Cv#JHweA%a%aYkO+zmvH9zl(poW6oOJ2L=6zHpl&yNTyIJ^)4}?Qd7ih<~R+n3e&aD|s`$ULMY-Z4}oxSJhV7g-Y(xs{q|B*aPLGDO&Wllx5RO!q<#h zQ(q#DGCxAWD>`NEpZT1Glh(D~aHLV*RT~U08rJ8o9Z-C|$4llzklk)z(ClK+l{aFL?0lxZZ z!$bu%uTE&Lx4zHjukx6*x2Z(C$bX2VXDVD_86j*1)1%=oeSs~O9DG!O&9K>~+94gUKcGE3bA1!k3+82Lt z<{wnK&~{ox!f_LP=kHA`0!r!79i}oWOg<6&F*I{9T%DeN)j@Y@DKpuy*}BmIWIuh6 zBA1Ozda-i_xg3zqE#51+3zhUK3T|Bgws68+!_4h^Yv5u_?L~Wi6Vq0Jj#IZ=*6~MH zaOTGbTg}N{^N7N?_m=RfZ?6*Ns|E&4BJ?S}M}Lx#NvKVS(rf9S4i7L*h!)5l;V0yv zCx~&{t?a}|uZZ9ucD)yfOIwq(E*4#6K>o#Z^jMk?uINN0GnTwss6a!esXTttVsi z6&P61_4hlL-`9^E;g=g)2&3s@iRvd$u~h=*A6DmFrOeJ8(l*9RJpc(pT1KEg&!!7n zvIOGOLbljKPbB^FUw2Hymw1ZRNe^fG>51YD0GBIhG!iAj07Tg-srcZLHR#7a9|HxtXG^6tMhy1O6#6K+jCr%0uS z9$WUo#nIDcec>cNW6bT--VQq`sq?7&D;9d-8?*o`*E&!}yVZX5`9WyN+x*q^ulUCh z?Zes$UCF51yD}dzc44xc(8|9Nt3SUx{b8)7ew}QPv&Lrf zS&M>5kb1ptQyl~WYsI0+AS7ElKt?;-<>gq}3YB%7d}1(lEfc0jjIXRiU(i>;uaG=< zvLq@W5v+|;DKjPwqB+|YtQMxVBPW&iwEC)t^$^~rmRiK8`_pCj6NRX#^mzBhQAe96 z{0jZ~WDi4o<2>+HyI1?#A0zm+!d-;b6H&`PQ}NHacc<(>oUEt~zT%0=UYU!g>SEwJ z?Wp92F@bcY%>N(|d+@OJ0!{IdIy%-&l!$A^ly?DiU%yPPtefq-?9gxJDH2v^!*7q- zYbj@e!kN&G z1J=JtBp=MS-0s>+lv<}r%nn~`cXWp~bGxU2@rULCrJJc0dOGC4=r#B>eK$Zkf@66z z85+*2g>3)o0Gg()x7%5Wh(v#xE8SeQ1(cRJyt_}5K2Z@N-RR;Ld?OJb;i<>WLEJ_i z75jb3AUjBP!O z|2Nkz#6Pm}Kfl5KWnaPXr;{TgTQrY+4|i^)_lAbh6s@I4kDEKCmLwkq6R+gQ$&JE8 zF_%T4N3%z#dmOX<|I-x(Wo;s4pLc+5q9nJ#iVn5;&PXG>0?&Ekl-Vr&tD?%gkVA^p zv^Ofqy+4!k=|2zgS9vPPgrpk()2W%1w@8n6jGBNUy?V#*bpQ@h5IPS)TH4^F6NwV# zEG1I)#CoVD>hD*& z-;EaL&o-8SEEaO&ye8cGBB?<3TBIHgl#1k(?_sQl?g_^YAH_OX?Ds}-{wCGEY`X$g zvjR5EdB-7+{|WS0A}YRUrzT&ck^>)1a7?a}BwQ^Y5=@B|gNpov8?Ki4{$0n*P6XlC zM!qzlR4`}i(((Lmzlp?@aL=o+HrYw6=94ATfg`;Fx%w!c?BrDsyMzWv z<%xQKazKW~D3<5mukjZX{_zNmx_r3$NiQO)I1XIp#aE`u!K)g;t@}Al{*50Mi)C-$ z*0rI`V#sEmMWq{q?TneiSo7`$e}UYjjx4u3gDaqQ>cx!8xBEwsvc=~fn(UA=5JwHc z@)LIUyu+kUUjMIJS)?p0_n$`;fLxg9eIkBX1Uj9fk4f!ted_qnQjjwFkG02C4mEMU zLW|+%^*}QR1e566NY9`&8}9u^ydl0dpyz9|_cHt^+>(0E@dFji$bq@5O$C$l7W%)4 zOrdWDuNwQf%qgmY6Y@HsIBAJArJWa89i;x4l^GHe-;n)I=Z@S#Y+v>rRyzIiaX~-@ z({eP_eP*sh!Pj$78k3zyZw^DyNo-yHx>R;^oGE)-OnJdsEU&tYSV(Q1>$xpZ>A}QA zGKmxtEmtGpdkdp`*ih~^mGUxtlUb^dB8sO&znfE zw+cCvn0^6|Dsc_9T2^+>y;R;yci=o8&c!#pL4|%D_zM-N5IZ8KuKn7b+Wa;W$#>Ew~^$_h9TsSdnw#7C~&RA$LbnP|zOUo;5b`GN9xn_6YnZY%EeGHK{mPO=U+Kz?JoZ7AuA49U4G-15LuZ zug-D2;;MbFqw)UY!)#Ti0k^Ak;%px(KTvlK;~^pcg9l{8|7jx%7OMvn50}mzx(!DOP4epx^?NLk?*C^l@4f^HrMGWY9;hSAKoJ3%G*bqiS!qA0BRh7 z_bTrYTdYGoRmhNnYyHlMiuzrxh2|1HUjhZC!Q5(A5X%)x?pkZqANCib@{s>uF2LUw zWB$k@*u7u3^xo^PyI!vZ-#fW(1z2*v7=p+jyoh5{QED38?}Ff~%CgJbpWR0Hdu(*( z{XFNPv)OhnxrmfIh3cR4nv@^sz?(XXQ)2iz1?S=*Mz{4*Kq=eD3ke2ftSB3ggbPfT z03&GE(+hT=0&nP)+rk=_9^ZaGy0yqpcRD&PQPT5T6YPil%VZJfw*O-{BEk#`-LxKp zvFpo-7+FC$<%(m2^tm6TEdJrQiCb|FWb;m3Ar8REuBstj}rKJCMCXVFsE@qwb@ z_NHc%8w`B3)JB4O(V+D=EP|fCe>qxJMTv=-?)s&Hc+vliC)GlU8w}XnwnM5KBGIwG zLjD^7fd42I`Cws${$c-TQ_osF-icI_b;21=HB17xhj})W1#Psm*^PcwPuwD zVU&Wz=r{b&AG4k@%^k`}hOds7{g*r2fJHlol(h1i*0-)55Rfsg+3GIEzHy)9y2A+G zPxk;;hmI;PJ(2ps&z?(s*Ghe`(ZM^(__09EdgCrd4CwLp$An|WQB}7(xG+qoGmXq* z1*wMI!f0IGNX=)Ia0U@Re+0D8x@a-DW%8)MEsw#ODz^RykGq) zxr4S_fwI0YO4?ulIYK+H7ts;Xp3&zbPN~H|kV3Nv-_hIm^rm&>6YWcD_>tgA_lMDJjQUk486V*9+HXkX8*)% zV|6IfYVUqDI1HBD^&*f4MPG)2RFyp{cZL70C_L6g_Dk4o0IrboD19-kA*v& zCd8U3nfX#)v*Ir8OK(uTEK^rJA{EJcSS&9~aprvaOMLo~rEJI&+#k{YE_VtT(7vY> z71#Utfl~h0cy^C@UWgq#di*HSF)|zvX6Q z;vpZ{veiQ}{d%-U4LOwb=4qv|4{ z+*S#V=6`IpP)?d-P^4D0!?N`0*M;2s#pjvk)YP6Sbb}%0TnY3s1x%e4lIe1dgR8GO zDYfw7&Og^z-qgy}?-)hs!{!AO^>qMU!`Jn4d?LdIX}XL+UqjcdDw4JrN$5%TS@-}H zvi%{HCG@7U97s**zYz)PfafXI8zt`Pm)FR&82hB*;0f({5|L=)$;0s-J9HAL-)97$ zo6Nw)9`zYs;;4;Ab~Rc(t0L-XhoQ54tVf=s0@nMxf5zAQ{;v56Cj$wX`?ywJ!$0a_9 z0$z@n%^hT)^mArAt@cpMDAvxY3fYa=fFZ$FgRFWOoO%zZmt|1|{&fTt#j zd*5$agH)ngncb2)p7!9QvCkH~hWkBr&iAiw;bqSbkyRx=M$^XzZYEy4S60jUS8`CD zhdw^+f->nCTU!{}o7>DVh|gaLM54bZ&_p7!_X|p>*DIcG2O)fBG%sA*biv%1{hG%g z4~f{d;b^1yppTIJ$|_Q6;~$dblo^PAdW+&~KE+J+j|K43F$mR?%zz-qOKg@5-TrLl z1zh3Jh<7fQJVylH0%RMMJL5;s4o)he4~Q^wRVF_`Vap~cQ$R3 z&;XIr6SSBxZ6HLN)W$ShR^hkAVmY``zx;Lrwk-;_!T=p&HE~K2PA|_AzZ&CkH^ye$ zrPxq<;sdL{or5zd;%q{dGie@DV95TDHGC-nd}_!sAyqX%w!waurxdCZZ5A>Q6|RPo za;RX0oWv=MEnr+6$Xn?twipwczq59|oC#X!+OExQCWeW~uf^Jj0$^N`IdefvDniF%%2m<+NobiwHR$}dfZch_4q>44$PPV6te;NPM9T7<7^K^Q(r|zEYs+0X}p@nem z&b~o?jJtcytqKdB2K;RM!+hIKoM^A@mH*UCf6GT+%W_k^``~63ZO^%ixgL+F*7^lu zzlLdn%2#uJI2ZHP{iLSm?U?yPMeZVr&V9B+#cNDp&7D5)%EHbK^mfM2j5STdEo=Woe5#^F6HzrIV3%Wjc)tV<$2n3*dUK0Io_J4tx$}#`#?%BNpj}ZNOJrf zbosZ><(TXEI6Xg(#ty3P*OhfP__B5wVVbFgklVq^6ZC}zcJFH_Z-L`51-^r{Ls^}w z8i3Xz0PX3e<2FtFNRh+R5?Zt?oRlCKqYYr*B9+*L|;Muo-$Q;fKa%M{$mCZOwx z0kzPEb=zE8_ZsJ5(d#!>56zt;&f2O=ebWK$TV|Me7^ykgEy(pzq}&}a%7C#U`$SM-7~_X%$y!)MyYfGk>eLVOB>EY`U;b=9 z@OR`$k$Wp$aU6usm&T{lG5mM+!p_HW_wVpT++lr@>|Ce)%&u!l`-w~CkRURr>IHp@ zf8LVQ7tE!(?Oj=WnAYqS#8*Fzm)!H6BSveWv~rfpfOeOt$bHUKsqgYu0M9DdqgE2z zhtfQ42omthVabD-2FEdI4t(R8kgmk21MfIA;X>sdB7~{+1PfS=B zzZr8|BYl%@H^?)KLErnd40?Qd-Yf|$!fHD8(9=46@Wa-JCzDA7`JdS6#%C#=_QvWz zLAZWR4S|)X+p8vHyGhPivk`S+Mc>tm;1et!Iaj+C&LD{7{Ez{@eGbmh#g(xIy~yISKLp0Cy_2Zd^8nX@T)erPWZV=VS(S{C>w1t`B0`QNJaB1pt+ZDu-_O$ zOkd!_h%p^zBol*7cL0}HavrChS2x5ii1ib*=UST7xCO}cb7{JB_Ax_tg4LnFA@pK7bUCaQFfz z!7up(2G+ItuI`aF%3H`_%V#&Z4_+3<#)gZGb}UJs~O_-Q~S6#lz1l>z6l zsy0Ulk9q|f)Opg8e-F&KcpQL<3EH;LSS3}zG(eR-Y+1hu*6n#j{8nJv~Y8 zQz501+Lc;0{{m!eonwP6Yx;Ky)`l9Bgwm&HWZ_p!%S0$^EtJ#^e3mC{b9_Rx#|p7l z>}7IH4vzAs4FQ;dy{+b?E1Gd` zG$D-dQ(XM(@78alQ!^>!>d^)Vf%3Y0^KV9xtxf~?l%+k;?jbj#qr>)`)t6C>FDOEEP|5t5kNQB7gW^KOFQnr zg2o*fO;q}<1RMKx$6ws$M#QR*-E8Kb>*o}u51l{KX(J&oo=MYL&*@YETO^f7q6$s{+NezwLRtL z=P~TBJ!*Dlk^pptETh+QLPDp}qTVvrX`?7N_P^=`naqx$G&U+(mC&d{)0e+-$p6rQ zYslhCLAao(GJ>xj#uo;R@d8sCydR+( z@sJlq-8%$JG0b8mxW&bqirC~+ZceLRUR-m%QFa1Ns| zK$Q|*2p5ml*&A8Hccdh)X?A<3s-&Igi3b|+4l?NaLQYqm#R2l zikTxNY%RjrR00TlYEMxeuq5lkYr}PD4VgwO{oT&q_WXN65K~#(vfcfO!$}kEhXM!R zJRd_Anat6K0oH&y1D6?D@j;cXOwxQ0uYTnP;E}a|jrT;?P{)FHB{@<|bTb}Oimok* zheQp-QnDd*5)k>H4J)KbaUOLbJfteUP}X~3_)@xYA+hhmGXd&VlYpe1%*_;o{KK(LBBaneNU zgNe#SKHbl77$H+V#HtTkHtO?9PXvClurxx}>?rs~hl?nXeBO0O9b^e%thcMfVi>GZ%k96dgjbHzg{8=}KUds%UD0#rhsXNSPq$lw~8?`0e(<%#h zgb{LmwnjwHpJa6*5OXVL*-HUW(?8>9XM=@!trWSd{OMk;MdJ1s7{9`SlPZ&#RC`oNKK3G0kUhC4J9`;Tn#P_?>Ar&K*1mC+RzieqH)?FCas6wGGNm5%B0EVbA0S zos&(Df9gd#yOuqI&3CfmO+)(;M(}mASjmBXhIK=|?l!@C{p?C={|#YJx4z}7PkCRH z?{D`PnpVV{v)oeE^zl`S8YMMS--OCt+4i0Y?C}%;^+)tz;t=hnr&eHH|cD zph^u0-%c8#!b}enJIplR&X=9)>?8!fbDtS$E{1$4>aQLK41Ai&nuQ|#*puy;BW%CH zRp-JbNkjJNyUwL>+4cv=(j%kZo)oY_#uBMr8fuMy$#1y*M~+#VoM`A>%isQ~M#q$x zIx+vakR~W8fs*BQ=WUCoyO31t%;3u!G73{^wy%2+X z!nHVxh8V=kbUd5o-AJBsxQK{mVDt%}pX_t0q9*ht|+B+&w;ig+dovP4(-vEKcQ2z=Kp~f-;b<1^USBxSHK|uPxRm zBoRlWq7dkF^5UJRR~Bi*Fy$t!G{UR{SDau`q=W>|VX_aK3s2H2@6^~R9`M})Q+OAI zSJ-pDC?N-5)rvh7`x@Y1S@9L4BW}Wd5IdZtA(MfMpum5LU5ODW3B4nQ*eF3-k4B;HZca=Pqt(9kfZMcfcKW!!Ja)i>=sCY`pWNIFE zK$M;k(s%(?+|cm@zCunp+`3SWonLRC@(VMfXo~DX(hg|3vrOVv!?jg( z1(h?0;OEsexq^qIC~ngs`>w|N@ZRDc6M-!f2VY@)n)d&hBJwH_r;uGGJ0O@X8!W0MIE1T^vq9Ak{ zO;vlPx87Fng{~|!+-l+xFpBcK2Buvsv2!EqVULy@!b`$1Q8YZ`3-UcGSI7_V-u+YEd13Qwr`{Mxk-PjG0KT&Fd2|TP#^9 zMwjj9f|kkogC&bU5O*w$E*_z~VkymY+8k)HuN?8z#4RXm1N;C+kj7;HHGl`VPDZD8izR~S)m>>i7d~N#Ec^V2oc8XrDZUn#(JQvZ zja3{;`MVkO*OF7M1JRA5?-yZB_uc792zC?6ePyCM?)$<5E(4DH&H_W$0kre#fqo^S zp_l5gqkC@mY8e3>HR51_bSdpO<`Y}3FLCVy$$a>)yGl~u6h(hFv~_+>78Q7Pmjuv0 z*?*;MtUv9#mE*T{#b5j@;?TGckBB4YN~Cw$*baY;`u?#K>*3Wg6f>*wfy~S9$mltKl{#PJLk{tj4=z0scDBGxe^qFBO0Rcf$N|cap=}{DrRz##hT3T|b z8AJhnx3-Ij8 z7Kd8WPj?nZ>A^-m_EA52~?pnV0VXh?yD z8xnp;zeVPqw~ff7s@dUb#PB5)L@SdRF6{YYgc@aI+aas3fr)60h>K6GZ@UoggVIqV z<}Z7S=8pe*A~!c2SQ@uJ=4r^T#pW-DCDeu=DU<;f7j38GPaYskE)w|ALw2dhQRvDs za@{tfkUL-Zl=x198Fn>1*Y6X(X!4jbl{Z&XV}!hIKVNNdU~m48dLZ{a8u9WIZ1FG+HjZ4Ru#?j7_ z-&VsX*$}S3Wg`W6Qzddhx{hDsA%A-SYt*#%1|?x3%-PF5&IhDq=5H!ki(xOxfZs-8 zz5P$sf#A_i;c$}u8yU6FMuwF+4d&+O0&hs zZ&nJquf=~tRL^D7RmPVLW6=C&Uc9^@V+(^l5~(z{Sbt~qFv@RmM}YN(V%blO16yqC!U#r|yA zn$H|WS))G2Z_)}{f8K?tcepn%a`#P#vCpq>O2&Q{jD)X9ncJsp?k?FKdzJywiokQi z@Q9EYVhTO#y^E&Mc-8nQ5*kZE2k6?fiDzM9@08sIQbo$Y5a_YHGV+70!uyXJhUM0| zX`j|qz4JE%by{KfkNEAEkyWzimiUc?xghdpJUKPDm3}bs88YYw0Inf{m-)hrABnI5 zUqq8z(#$n#F>7d?{plU>j)aKgD~m%y#PH7APVA;=F}nRTFRL{wF94f?TlM7fJqf^F zc9b>g8UujfKq)<0(viV!F$zdJZ6lJ6SIJ*;sF_%s!tSkmvZs&oK0b&L&FvU}+4_{d zd1-$3Llazp0TKFNKKIDZuLZPpldOWT+$2$24|roLS6_hCo#o@UOC?)g@^KYEe-6%w zYdpBjLC3z0Ak|K)84o=4n=f&W2NzWE1#-jHF{d5heOLbaLus%}B*<`;6NI-F12KI| z*Sv(b5#>Wy`O_VWv2X5A?FDag4&$Qxps#;f(;(DO$SEkI#trSo8{M~8n<@_?yQKSl z=kE)cAeMS9d(CfakEiXz$nwl!5&y&DWZ_4p&T{MP zdwK%Vk8J~Z+8qr)q2B$S9{(X07v!C!Pl7Ic#=G_Bs9NMb@iEPlze;;+-Jb8E_4(f;*i2`9CEC zAt3h@m@uP(C(;8?7YmkXywKqL;a=KDtYWuzziYpndt;~4-@_Asd|wQSO+?Ea)C@aa zeIdl17fJ~17A0|;>E?cMta(SOQ+KK5T=R0zBwvoLp2bV&pyx1+ zeWHj~S0Y4HpW)XAjXX!Tn*)>d;AOd!lQ0KRn-~Duov;I;&igZYH9dJPCfUm`7C<@e zYOi?;*rHx)^LZ>V?2>LD2aj{KuTzLt7%h|A%TTq}klTyxwGPZ~;v3eK`aGt2Eq)ze zRHss!;w}aJ?JRv+q)$Gm?%IweR4LPv_L29{kkE^&BN18)&;*K- zvl|L( zxNWB-pSLIemjR}?DqOQ{W@iMUaYD9GisJ}Mt#aShFw~Jt=K~XS^*6lAsRCd}b53}6 z!GxHYjqy=V*n)|YW;U3u-2#z0B6JDYYVU)NQI$x0xb`fCa|iX{kl?GTOg2Cp?ATe* z|C_*(=l_W)N~y_pQ)qSz65G8h5zfyV+H4790^^VdhQ`NWuy)kK=ON-xyqi! z-(;N@X;bP~9JI~H68p_I>lHEwov`JYo)Y4ERKLJ%#i6oPN$(im1_7Gmu*yZfG zh85wk){fYXFLEbIMyC!qdy2t~E|!ujmiBjHz%s}+KNBDu=6F#>lXc(>*Q8=IWreKh z1|Q9TRPT|9cOYh=Cc*a11l#vYm~iQ92%JR}-oJU`R($JT{0jlkGMJ&0)WT2=Xo0kR zHwNnC+)P_aNcfXO>Gx!KtRFm?B8=xP!3{$S@R*-y+KD_12vN?qyr1uBlgU|=5a(YM_gvg6R{YE3j4CE2FDT8Is{%YHU6{DN(-=TX_eM=}v~D&m~H>kz()MYu{GO(~Rr7r(NX}Q6~mg2Sv5Ms zd~d>pZToOzv?N37Iar*jRx9ALOZU3L`~2e8;Q=XXY1INg_sI-zdRJ*Y^rk%mmnD!W z<-fg5C$7~1FG>WmMN5xA8wuoZnJa~&P?e-RnN)-xJcKyC>CKe|6Mvt#5^GW|O}<8M z@$^%{{3O_{u_y{|ET^56Nmoh`S)acszCAsZqrwcFwU%mUn)lndy=sr?ALmZhW8TyZ zUsMEKj4ND50UOnoUUT}Q=j^DDibY$44J#K-x{N+V+PONb%3AP4=#1E6nvGJ8=o-A>d z-!k&b)F*HE8kSvfs=_sLsz@PseX>zqm>_Nd;0k2Y>_^%hPZb$!US+SF4G!2X&Pfme zQ8RuOp_Hsi2c=LqG9U}Y?VzwC&hqY@cw9$`Q2dieEs-GfYctW>Q+9av*?--4jAY7F z6=A8s-Lus`i5cpj0Soe)64R`=__}tE26}~kG@oXb-xGgTFV}fX8BZHdnsgHYYJ<b>}RXJRZLd`4y|DCQd%D|a>B4H_Pam}dCNc{i#q15)`cfHO)j@Z)>@xr6y0BlD-EYj~} z0K}Cbksrsq@;b?$)!u(bc;DMJy7lyvBEE8eG`*BoCi@-ny)j+Ci!Ua1TjoXn7XeH- zB!yP1MN#E>!;)gdEh_JK3>+lXeu{72l>>K0Iy!bF(@#=+Y#F#roO7PKGwjoF6D550 z1=qWrRkkHv5O%*>$ZvcO!yPOy{d_$49cuLCJoo{ln08LJr_-) zyB=G1nzCmhb_2eCes9*Q^Hay#D?$Maya_&m9K9`%U)|c0ftqoO^#l!WOV1rIg)RiuE_^V?20@u4U~Ma1FIXLe^qMByI~qpP-{5H5!WW z-%-%1-Hx%a(SeI#S`#6ct&MoW2(qJE;`A&Cd-Ho^CwfTm%hRFu)@k!wg*Q(-jK2%_Y?-g}3z`HkX$U_;-w|Nde-$_g2cMJn&txN?B@oHchU)DOl` z)MCM%g01fvYuBir@tjZRE<|1m^S4hTg{;L0vW?Z*G<)@(gcR~A)|6;s=y%;pD>c_m zH3)DKti&>n3l9{Z^Tzvh`RT7E0Lp)Z>Z!oW!KdxKcjJE6k4I*qA1*V(!w{rAR<@We9RS|1^5%Uc00g5hj=HiAr2K~6bb5x?+7 z`!whQCS?*8MRW-m0!ip(eRRPqG|lsTL2dR}nmnS6LxNVV}Q z*Y=2%V_D~(mUNCq@kx38%hZEi$cNgX4}D_;R|sL2f`|rh8R*%H+;Ffi% zBd*(0MFqB3`U48HywNR|+Ua1}-=$TDNUw%HV*=ncGsk~tn~>e>^H||eN_gNNfHs6q zMh^I#4j1Tz7=b91>Hz}oCRX~rdi@RrktzO{4N4w<`!mT{Y|if0g}ZB=)vj2Ye|#S8 z@iVnGJub9%`kKR+Fe^wFxb3j-;oEs>%_18nZ3gIbG*k*`S@bJHmtD?af3@t6(ahOVqe#imW~} zkXF{zmr8jSadr4>=M)cc4g=rJ0TJzr(UUK;UUq{O;BS9JoFt^5N?kmdET)TywP+Dx z-L(2~wZQM>o9-oEEb-h;n)V9Lr`^k!yo~=w%l4inI1)W zJBpu0*!67WIt)02B=MU_OH*nN?(Rsq88efQw{f*^&A7jVx&`s;-xaayti#mDkNAoP{aO3aZOXs2NmkT@Gqko`x$BwfKU+0lMnrWxoU z)5Vjc(Vm7)f~$yF-xtx;j=JAG{(Rt;ppJZ@hXbzU_=Yb&ei&R>G9j}^nkrGRpkHU+g7mRUH`cHWDF&lVMBqh<4G> zgt#ZA1Spagq<3Os&Wc*~d#qe%yohJnG(rK@c~p_%qu%ij$zJY$U)(<1vGW$i-=Khz zu^p&(bEY_$$a@Fv34FpO*H6A9v1PNa_t5x}q}W*g5JBM9(O_}F&uj=|zqHrES(V{l z(r+>z0an*0JqJS(NV%vf?DgPgC}nfVT9$dlZ%8brhT#B`=L14kNf-{%Ou?l&e6;&9 zC0pu6(l4Zh*M#Kh!wjC#c=^k&aIc%pj_FDA>cdoEHy_8z4SNW}* z3Uq4?6$jM!L)F#lZxU%M5MvKE$+ypbRwmCOb}yZf!!z1tr}VooIdug#q7w$Ahqd@4 zpDQ>6o^pk0I0w!SWyd`~$z=}mB2{2wXs?9#MUJ1-;EB60n7 zXnXcg_Xn@%;;b48RMnP8RKY58|M^ZfL)Txk9M?w%9es|Np$csaTa8fJ4^?*&pDN*Nw1CRCdvKiiC5??ne%^25t(&km!rfTL5d{jN#$VpZ#RC z>LLdKwq<|Izgj1`lLRQ6R)cw&jy4g{vqFV(M;xRlIQeo@gp(Y1fkcEY;*XUN?XlX2fjbfPRfwgjLQ1-g( zBMogPZuP%SJa@OQ=9;MmBa+n#L+t0uz%~RbsR*}w>VzE(Bi~^y0mraNBOeykGy_`c zBtc}oj7D%9;KQ&`k(3LD(&^!5Qp@@u?XS|-P+F(O>s>2C6rfPLCl)US%!t=VTU|+J zy|X05sVv7-Sw1{lElh7B7w$RkKB{AbTU<;*71AHp)ZStg*RI;>z9pFJ&_i8ZyQ`4| z^(dn^yMglm`~MPMUjJYLjv(pq7A)ka0FT{b#a~Si*tcl`_$wr2d%a2SlV0Oykjx ziWoJe94JoR?1*^uN9s1Old3kxkPGJ~#8ssC`-<^AiU9)PjQcth;4v#D0mb1eNmc9v>>JVQ0VutT<_xJG~=7 zy#RXS+|}j92D~qvnXN& z(uw!s7Mn7{xp*iNQHGYkc&#RKQA6a;hv2@Xemf2us1`*a1}}4HpL?33Sj^t^KW0LC zpW!1Hr-lW0_RU{aQIqotCjp(=S1gm@Af<;oxFrIdg|w%id748mcfTa{YCD+>8()5{ zC%d`Ea}(eYN&hudL=JNC4zUEGQi7ygj0zoXgTU%DpB>I5{awntNf%>%V?qR`W(Uy{ zM_+91_9I7Q<*S2BFCogHod?keQwMIm0av`$TR|+z7!#y^Ghb{3PUDXA$?GwzERBbn zv}uVxgRk__2|qON7U{v3{d&36{d*TL?b$H}N9Ol(>6I{bWz*5Tfj>f`Z$81P6IpFXRMB zST~Ui-^F5F^R=jA1s2Euc!kVE>cf_@<)|&GXU8Ro|OpjN<4AOXsuN&r+ zRGUC|o?4UZGD9Tj2&Je2oBgiLoqoFmER!0+qbDmiu`E|SvBQ&bi;`dSc&G(^_&w%p zNEJ+p56AD(M#QEBF$ST^3uEWGm}f1C5=Mf!O~|Mt88FDU{BFiB3ufENeqPm< zik0+=gq$#h1EA@&p`o}pcgQgppLF%}P?3~t>K3Kw`=12VUhUed{EE>Y`al{VMEloCz zrOQWwIOjhHFGZJ!+`6+d7sYKBRdV8@Mt5vcoqgu_bE0H8rCg1bH&^o8>K^@Ozq})K z>=)yI6}tWdEy1zbIePQo4bIO=b>(hb5yFT6pK+~ymKzp95h zKOS=(EE#f#Socg_t3)+NE?jRPWR5+*c-)tUE|gt&*-x_2r=o|7i+-MJTYF^e9wSzJ0T1vj`+VbYLxM(%@mOP=?pCU%B|API>1@V%8FiHPFrENArR2K>B3^5Cu2SREj_KRcub@p)vZ6oG!umjFEg%fxK!mG2?;TS@Z3eQ+ya z$UA-tFn!!YPxz}h+cL0Tlzug_iW`m|=Vi@9G+(zLqM3wP#bq&_JCg!Ud*&>cJ1p2u zyA!#}%jw@t!XH17J$(@WMtj|_`{NOzy;J<-u2xBtMO`(A^=rF-c&YoAOAZ9jfm_Q`(tsB#+Z zySRXLOzc?f>n=4A610!_$Gcx`jX%dE-7P8z?#sq&-*~(0dso;;C{OZLgM)t;4#ZejSw zI5on-PmLb>Bzx0#)%QjTLhaG+;SjBw6MK#6{9EXaB;a+rY7p6oEzKZSMo>R5w7d%Uw?&ix&g$6~U&7)cw{sht#9xdO544@{d4Z!(O5e8X%=2L1UrH za(Ucs5#WF;F6QwWDPM}S0|J8b$m_X z-hY0Knwx6P*vrmh!tfjVK;Z``F67!H7UR#AobqH&XN5)T0&oUeTM2^5;DR9^7NPqs97&|=AHy+$sI2VF8L?-n!dB1ogO>^zx#4MOJ zrnHGkdXkBO0>|(sfkN{KD|vcowwpSxvTIX+Xe*t~^u_eDtD<^O>LF(~xi)Yl)Mr&} zXEi$>?)MgSkbP3JCE)^{Myq1@;OC&;_d&nj)DjVr=lN)2b?caTFx{;T@6S=EC(Goq z(<<^T$Y<_6Y;(n<4;vpVS~ep#!k?G@;v|M-U0{XcICv{d!b6|E8*|8BUZwY`Z?j>+ zM6t{F#v96pmwJ{$G|8WLl2to`bdCAj#~oAcZBB*<1GC*m2T0C~2TsmgMq^(;+u3~- zbW|c#F>jeFa_s3<6sz->zmmK5Zh~pRJ>{1sW>H_tkvj?J8 zGin44g4e>{Q55$exy;1`*7HvJ{urb3)q)snpB10ytl0p!CRsG*8{n1HKL6~>M=Hl;>v+kokKPd+Jjol9Kuhm>(l1H{U6`ErT3sC)*3UGa; z8y3V%+WFst_-4dlA*MG_y#F8d=j9F|;0HVm2dOmw3lB7q@eV|MbB9R(i_TRIB+kJ9 zd_dm&aB=Q@{t^i=xnZ`6M-iC zAzYa*?XZ6CLHGN8KM7;>`-DN)^Gk``PyR4_+aIYc*&EpfJSAUiE-cXk96N;evzHS; zzRw&##Wr?t2oYUZH|qzA7haQBvtoYs0Y-G+yV0267kn`or7SFA&I>{dz%A|n;j*p& zxUBPfmNqBT*^O8GLD%S%7X6jm?sY%G;BaSl=wG*)X2)7nFD1$Un@&?*Y8EUH_>K3I zTM#7-YBkBay_09^qY%tBR~Y_v&X$u0YU?vYuSiZEHa7n_X2U&a&=BdZsfxY*bup83 zk#4U@6$T8DP7J37l~n?jV>0-Yt;j=h4dzRn(KU~yqSZo!oGi<1lE``AO6R42uR*46 z7%mQUW0YjNwlsB%yMeKz#T=})lsLuUsy_q6ppj0>Iy&5@(u(&dA?{xp3)t>k{3h7wm?GF(H_f%kik*5_0oRPam zle>onk^)L4GWMp%!>H0AvZDdq-j_6y2Ft%XU`}}d?;bvTy;=qd`Fgp%G~6(@iBQlS z>N?J$QVksOesD|?_lZx?C)ChoUmd4j?Xh#@4JHS5+M+L&qDBtlgTHf@6-AF86Iu{c z6Y4=9TwGKqbDQqYlx7j0$sFx9O0ak=Nyw=jv_ixUo(8trF^WRgD5*nHym+kVleuPi zx-7D?@4D+uoR`nchT}~q;25yyw-L?~rGvfGV82yzLIgYwM6P>hy%MH{RlB7aT}=z- z5-K!5LC`^6E_y&E!sV|_)EM6=1#78oeJk}EzXFOV8(^I(v)Au8X zNuV1p`MzAzFjown@OXv|MnsPD=qrJZVn&@JZC|tllP6OjWGpi^O#g``F;xq)-1vpN zDx%1Ryg)fwD%#=T^V?;RzyyN?Mqfb3SWoM!!SkX{A}iPbW(<-!VTjj!?a_8E{b1*C zxq(E5YnuheqTF3qShwkDUnt9H#f3K~ZDaM8=DcY3#Vyv-{nV_Y;p{52%d-7{ORFGKLmTDpc$i{iTCpt z%^EdpJR4h%le*~eeMqdN_vG65m$o^$yjX$bT;F`uq!wD!35BEsh7L zLdi8R6bIzG`F4xL>_KMuUq`kzlT5|=1xXRJu|#87uZhw$A$#(HlZ84X#M^zNp3?bb zfnTZyOFgPj0Ot(k&MM7~?PF3M_fJvBV%*vrTPOy3$rV_`&o_BUA%_XV_!qMjf(1^S zhA)Q43DpVVo&QIsnbaGC?5m?9Pkg}0#v{GSm@v+po^OVy-3Mj9no`j8#a^@17V_Es z4w8XhSsV5~E)$WB*o48d^eAn3(Lb@Pnu-sW&vcbMlilCQl~tSdD%{8J>ClQ=&dlvm zZPnRw1KMHl88FMQH2RpO-gu#r`W0I`E7fK5cH1s8?MTqam?CjfKDk!BpDOw|`uCU- z2*8F0-m2M7%Y@7LUFz4b>T?_)KN^Nyc2pbC(d~sdT!bZagdl%frB;9RrM3W$hzP)K zH}hcY#6q^KO8lSdwd%LjPOI)T=@qNH|LZ!{4^IN`l4!aa2Z%y;J?S-9Wp1qHw-}X| z)JDA0UCHcDm}wj>rKg7$%Cc4Z7>;1m45uU<5qyuzkOus6lDl!F5bavbSV{UbBMagL zRzF`ud8GXsyDIB9>z93Vl2)n%mOC}4iQ_Duiw9==cDQ%-!QdcrU%Pp)};EQv^>yB73{C8GPa%V`t(`dOHgZFagtDj z==k{!x}{4@R@nU!8MbRY;P`BlNHc*x-R>4H@4?pH<$T_p?RAGS5_8WqQ6PCz!?+D7#KJQ*qS9Ht^s)xSxI`dTCi zpft)*dpcvJg8$1o-FAG^JWrBHBI?J$PN^68V=+qHX)uGiaWJxe(u5S`?KoKz<{w<< z)WFx>OY#X7Sji71wEGFVYV4XRl!uXh1hu~@BFExhciA&VfqjipkXSwu#P41lHkt6p z#_Iawn7h|#!-hD3`zB@pN*p6-zwp`p`!U~c)6qd}GPxJ`;RFCOiN!^-+*jw!V$jDy zxBBoEy=!X#N>WI)_uGFma{FcxpE@1Xa;@5>k;~R|0?eTEKA`^dMN!*_kw9W7EC|J? z9(}bEHQ6*(y}rr9igiZSFUW7PF%kfs*=?XC+Y8vW5-{)Ax4vS+tXP|fxHV5q)-#C) ze0lV2pLGb8ZLSFKjFH#8{@u;pKj4d0VwWI)K$4mpDiH`AFWdk$6SE51E`Lf;6>4%eVNNU zp^OAwP?XY}e5=e&J6W9d-=u_#1F8Z!)(F|b>zumH!usU~3AhHerlvXcZy$b4k7pE{ zX%m0yuFjm8LOT0+!dFoz?p5;x0{7ZkLsOQ5f~~4K!}K3u zwBKE>tHS|>ARvP>?7%#C=%7z*#3MiY1SE57H($qJdiF!JB2}$3^gbkHFm2>VW1ZD03s2{%?9n_*m8w&9Cp2^NRyPQb@~xiHJuwZ`7JUV zj{wR@UKS_*;s|i{49~P!Zr01W40_XydRtjqoVfaC3mAkD1r#|cM5w`zh%281^6wC& ztF8~hRLuz->%)O#ebdS_yv(`Vsr;u2y4Tuzm)PG)0J)K)cOSodqijFs9 zx#w;sHMg6#mQ$wda(Z48b`H~>Fl;yCiN8GgO_4-G9lcwe_67Mp``DByVQkG;CA+VfVHN>wM59MDeYe0CQ~D3ut@-)-)laD;RabkLb&fS#2Q1i_#TMiU ztdoftAOHq`{Wil>52YUTmv69L9$dd>So_~~n?4}&yRS7KFNIv4xoXOVk&n6t=Gmi$ zrV8#XU^?KO-^XlNDx{|X6hQ!Kz&%Hp=P#%}`{OkwR>sq`C6#}-vtV958&w}ymkpO- zfQnaAZQw)rw&ohn0_U%+PV!hV@g0tSyLBvHA3|uju}kuj)TZ!T?2u*v_$V|Y4~A8QOhM)WA6@+5uivtEsqa`9V+V0cViyWbl%b$f6uK&TH)%5!>*htF(+dBnLKwc#**jX;mDDv z6Ie{l&4Z^c@}$5ZLWNnpSeXU#UmtV|t;9i?XCMz!DjrR#y=9E3eR>?I!Zb)7r%_Ur zcB8+Ofg8xHYa?#LT_Ki+QsVEHrRQJW34+%o&4PStXj>O#FqH*|ipB=y+CiwFZ*MhI z3=X^QUcGf{1)GLkh%1j>pY`6i@`&_cy(JTVqDG*yLT`1MLVI z#r>O?UqRC;us{##>c?4-0k(u-3~ObB!&`@?P&GPeA_qWO!iRI{iLxt_S*{JZ9jJ8R zF$fccKB-2NnW~tVUq`UrhkzDiJN{-qK%qJRUp^cCz@`N|VvmfFUJd^$M;Z{m(MnCR zw#@4!`hHT0Wfm96g56t}p5H$u_d6w=pRP$BYB)U126y$J9?9F$HIED<@6rM3FkW&- zE^{cg5O4s_LWXqad11?(YL_IVty$j1%4;PqY^M_&lG1%9L=cExb`lY}gPr#{McN;| zLsJ|62eqs`k8^#|iI8^;g0MIg8%0NIdjEu2e~1>20pyrQN%vXxAPLZuBZoATgNycJ zGa~S6&z$F(>|PE`JNg{-SK<2bJY_G|um}~x#V%GO(D$7Pbb-kq<-(IbE#h*YIE zF6dOs1EW~T)UGa*oTTqBACt50s8%a}Gv>TKk76!y{#tP3insf_d7|RyISh6~k76;~ zE70isqO@H9>0bG+J18`dHn|Ra3&QMenkgs(t?(w@a@kmG?vg@$rX$BUWVKCCciK&G zi?lwwSEm9FO@EnoeHR+fYpjG9R@A|AYzwnU1nQev2moi=jv%s_z8e(uP#LQCsm{wQ zf#MCe(-p^H6VU7WZfTM%i}J-tIKrxN_hw>(lwC&*GQ&pwt|8;i|N38~iWQ81J8~rq zg1_%4^b>?heV-&-4YD-?A;LzrE0$|r^%XQ5C5tf@!+(!T0<8wPN!in#n!noUv%XZ8 z%QGitV%n$1>U2Pc8Y=TqBz0IF%Rucg|&3aP7W{dDZ=QQLqcRXjcC(^ z{C*3KzY6+~a1RVB{<*6f8(6hBo>Lt-RtJvMRb7%lOcx&a>BFxEJz^k?zs^5osr_ii zY15hNW>!DuMxo^4OVCa; zbn%oO7Sf9swLU0U43=;uAwm1}PKwS=MpmAM0TI9g90j+rooIHIKUj z+?d=LK6B6D+$D&zSdGGtzZitFJeZF!Hng7g^(qe`u+keRmIh zGZN75IyOT&8uPik4)&IW=`|>3{<-EB3M~kj6sn+7?DI-2jMt`CBCY}s;!@aA`4%12 z=TzMPazWr^4$;Fmy?Zs?~{-LRE ze@DsjaC(rbU*ANq)7=5;bQAuJl<(PCgAGX0wz!N-#b`X57 z^2duqj5YG?>lcpxDYyS&OEzE!`~rN@W@dmuFe|EvTaNH;{c9U9zIi|HHbpGNUb33^P64IY(}+!Gzr)}-7OA<=AbkOj7-DFk1HZg=Y3nJji(Jp zo{bnM<}+*{`BtI>U-yj*ODGbQyN;6L$yoIT?0ne3o8ZYR2niVpL*+l~fORH!_y`EI zO?2sE=1=-%WWpDFal4_4IeZ3j_B~%UC%=;WzWp_`Qrc%5$W{!yRY*5YM+*CD?{PTI zK8g7V{E-tkEwpEigb_*HqxeZLT1rOeYua_-&_ff)YY^u?ptj30)>)7wRhMV&Z8bM= z*sDD{I_socAu4-}@z6QVclqli_cv}Uqdu{mU;}KmmqX%`DVz_smH z*F4dCldF9l8t42Mmt;_MTchoXLUS(N&Kb*ZdRjC)#qPr$5qviWsLFn3^K;?&!-e;f3IozR*`aslo%QkD7k>3OWMPI!h(b&_^|o=W(^LUM4a4}qEIr@>v^gZN z*(7nRGi)b=6v}FbqOh&6b3rIy-cx$$(7yH{h4bCCpfg2P)q%LAB=(kZ<5^nYwQmIm z-ByM9wKyZvk%*zc!x|E<*4+L*85FmGosl6$7CBBI;)m*;Ws2c=tf!;aWRR z)aF+wkBqUVctL>F;B2nuYfjxd$_0NaxGrf;!kCm1{#@Ez70I1c{>arko1tXeh- zG)~qtL{_Q4;hmPX)E`Hh4jZBge6oNTFmxnFOvXnT?^ArD`}XVCj{D{qQ=#`oF4L$} z{qN!?&)ED4iB+AQEv2fzpL~B40dbVg;1vHN+Vhm9Q|9{P7QqA43qp007GFlfS3*#^ zBs`xvaa&uK2zEmBBfIpQDQ8jY%By2hEH6Z%;bsNjZ?}^W#9Y)~WRt`!xIucVx9@bd zhv3B8J|)-?J*3AYgUIz?G1n-P+I@*`%SKt;KN=I0R3iTHSkb`GuOn$RkDOq)$#ZkV zeN%tRTX+9SQ!f+pHn^&~Rhak*JKh!%GW(1Wfa3wr^cNrUp*XJe5Tn*GXLSJBOF2ec z_djTyX}arb>Ol`4p7SP??Ei@`A4RyRmB;Qhez)+nnVJ)R0d>sA!=XbE37-Fmjqu&-{Dh{|->sS{;&CA|>@ROxm+t7kTzO;J-S5olAFZ zZBL@LH}XjbPfD~i=DTfxxsy_t*DD0Y2Q~ofvj`FsMw?Z(0FXxF1D#z1-6^LN?Ibre z9$W^DuQDlvXE$R5dp#wu9)>z|zc{9YJP)!sy5r}8Dq>Q!_E>a-e7U!ayT<_SfGePG zGC+M(s2sYSnU~G88rjmRHE&phv%dAMe6rIUmF4*JzTer-nlT0&kJ%LNc@%v1os(jE zJpVb$l%fMzL)!B!HaXFQ@ozbJH3fHaGCq1BKe-A{0Yiju4*PORmz0~1G0_@IJO3>H zxFD%NZy^Z1H5M@H2)nlvEI22$^kzd03S4N?(#22SY;WY>D4F$`JHA3@usO$2i@|vD zpDLij>pt9JfbM+ZW9c!%sjBQ#y&(b~x+}B^vd)Z*RG9s}Xl=pyd1&q}%WqFA-HGJ% zvVELp$T7a(R-wIUywaLirFI$cb+;;%0QmZ1B7ufN-BRvV8cDMV@Pr-mCYvCobn(OI z=i_K!Z4a|Kw^!`ji(}!nn7TrSH&RD`bEK_=86nT#dFPOX_SgrPBr*whGQQ^%3!cxN zA8oW-bP0SA9KY1x*}1pG(ZIG)OrOpZwBuFVr&yD)k9(C;Kj@Md-Mlz9|mPA0-Y$nLo6K zCUn_LowZZB`d=RIgloY7Q|CupTg3XvEVw66JXHYizbNb? zFbH7s{PYk^JAek(Uow|q(L{5z$pKWt@9})AD!kf!VQrm>I4wNc(3F#;sNd}Gvpe11 z-XduHq5fg7N~#y_>6>_Q5U01=k@6MsmL9y~Du0K@2{yd6;U98&3{$+ z)w9P5y4&4Mk)qJ@Tbk_YIR!qaoAGkU%K-H-hfsA>#dJa36k`t$_#E5IaJt0RfxaHP zw3NrX<$-g!nk5YSsY1HE4bk8u1vn{)$xCLAahZ2a-YCqvJIKzI*=<%oW_ zHs03O-W7(9f9_l@80J3ud;dV^gS^8#fs3jP@+8(A@`*- zmb4PyDvP~bu#hx=3V-!eDrYJTu$G#uHUCuvzBWu0^5Jd)3+_mu$^m=$%lji9qVTNc z?Dr}^gPxv{WhBzZrN1{Ofge6gOcwAxoo$fC`bp~M#}a1}PvVCKcV8I@uKEuTQfP%a zk);NqUdRA~q#>dbo=#Io>UN`tP4i4wn6kQ)C%TC*==byPUg)*%q^1oF{KuG=>hYoR z9NqWzjPN=|u@5a*1X$zVV)vhZvEm=N6Dbxq24~6)rCbOh*-;BN@a#PsRSl#xg?r6v z+hO_6ddSD8hz%c#O1pNEb81MQhyDrp{g(g+27!*3Op;T^BWPPys}-t{uGYNvSZe7d zScOu;|K2=Q_S|xlfVp*eZXloWHM(am8i>Mvntjjv_U*8zXuJ}};%8y7H>{bY@2%Sv zV$Ac?lzVoJ zm_|oiRu*PG$NWpoeSB#5J{IKfd8%CHk)E$Ip)143IE?A}ZpQ|shwA#< zbH9jfaE_*MzI0o8&uMpue9rZBC2ZTlY>LTsA*O3i*7LMp)y3I>ee-(k&zgp#S`7BzsNY?i0t4BN3|I%5V(~cnY&2(yg#xo_g8eCvF z-nL1D+lh$$rp(|R-W7{Z>|5omj|ydes!qudkC#L~<9+|Na;|Mv3%GNN!onAC2COFh z0JDVa9nY(#wQx}1#hz(kDa=-gC5OMnoM&AuQ1MjlZW*}pR{G6Rck$f5BJ~f^5+Ncd435fQ4g(2u;4Bn+7)Jpq+lQ z@$ofc8q=u6)MbN7c!GY2Uc^7u^#u3$M}zgQNukeqoL`;?i?BoQWlO9i@1{?W{&;-9 z9KxpMG+sSH%-!lyy2VRlR!#}?AB;Hv6WqWtE~0i{rmNjK`1;iM|L4@L9x_1x+dqGD zSJ6{JVSJo%tm}TFWY*n zSgY>mP#{W~!tW)^tse*3K&~wW%aaqHwD-O26*$D@B~uVk3xYV;`F>zuSv#e$*$XY2N+_F>sM) zS}4A;NBQfgo5PFjy7%2aq+Hu>x4>+!1&BJ8!>OvTIV?pfWkMB-wxvwvCL^w-aDkzT<`msIiI_7!z4lY=k-$0D`0%KZ|Y;K~}#!6@H zJ%8PC)*m9NlO-_^fxA>7TEf`VNZAAQ%I2%jy59dvh-CL3s>w!=@sW~x4GYG^F~*&7 zj!a@*cJGSY@TT=U-|-lDDb-xjZ>UhI&lcYMua7m=iE``{IS~~#I3-!Abakaa&+S6h zipIz7%J^H?hf@*{td7s5>|f&@HTj}g68VyvwkbNoSIip9K*7~?XFAYObeN-anicsE z-;*59YVW>zj)muLj}EZh(xj0AN8#e=!a36-ou4*X7uLzm@$a6xgs0h$i&&yv_g#Km zU&LLY<*Vyio02c0%ogI#3V+D#tz_{N^;}=b+go(VNRlH)>G<=3s16eT8d^rQ{bp6i zfsUeX@x0M2PTD)t*5vh>!yaE)x!D#PE@#HHm%gerYq{S^7CelOJMs|nky_W?@^eiw$^J&1Yu%I3tw6+(|EZS>&UEAUk~`N#LI zfrmjNIp0a3vux&EaE&(cs+M<-w-jk7|3rUD{X{EG%8YjTL~9xl3?FJ`LYJHUj2`Tz zvmYqSe!Cub=Rv;jRzY9!gZt&G?-)w?+qDI!_HVgqV4hBLxI7CK+ou~@1Qg`Ntn zw-80X%OS2!DLkQ03bkOL+LDJxlT;Q)MpC9-cG-R>^F89N;+!eKR#*cL{UV8ueA>QJ zvz0!y+?m~ZC8G*2Md^E=lLP!Vn#h=Sf2>7?Mc;ylD++=O63#Gs&t}CwZ)zl44>>r| z47^?QHwz9=DwJHw!2S?B8VrBW01H6NNEK4f zF=Y_dMHD~ZqUV$gr4Jui2!(gU8&8fN{w=zxxDKUhGL(Z)6v3Elqi*@-ateFZKHa3B zeLH`DAp9!>j!d+kbn-(HtGU97I?HD1B&d9pw^q2c^4ZS`_MydbO=X5nepPtdG|6w; zp!4q9>|_q zX7t`_u!y6-Nn+o@j_1#J2S-iOkfrT`pyU+_pP$aSS|t8n}Jyb1&VunjqUufqBi1Z{<+7lt2bFa8L{h+toX5L4k= zEBFmC0j9Zh*#Zs#LEY(b56*t8C7@1kP*ULnZ-)nNs8$H6w?d&RYSPe@d> zkGGtX$;S805iXjW1}kfm0Yz^M)UqyJJSn#zLeO7o#xgCm-C&=)`e_GPN4fA?pO8q{ ziO%V^T}G-D$bThNJI3*eJmYg|@k)SFi^1A( ztX?($qSku{K`B^a9~3HI#9TPXRHPjuqnxmiVB={#h=NA$votle8eg7F7Zw>dk>;0k z&85_H-*Ml7PY>Ub+jd9^O})`Z_hT|rd~T@Ic0BIT3@?KSHDwgexFEL_@SQoy@k>BVck?iE{K$@v7sk*xH8_nELeRR z)HdYhQTN`>G{P@|DdPr|RA8#PTrmByKjCU!K11=4h>eqteb?P9+&T)|UovrECqoC2 zT1Ar$`dsf&8DkD8$1tO}oI;+es=i|dZpBF*)r=KK>+VuJyZ2Rn05c=<7gDn~Y+E=9^zXt?>9<)oPNUP%=UV zRxD?9a*|FY8>g9A?nhSoR1pP;c6JXd9g*n{PGWg&|rA^WL*wUK-A^A79G)|BKMp=FNdGMf|LVEf| zDSbHuJCai}f zRJa1yb(bQ)+nsi{v)ksFPa$g^=Z3@~eNBITyP;nZSKU5yWYo}hl3_iKH^3I&_n@(^ z%|y>o=Gt}N49Cl>E-8YhOSFRFKf9)~;(+c$FY$|Gzr_$tfWbd;V3Do5`s?E9d8s=$ zDScP9&PVW&>n`UHD7Y`GMw7-UNS38O@~IGY=6x^`zw%YT-2u1{z~4W@sZvb+jS20> zwhuh0Vhq6pn}yBJ>{Zq(Lt$gZOY0SD#Gp{;^arfJDYxy)ts*+p>D$G#m*#|gR*X!C zzk|oRD!NhVdBVJYrAgtfR1K8Fm0PKgwkt|1U%VEVvi%8yFS%>2pWf9!!))?M7{TS| z*BQ||VY06%4aKpe2l!m6QP6}o4umVGx4@n7iy&N4aPRbe=KR0H72=k~A%j(-AYzYJ z@OU?=m-kZErL_h{2Jq$TF-}S29|P%6Q}WJ96Z%ppJ|2W8tXb(h40N=)8KNNBmIut> z$1y5~757eG+m>HoZ(+$$M8CUwF?OCoU`m+Gg$b&#Fl0&osg*~=vbgn-e)GH~)hgJ* zsLdzL_a9p)s9&L)+-ps~Oh%28wI&Y*%U9j|%4^^LF0S{#h6mXz2;DDP`ujg*Np;tU zTfWIsYF}FOv>Sg|;%UqT9m)Ic`|R5nVuQ-D&I|JZYk*@3EP)i?rRi|G2wmf}i_)gY z3SwnXGI1$iCtLB7>Be0Q>#ZczTM4y#jt+k?%A~E{JC#S_mrMr*^U&P8cTqi!!nE~y zrSl8XJSueZ7|5e|4#_}pqNPZdziVEgYIv|T5_HL2m#1vM3CklZumHk~>1Zj` z_xh|pcTaTib@Ea8G_kQ1sMJC(eB9>6wHMLYBE!QNSl`mZAVekueD|clQXgAfYx1S5 z_`#`0-a8KrXc^DmXQ^*o-RqRiWGVyZU|$BOGO#6)1_$!xWi`VoclW~W+b!=$eB8U9 z^qzCi$#y@W`zNd!yS=?1MO?Z2PjoDyJlJEcU&%5nuScPt3#H57+MKZxXyRqM%?lzI z+B$7*GRf3PD3meNVf$AT`z1p6a20m7W82~k)Hm;^uNfF(#0AG&`7qd6=rCbL>n4D( zI!1|Kmpq;rN@h-{P@dkhIIxBT-e`xIsJsD>8M&VO$-N-+kkzUHl-~nXjZ%TcL+lu9%Gf5x^hLe{nclvp2F0Cj#VgAh;LDS<@?Lz#Kv(?3n)hM_ddWA z95sQd4=3*p!8S5N3ECj@eARJcpf^D9zH7FFa@S=ddbSp@ab6e84M;r?!Rxwi152}= zLX{NLWZPjH=ucD-rYDuf?PK%@dV)EVLF;;}fe2zqom=L2+HPQ`D)c%=KMxdsS4tD- zay)nT`y(d|8pLKz&}XZ1`1|X<)sDQmSBf9&)T*m;q&ZzRBWDy4P`EOA!!W?%ZK)9c zLCC9{Q3(&u8MF)STdQ!Dt$91S;AwZbUmy;+a(c^Rz-IudVD+#iTa1MUwqA!mMg&y> zjWo2hEgH=)*Cc+!*ZB;OE$z(#`>>9S?7pssI{|bV*>(a~Xeu@*K>mbklY4s!jAKu@;4P@MVqmVhV8x ztl)Ep600OXHNJq8#&l%uzQiOG2%AR@%pzJ*ZSCt>bfyl#-am60%hJ3k_Wb#R+qbWy zYY?*x#GT!23ioSIC1)!+1{G=7kehxt7){ZyrJpkn@-dG-%1i&fY~tw0iG{1)W}dwj zl&35cFMhjpkh&>tb|v?d3u;maSdM=%#3GKZ{vm-q!I^Dm0*))%F0oT7-U7c8Obw1J zw8^fA8OP3Fl7I?*tu;_djh=ORMcFUo-36^5gB42(9mjj_1OTMfUti*~&Z1<8nU&>o z$sl>FLEjHKqqe%0y_aI-f;vyKhMFDA4YZs1i8J@BLb-%gBc)@?6&0hy8X3RChtszB3J*V`WrcW z&()I0^r*Zwo@8x1dHl2fR{ES!k>_^7Ajhw2zxYdpXVpr&_yuFYkWi#*vs}e3ko(AX}n%&-t%u zcKwrm{&N*&LU<*bFP%Xrg7cw-1HkahgDMZiwq4QJQnxsAd|kqy7{D`Ufv?L9-P=X$ zV<4tn_W-@V$i=&7QO9q2v_On6Txh{VK@mx8sfBz|K&xsFY};AQIwu#P+g9(3rviGv0H2c0EU$@&8e+;;6`IS7%Hw@oVTw;^DwRvY^XqrWK-s86e`iLGJ zsd_EcXsNEuh77OGvKy1Gs%~EXxMe`IEv9@Ef{xDAJ>PH;W*ny9$0YWyf}hvQho<4y zkb7KdR6S%GKP9>64+?#5_v}T|jXtXlsu-@iarHdP*ZKqHowO%quN?}IXo+!|=`tt( zanoIt5gq%qz5VH{rKRFZdB)9jvR8%c*Ik`$=Xhg(Ts-hu=XNtGx=lNVj!?L|&`Pos z!$Txh_B)%h^Hq?k?d3s(dt=%P2ZzK6)te+@m(0IeB$O~e#)zZUs@;TX=A`kpO;+-r zLO-gO91d=c%j+%r)Vqiu(MB<;DjzMr+jt+%TMM%~D<6&STwmPX!aTmOjA72_((H`{ z@qBahEz5Fv?VVGU${^=kDpVO`SQ(ofD+@KaY9jlw#oNvOf*){0=W%atbj|kn_fp@! z_JI7WgKLt~96oFPb6<-r_xJ^nR>VO2w{(c}L5_wDjalj^dm_@PGj=mVDJJ(Gcn;As z7~Pk!9r&fdly(&{sPX7LHqL8e#~`)-;ogB~t1q9YuT4bfmg;0EEtr5*7!#E9!|LrS zO|xeKYqT^II=>cvq`fMq%{LbIOHGGCPf>_T@s8C(%YpA!X>wU5g@={&#QD8%l%HXE zdZ-)6s8i#*~G6?FC|{s)&bYfec0xa7k;Sae+D;@x?crxGr<1T+*2tjY^nC{ zi>FycE@5=QqOv{6IeX>IL9TZS=nuXFdYbNA!-y?y-I^c)u-eN=tqhbS)5T;7z>dNTS8-Kss_T6bec+c~iL61UxyPkUIO)Nd1ti8cq zP^8TBXFHPsUibXKj4yqm`JKNcO=xC z6swnGH{+8&R52^nc?DLSHgO%QnpPzoVjvs=IsY!r?~El)6{U4KdFe)1U1~-bo^$K6 zT$Mp0_~h>bj`?|`X>%`quT6|QA7ifrfmrr+IT9+IW6zJi;ZJMd%Zm;Db>&NrUS6>| zf0}6XW!|&jexI_O-SDs=8qO3(-S4^zvi)MOWnD9bWrRc_>tnEysMoRO4KAf((@%Hc+l*Vgy-5r<3m{aV=PeE)v#(!G^? z*o6p)D)&OiY%wzxJn&0up_yN0-@Y!5e@jtt_0+H*CkOr|NA%fRYJ<)nmo#SWBRQA*LLNQXXUybeX5}FFaLdh2A;mAC(m|WDDIB? zsW0~K)**51C)!U3Q?{$a2=T36Av$0FJtxMNP>D^c zaBp|8ZBF!YZ`aX-%*GTkfn(fn_PJ~#k?PI#eWz`n4l=Uv)3^9Kz(ESpQx|>mpm;{7 zPG1Bo+xL+gTpuA(+S=F#k417dRdg!S5?t+xf{HI*_# zeA6xcGCYeHtE(RQm^0b3a3q{v<~p&n)Lvw-y~MSX`L$zZ&fuRfiduZD)LzOQ&AIE} z>z?9nSBoE|dUPol_2$pt;_ zGQfdyj3*7`F+RBO(edr~JWX$dFqVk@a?1vlPijSU4EA08)fH6rW^Fz?V1|}&yhsr* z^e`RIuIpH?JS?fB%|P23_cD4Q*vq)2pXl>{nXr8cGunvtYps!7 ze}U4*>t~bib`Fa$%UcF{KVFG3!xzcU`q<1^rqUBLb|`3@?eNatvDeJm z5H4%Zr^xsS^2)%B%cd77$1PGl2Udo_)w^9ld-LQCJ?l>jDZg7ASDM@^E-ndNu38de zUT>Sahm*OJ$|@plr2OVAhx2WHmV2#DJqsA;#LcJIg9$mA+h@&|(4LsvPtpWUWx!3T zJx=?~$X~F{_LdgSo}3?iwMxS7ZR%`v-2BlVQv(nYJ3FBL2b!4gW0mSTvHI zpgkh^difQ zsLj1s_wOf2zWa$TRRsH<(fCV+V>79Ov`O-Ij;8p~l*VTMISv3>T1g|hv*w{v?XJfe zYR=?vnljP?^}W2-5u7j*(KfTEa&>gpryAu6PNA%ib;tf|2!P)R5#B-BFuwa~H19S- z)!uZrL!TX}q_;nZ9X+6w{A%EeDEW;8u7aHtKe#4`~+F>ehbz_whj{L6Ya>gEqBgClCsRJ zZnrD#XEH~|Xu68lZ@D@b@Eiw8+C4Vhik29h)v@|eKm834aEW9mLacHRmEW0kr@C5@ zUyvIvJd1K;-v_?!0fHy8~`k*OqLzkKP2f&8Didda} zysypN!r$&c(p(toe3P|`#whjcxWXH``~oE#Dn%FfnZDq+tpEE^;@z-JHS><#6#sb# zhFeOh$-O}=LU2_-!H7h0PI<>(hje3#tm?M8(%;_diX*Vyn3_dRfOTa@RrHYr>fs4z z_=i_HarLt7=I4Ssl4ECBr-cL?9xq#zdxI@PTFaiinlQlRn6vA&SH11fTT%Me+2!J{ zeu3mEYwS$mC$RCVSIOwBDXr0jX0eCy?F!1h7hKR_r89Lmgv3mo&S|};a5s7SMa;5C z2D!sm?Rs#98AZ%rzFnk|V!zz|Y0v81rsfjqr@3uRwOjSN#2z`#FialhvRxeT8xw{k zZAMc(KWspXgP`r82HDMpCuClHl@F#ZSl1rnWh%O8h{pLi@$s3$>6Q z-B#hXUpj3QR-I9uI%&NszweN28mYe6*#k!R>>kkWTz~l#{SyVX^}b?Na>CQ-l+}ny zyYB&sku?{Tff=lydwRa}Oeo#zDV{4YQUGlEoIVcV+s^S?2YeJ|)V6Rv3&;P;7N66H|e>FpJL~FCs2tlfv-}v$(Q;@4F@1Ck~ ze`0<_Z=|8z)P*UoP@H>AhTEQ390EQ7hA_ko&0loX{9f}UP_5JX2nrCc|EL8GvQfjEV$#a{%)A3 z`pk~cdW3rK8OjkRNS_MD*MVM7Scw;YBM)I6<77I+yYhGsN59I9*r3ZOd9ly;AXQe61qF;qfEsv6RtXvpSk( z8lFbQ)-fDao|pHmDE7LLuIv;8(Xsw{`K_C)^ZZwk7P(nqJ0r}Rbkxftu&NLbfXPWw z$^Qr~aka$ca0P*6$RRpmpY5b9gDPqFFp+#~-xrl(Q^M?T-B>bD_D>SL2*G_5U9;GA z4B-OXW{B>lCVxN&$qN<|(K?2gXT~dt=w8y#-Fjc<%_pT>+Qu9XutSa~*Wiy(TbW=? zu(GE2>ubNFOGon9r)d;D>T*{!4ZX9D-B^YWgL?~EV@H=Q)GHtTb^mByib9KR$J4vJ zkD*FZ&!P{SlJ-eoB7CnN3x6W}^I&~jktvw!4@snIliT>tDy-jX_eEv)TA};IsU~hl zSL)9?mcwSGC_C07ql8GUjxg5(OyKKZkF8%U?l(6pQGv5$0 zRk}~EAk>%7y(^XWSAN~Z%dnfTw0U{CRNC+4?B7`*T2a9^sPT$=C?gqiqeitqdzTm= z>$Da}*}9S@YC~aeNo5H{D@+=GGPL#MO`;Ov@F#YBp4UXW(YLvjkeZNlY$%=Vr=FKjEPYOQQnuYJ z_Wc$0cH<07eW;JKv3}2kSI+0Y6@>bo-KZDsl2qo;{-ODqd1q$tDKEW%?lW@NR7Emz znC+SW?7QY97Vvk9jd%)$J|w?2YlYRZyV@tlAWrg znZC`*d&Hw0nk!fB*BCEX6YQs3E7v9&5}mv1*rvPoO@+9+Z8c0o{k|ntDBGuPfafiu z==ZYNZA{8_6&g8nyk6XHDX21Ve^i8=ErkbG<)chjK8iXT&^UwSMPX^|l+8|(9seL8 zhiyl@Jea)f;(tc|R{Uv-_RDAT2FX>)NUW*9X#L7;EjCFfe7hs}pidUJUG0~gM~Fzn zJ5-LTxuM^u)I~F1Crc3=Nm5b1qG_9WfGcCJLa^fIa;W;HND6Ivdp*R>OV$Bkbs&); z8%e2qTU~LTAFIs|nd@72bv}QI9RDHV==}zZ)U4rFYe=6}ZRO$12d+BJyV70>$dTNY zR`U?@yucY$p`C|KRhv7zjFrxKZ-+gcQn(LXhNGROn%Qvt+0^vQr#zbpq@mmPZR4x` zsxSWQ?7MALH{`Xl&a&@7x%VwmZ3gLEudVu5%fXrNP#??HHB&ny>HpyoYkBXim~#pH zeeFz5Dy=X0wvya2c1#xW88{I0wc(n?xdUALZ3vTom#np*WXRt+c9gVVL05{~+DJufk7MNNm}}ik9}2 zzPv&EsjJ~jdMUN75ePD;!|JFP8Nf3Gjq{$Q_ocd`WbCDHy4-&AYHVr6mWDL_w&PO% zOWXTbyf1~R73asejhac)dRY2L;;mlZ`E%TZzv9mUQj`F}Ic!dV{A$b%jjNj`&X(Uz zm@nH?H49itoKx$#6Tr2Qm$zb|PceAd6`NKh@)q8mU}r z2KCUb>93Ccj@E81-5x>?2-m)eg{(C-E@1*f%x%&IKXo$MKN%i0emmJwJCg0*UAX1u zpeZ#UWOq2Qs`J`*#aP7TX{pw!fQpe9zg7(+XWHUI?W>m{<}dG~_fmkMI3; zhgHdO_1$K3N$ysviO=&{z4>I#N#MYWm%^8O`slXHmA+X+y=HO!K)QanotrYassrR% zdv}uKeSaeFCMbgm<+D;T*+AL4n4)M=7Mm(FFmN2)?ywF`zq+8UkM_FG<)OvnZ~hsgu3?f*aqo z$8SkgcN24z1ezYf^G+l~dV$q|dxWKL=eFWr{l5bu7 z+S;ezdEC_Qv~3(KJ1&aXklkVm@H{ zof9WY3K_VUm{}d1E;$bYN0mH_E<}?ITxkB#{erbmTZ^gi+C zAd{NR%!WgyF|=Ie2AcyIHOMVmI(5^wlVjv%RI?^$n}V)*|JulHU#!YG(o4~hGA%YX z(9J2!mC<7MZo4tdak<0F7FgJmyh!G#oXfXCf_2)_ZFLR!(Z@Y0^8Oq*JyMT!$(E!X zb+N!cYi4yx`=n1d!F$-mq8ut7GWXW=0T&$M(?FRdIkv=roim3V;gO*US1iTm(np>Ufge93oCq-pYH znbd{2${VM?JF(+vf%747NJM^jI)>HEkf|u!Y*zXKiR@a~lZbFX(Tft$W%p6&x?G4n z25cdWxjvpB(%pQYnuT(7nNs++d!1|cJnkvFmuK7HLwbDUxJ7~i7i1oZPA-QZH{ae1 zm+*5nryeA5)W?BK3f6XJFHJ588isJ3ybtar`*S?@&!>AgdHF%Nx{|T9n^c4aI*A$% zwP9_7pu-Pc_cW|+TszOqxyb+3A-dts5;oETt5TSKoqWE!s4T^D?^A8fMdnAg=1>`{ z9Xoh1(;yoaDo>%S*73yqo9c#j|H6}W(K^%4psTv4k=w<|uH^nXJj9{isAoovw~Eky zH@AwLuK%nJ-Djc&H=8#)W<%R2+e9Jr;I-!o4Q8L-wI24DraV0#H`NT3n<(C{D~9#R zCM`@tA9jW>wno_M;4Y639%Tq~Zx4AXRFvYT4IaEfZnBwoagzHZyV}Xd>$5$d8`V;e zJZDngNK#jtYGv{Kl|Fs5i5c7wo)GBJhBEl$CLp;e@_i0k%e0M%AHYmmAjM&RAINljGF9ZjQsP@hx%1{UWtmr13IdaN!9AB@IBi& zHG-~oJM@ezjAK^g3!Pa}o{^Px|B~9PAFUM!&MVgnn|6i-N`YH=wPGlb{;Z-fWb|#{Ki64o`%VCk9h5m5sGUy#F)P90~8}ATZ&4 zS?$ocMf|m*EIP=XYRSpN{fWm3lOx+UtQY!3{W%&ainEW2$--9?n3&WP8X}qX4s2J* zqUWh$Yvb=vDhul;!hDmb_`?Arya?ceXt65zq&dfDjrDJ?Dc_508mDos|FHQUKlUT6MNt>r#$}M42p{=HK+ymBCy~u?;61DSP_n?x<(khv@$?6g+ zaInV|(ac4D*Z1|ca#));pFXV7$UC;j{lxOvO9mBM&G$S&UmTM$s#k3+L@!-h8uYt$ z5B@Q$VrWzO8Jh-%R z=zA6?b6P&{_A{|?4sx1yS1rpx_>{4$5}Uk}5O178n`}a(ELMfKE`}9(K*67boV}m} z?ZLw*7}k6bGCVbI(*!y@JSt-JE+w&S=riqLa^2b{m`!y<4r7+%=)28d*nMvAcG#L4f8s~=`wD~pG~_M%&L!7NjXtNo57UVE?=f| z@kf(=#L^laRs}hwR-xtlq=8XuGGH}&Q#V@kLe%O2XwR*mOZllQOoQ}Mm%2r2vlmt+ zCI@-6M}>B3K9^*^vFMPh1*@AWnAIcs9VGR3Da`5?779R~6dO93LayB+KBO@smI>gStTgA%8 zPOPP;qk;VHrDkMjrC3Elv@GmQe-UtS96SK;r=+LfcQ7F>Gbb-QEg}NqWa2pZHVSN3@BmFWchH2l!cR%>&OwV zWH|^O29dIX9*!M50?YX0F{|HRT!CeR@z5wNgW5wD3XyUiJ;r_f_%T>I2#;BEmX-!} zUtwwVo;~Ct5b06w<2<~)$6?96c>G*`{?j2meo|QykN**n3dO>b7>YdQApuwvp~8uhrQq>_q6m>F zOo1UMCnfQRNErZ$h^Qz|7|@Ks!sMd$c)Xo39={Oq36g<@VG1lc85t=F4kBX(bm9`? zBCsGO9zPWsdA9}pkro8v%ff=>6cpqLAt?zAksTHl6PJ{d6odJL@T4pD{QP+QY`_Od z0_F!N+>`qdDpEkkEiNf7BP$~X^9JD2Go|NYULeDl5MJ`3#Z4cC2n&b=0EwJ}ybR1u zipP(ss!H+ra|5!D5N@)O<;`(Gg~%o%D<`k0q$mp?1$D#0$iEYT3Gh*}(dEqzK!XM} zQt}E)$|}kVFc*=AD+CX7k%Ib7UJ|T7L?)}Kta3tCRSD)GR&#)A4icog7}2F7sMFBY zIFZaoEL+C-L*%5YYU&y%wX|*|GowbA;Z5j1DBO<}ojPr0o6N9N*bNHVHBX*8t!?0F zle~YYa0(P2*E+3z=B%T=RWcp15VbCkgUCg-&*YX(%d{XkF^!1y{cOPnM>w_9GZGBU#0hHgUpBmQ_39Oa%a;w3s%yb5+V(HqJ-vMcgG0k3U%$emnD0}|Yk;^J2VqeRx|a=L z!$Y9Mw_UycLnEVO-@cDe{P;OJH9a#sH@~pBvbF(eM+2avBperaWN7ag9QjJ5`-^O8 zd36+PpuyWgZU$D$3wL{5DDh+ zg-e$;gCHu^#P|KkU`NMVGS%)u7;*_6EI1t&V5nU4-JG(0Yx(<&fLFjj_ zJ#Zhor$G{+YtQs>JcPbk{~6au(%;wH+x`N8>%h#+NF0PNZRx`G!TltCy*)jhwKxc6 zJOa-^ld%xGuB{jD3+PAn^};=r-Ocx*xUm@^{)~GRgnri4i34?*fdQnJw7aXlYh9_qfM-Z&XXoZ- zXBr|PQ~{6#)7R7WC7_e6tLt-n`zIj7IBH@7{(+ttZw0MOaQ&#BP6R!nH*i0Cpt}Wu zPt=EgcmUN|58zWI41(%$;6v?yqi1ngD0uQ09zYLv)&3`XzWVq)1cEwuTK+Had{xs} z77RgPWC;I%!%jfaSb04F{0=Y}J<`p8Lnmn|plSGU&mTgE4h+D9C_wc;z>^G+HZ;_K z%*R1cx<8<-`*-Xtt!`|nudl0l4g>w-2GK*^b^ijLrQNGdfU33%hS0AD2jL+UAp0-q zTv!{fudA!Q1z1)31CsiG0nXuh{7PMIZ8i|A4mX4z?y3JT+#Fe0TdS?D5(FeI2%EZp zpe9n=S_At-PzR_4&Hs*>fII$YG0^bLmz;GyK!GJqobev#0)1YO| z$O!H$=|D$y*~^zD@CTBQAFHctYQkzUP2CfV0eHv{hW5F%i~uMc>igW<)KuNq*WZs= zRv=IeW^`hH1rXKapuH5)T_aydh6X_Wm#OJ#|CxZd*s^RROH+f6zBP@+=6#s^xYqEcq{^`yZn=PtP?IKIXN&1PNW63dHGMCJx#N-x3{}#=O`8dVQ&N`C4;88L^xqze0)lJ zb}pbO0B!AV+S=JG1MItn)WeCm1YA7rgN*FFf+ra})u3J<0GKnJgh@<@zYE90G4LJQ z#0P2FxluQ5Z``o4vb3_Xy#`1;afzsVu?WVI`Xwa9$H#^v7zYL7;!!c70ODkTIzr>& zd#LEZ|Him?4}c0I@7;@wiw^itjBDs_1{ik-jziy#3izKMV#C0APcVdv1tOv%{r?r^ z8iyt(M?Jv`Rfc0RF)-apQT`dUIt@D-vLzr3+7seCuimt7dpW-S;YXg zpu*vQ2fEg;Q?m=pzwl#Vp*X;IFwxQBe*c1Wt(itYk$rv1E3^NNasBT*qf|AKW|XY@>0@EdIa7JT6dOn7+k?f(M1lV|kweyuHojU0uG zfWy&YLEis>JIyn?x+5Do0P%yu!{IPgpw~YD52=nE0qP8f!!V(tfgS+ykg^Mwpao-S zC>(+g_O}O+r+Eg}g#`Q|j8;f+FdT&PxCuZ{LmSqClz~5ZH8?mZDA3>KCO|!6;YrZk zA}9zBKzq901gM7;qR#9CPNHpKK!Crum#ZB>Jq>M~4kQhb&4F0v>1y{E>ZzZ`oq;dc%3+2F+ zc=^D$F$gn&dupfrwV@L*gac(LcSnGG>PX2+(AL8Tl+k;8INvY_{-lPwn(B!YD#}Vq zii*Js7{wEsrvkL0V=%P;l)I15?c3h&&S0VGozXsh`jnQ|Nmvs+-mi{R!>DVXIt>UF za1b5o6_4BA-d^r*Zmws}ojt3kqZ4oj)`m~xPNB3;1)hdf0Rl2uc>{?_y}ZupojZRX zJ_nzL^7zPP8Zg}oxx~ptIGgPRB}Qn$UHsW zIJuQ|F2H|?usS*#68ix-qR+bl3Y6z*;IgvIYhT!lG?=G%hNOnA~`6d zMU(?`R!ed}07*_udkV0^X+%$+J1w=p46?b2#MhX`DnhaXj*u)5UUE1Bf(xXJz4uSZ z$UF|hLo+xTP=>^dovPA11=64ZadXD=^Iy&4@hOsz@c1JCR45TA32G46rV)gN7gq5- z;(2)dr4VsYiuf`OAPgMAPmAW_@fSlxK_RlH8$jH5as}Tj3`)EGKS8QEVNipFdBc&B z55D2?_XQsUF*I<3pcskiI;8k>@c1VG50D~`ACv(vg#2rw1TSwk9nu0{o=_Wn|z*0$v#KLRAs|Pn-Xz&HrC*)5aND z@ui6;D?EdQ<-8y94*G#)_6{|H;e|8UUfbQp?H4}pO4a8N;d zAoKtfU{X>*-158hF(|}(fcz@7|(=Di!N?!#>JzcqY-H1rk!TSJngM~@Jj z!mOx6z?BF?`gA6?&C7e3?E|F#-D?ser{iHDC+aW|6h4AIO3bMe#bw1Ef}s$kxjR#PC&Z8ss39hpgDXLdkmy>fp(DbvciYZEX)Eh6aWaR0yB4*Jbsj$eeZ8v z?tx0Q*N(1GTtp_QW5-}_6et2pW`hA63=0c0Gw^=^DRtNmpU3(6k8*SF|BX>Bs3lR} zRUtAM_$UUE20o7B`OOM-=n%|;VP-y22b_ULhb0m2T<;UC@HLD+eT{Y|m( z(Otog<9K%F6w&aZ02UN8lRvaC_7AHZ0zvn(5Pcz%6+J0+yP`E3lL2v1t0;8*|_ zLJoi__&qpZlv-sN5V^jXO+bD-HjV&gI~5XAPIH=<(1)`@0-K{V_SSi?eSPL97; z5gTC5@gJO@KYNOp#lvhl=s$QL`=gG(<__lDRR>^=5*CI`4R#g@h34DMUrZ#6&>{J0^qh*Z42? zrN8+j)`(I7!OcH9fjIw|H%y#XqJ}U?7qBoXG6FF%ph8)#{S0`P=|jj2S;pa^rU)4lDr#y)2nzj27bxD}76vRBCxQ|Z2$YG&qkp|M z4*b&)qJpU*UKk4gM@uXpGPqsKhec7s0)f&oc=U3VjK4HwLF`hRgbMUYbpVEf{xr?b zM#lB0Aqw2(5JQOw21?z+?3 zkoe6CwMP<$;NQH+5nj@W@US>6fs&NONueafh^(rDBv5(-fI-bJqo4S7)Bkq{ko2w$ zuoOyK8l3VZ!H|(rT@T#llLOo!$v<3Rc~}7@Cmkq+a0wJb3wthscd4)tWK85Ew8IC{ zE{+^W26+eUu%XC-AnM&3OqWcK&%z0W@7p1aS!m+qK1UrF6LU-)q{sk?#ou*A5$-d9q{dXR_HXpmQ( zD79a|{{8#)?IU+zQ^KF?SD8)F0%FJG-zT7K8B|KtD@4*?9MJ!@KJwG6OZZ$b!_#z> za{rEB$%Q68?d0s_?Cj*!>)$UrBAnEHL9d^wYT<`iE71=aFmOP>SLAN1O8D>k8oO~* zp(c8BH%F*wX1si_bQ3fvZaA|D$ehCfbR~11^tT6n;Glv1UX`CpDiI34m}Yv4o5D0a z<>)+QchT?nN=q+R_<&RW*G1`2DU_D!4nSjySPSMLf`ndK$t31IR#r&>%9HAMl#o1$w?)-G!Ts-zztF(Ve+^ z=k7hwr#NVl=&kbYl@6e6anPW_gUJwnV1KzY<9FsJ;rHvCJBt~4h4&1l!nX>Y*E_P2 zDRbqP!5uP$3>AkB8{A*+1lG5!J8={7+m!S|LMI`Uo`CbWHRI1Rx{=fMV15r02M?xf z{jg!fhYcAZcVzsI+{ASy2_1#3>&0>@vZHJmII^i_#N8Pgz*@_JXAj=+5yOWLlshnH z2W|qG9fa(BFol)&O5b--sp2G*Hju%MhYT4ylo3aa95Jj4^*2gANvXUZRVL^$1Z)C$ zjukv4TZavjpM=eCRzJy&hs`I2vy{l+b&|k)MCCb*rtPEF$Z&218A&|&;e+KT81D&g z9C%Mqo~absV``2qMMlofQzJQz7%_6Bhli)9$A}?vd&XFwA$Zs2roBLE~L8<*pJMtOS;x3p1_yY!-pbo7QorCr2}^CmvJ zQKNmlf-J2SBwuKUFg;+oI4@(sGij2SzAd1RQSm5R$zady6nE}T@1BBSjA8@qgYM5v{u zg5&Q#rnZEeNW7Y8o>ADi2%JcSTAEW}Y$>-|#Wf#CSQLx3G;^IoVDcXhc zMKa2rwG%eSkDm|`31q~=`IaUsaH|HKi9-Tr(|P=a35%9Q02vWJ&*G-yGE|&fh?TYp z3l=X~LL!7EVe>4m3Xm^G0T=p2;#!2M&OzVAIg1u81~y`GSdhhqBI8RrqY7*sLIVQl zCQO{@yKo^{qz7~nfQ?n)4=T_#NW)E<5*8j#q2l6&p@DKEZpwyv+~6&ZRKiu2&}fdT zcG9E;VPPcPZsEd3i^4+!WM}S|4JF)$EzSyozc+wQSR60UWNx5HXa0iFP|DFQTo}F} zKz33YPLz>Q%Dtr$L|?c~CJB@MgUJFhBqTJHgbAVZ{bfg$;HVOgF#_@|O{Pwq2>p|1 z%%2|&jy>gsh0L2HJ21xjEeF+;xZUFR>Ap3dq z0G_8olS;WH6=}bC>a^)|=J@-QxuSyA0~<7VrbVPmfwZVd$B=2hv;F)OtP{o3wgvgm zum~#hx{4I$`OYG+~`rG zq|r}~8567Ar2g~ckGCo*j?ZzUire|^+rQqiwCiVDXR&Yp zfddB*9X`D7i2i75c3#2nDWzOA(~Hg>FqO>IYhfV%PtEb0>FYbq*LOP1&7>-J@3HLN z2Neeo9r@+gUymL;aWXY6jn=NwdZnx^Lw3qpeeQ+4Tg7*wb_Y|7(uNj3)5#3I5;Ee~ zb&j9ktXaxmets(sA2|X=$4{J0ORp$`qqS?7E?<_ekgFt5yoTZqlArLK?q)&p@Ashj zBGZgx!)GT^&k*58wCm>JKXq8N-U`R4Uzx0??wnRL2TiQ5>&6XolfQL~+!hN8?%W}T zd{I$Mu}I6~R^h^p6Jo4eah$zw2+IGIE@TGg5dYR}C?7%12~&OU{6(!A55;8U27mJ= zxh394T?x4(78Vv2kz$nQ{Qf(+%ip{AW+}Hx-2ii25STWjtpg(}!^th+6v|zc>Nutw zA<)whP{+j^H>d&r_H9zYtBzY+SkI~k*`mwt>V#gCtxdR76LTZrdsenuop*^`7Oz~n zYHfrsj}A|p!50>iBEA^yAiwi>?-GQFyP-BiLNn|ghNBviMd=YGO8)*IFbgn&(xM9& zE}}Qf&G6T*k?VR|dPmLF)E06Ni&!Y`2I=*~NUd}n%Z4F3+g-780FB5-^%4q&&YdIY z_0`$os|^~l=@nd?x2c9`Qb2fhign2J@1$jB(&{q%YE1E0Fha$=JlZ5?iiNJ4HW6h2 zpinbIHDyMd#HJp;*0!AIMDIF7t7C({3kIZon z-1sZ%s%o{y=jD-WJe_`g`RFE<#-8r?qSG7usRJU8MsV;{w2EgdpEhmm!aqw_;;2{R zNUXbzwT$Gkp;3Jt^+iQD53X#(7IukCpuv08d%AV-_&J!J4s+)kzTAD9by&F}{``4z zK~x4|t(L^A-v&FW8-^rm;?;>&O}O~A<6P%$`voIh?I)fU?b3lxF7kAwS203v=x^S< zmA!R5ibCmtPX55mIf$N9m8F%;+4IV^D|~>Yxx)~l-_Syl%Vid1B)qRK>Nc5{;x zIeXUy+c0YAgb-;*l3bonz6w?PD_3&ATi9fsqGT;RvU8Zkt|4TGI1~R)#VXFRyZPHx zrG5`fzpAk-<_!o{zuZtY_=mpe4U$jDfKvAEjo-&;wr}^}QI8LK5 zp9@kxcf|_!?sXi89ZEYLb4EHXoI1V@2cr}hamkP`Uhm3PIQBNxH$OEU`cPyIrQ{T! zwjbxA6#nKFIbT?3g{JKmcBP&+oiQkA1Ku&U6(^t+z4fY;uS02e{x{SsHCmhC2!A5g zjB;zH-l(XLp@gsVBwQSY{QSdK1R5IQ{gY^5jKYvl3F*f^!Wkz7{Lj}U)Nq4x+KRG{ zQud#OS8-Y!jOnyCnv*E!(6!inJeyMC(`t&Jelp#BCLsgmy=bzWE~Fi$sXB^3dOa?m zyKIF|q4;m9OUdPUF)i(+1sj^Q>k0Y75UxUbB5m+7G&mWB;h6}ibjp}6rRh_DeTU;t zC*=$8S%KrJ=C#z5WV#p2VDXm$*QKVO*m=s3Z~hJa{{s%Uw0Oo+#(@)PYclHBRfd#q z#6RQ6T{Yy#(%AfBg*Q?B;1g-of+@X9Ys46%fo1x3hJbm&oJ8rV!oHDcL8IJF( zB*J8B$sTABP93$d1EvZZ;<&_+Va|kTcU945k`b$j`fzXJ%t_bCy} z2L`rcZf63O?y2^GY5T6-C?$!t(Z}ru;q);ODjzH9w(r_^;J-LlD#v4U#&HMZGId#5 zlu`9K35-Jrzr%6THFc?>`w)&h7L$o*4=AP5DUtvJIVAqn7N8@SlI8P}vRw31XS|m~x258uc z!y-+C9o3MKnHgW9p}IpN@xS0o2gw2MM|9vdjm^>6e4MECR}CjaDpfk5+ckybY?xnz zNn=|5iI4!B(n0BfxPSkif3gG@4uz<}pW?OttNtiRBa;36-XFC@7A5YF)p}7Q+MWPu zLj*zGf|hy}f2U zLBd#7j%dXH9J*SJhh^><6(5&roWrIplftR#R7N;+^){062h`Sm!TJH#jvKRL6lSG! z7$M^-J*rDr2z&fALb{X{M+ti?AH1l9JhInd;rDE1w?Hx{WMpL}WD6N5_EvM$l95ME z6p_7>McDK6I7WdTudGDu+9}2MbR{#dKrZ1AGyVTyW7vr2DiZK$64P&cprU}Ynd)8r zH1xJOJe*S_`Xv*FQb2p)ICtvx2rgEdd%wmB$D) zzriLhG#@f%$0}Ic6B35iU$j{EeBWBb9yMggQS3gPiZHqE4&~vA3dW?taHgHeTRJM^lITNY0rNy%%##UYj|6jHOZTfBdesr;M_dHO*dF~EF$3HL8eyw7mf zm}63eja6Z~Cj6D41Gw{w*y=Dr(V=ZAgp+4!KOwiJ7_mA;U_icj8XLS=%}<%&is8J0 z*|R!204@O!&1tYKSj{ydO+kIOIxtXR=NJqZvsR{@*z@8Aim5mvP%zpN0k>Svi9gTO zRGbL_l8A>3*<^*9Ek-y6&{@RCj)nljW18?A16(2JVyXB5a{r3>iYB%owz<;5M#&0)%r~h&9@!acol1uo)=InX^n*T3yuKAq) z?3v^He*D(7LqJO1U@`7B?lbIv=Yan3@r+A13R6nBPZ=H|+YIZbb9On|r;Z;vxL-cN zr==Ovjo9`Z&X_YcWa_hXFXa~$fsxJ_NHO%>iQ#F?)#YSooyM)0l*XUFXt-p&9Csz* z>Y6;=^&16+#lT-@cua|~V{(omSI9Y=E#pDi?90aA3^$B7&9{{SPFbOI)m2kIIhy)da>n9k`=3Fk16vW&~0wlS3T?zLFc9ATb zORaeAGv&y+xJN2TV2BjjsG}-Ere+e-WW<5byKQ8UWGKOm!A&4jVy1Q;|1w*K7UANJ z+lGQf=t(Y0DaQL3G*B$HnUrE(NzvK=PEtLNqsBI1p2p+~=dZ&W zMI{%-7K^u2-|ox?9}Z z{nJ?!`k2pI7mFuCw`ah35*jPsO8>BzmaL zRgY-tII6DEConAJ?$@t^-7Uwi848l`=nD(4>|U-&x)~Y_Bz|jV%B5U>QH*9?4&17VR zD70gc6wJ-Dvifcq7NvlcHRiSU>o#n9WAj^YLQyh>z8pk?^*Cj1iWHjW}kc1rw$C2nE%PETd;0=i^d#{r%(6zBsAI2v9I_veuyDNs*O&gajv(qN(* z9*CDrud0jA@NP(_77Re>%ncY^k>Fp)-)sxYlGq%^bY2&h0L z{`L9iA&LeP=)jKf;RgnLxf0sVLP!d0Neq<8DNR)+v@;M68qUuaXgUZx+J_EwrBoaU<Qp|eB56*>$oyP$h)De;D6bCM7zgHkCcxrb3M;OG()DXVf;(s9p;4Eh$L zOXsngN*d2DG?e4IC4(jn|sn5`|df@|x<_-9V=exO@c%_vgBCT!=cl89m$px-KDs zDyTk5>0&vN#VShJ+m)_PX1Be#*Q3Ux2-s2rGp{8aZHv}j_nyo`eG6XUgqn`uZsZf~ zz7}+TWnu#5E~}wj-ED7bHVxWUlpNsgPq%J;YVElpF+qqiEUT?b-F;tbwh}kI=!w2P z>Q1T)yR%c>k1=3X(8b47H8rFyo9;_JtHzGLfa*5h6m@-|x=m&wh$9JRycI$)OG|4m zPj9v_?JR8wd*KxI19vI~Q`H+YeF*kZ@z7#WwA7fzY`!lohei@F!%|%-E-ooq&hCvQ zPK25P=6G3AQmHPz#s2ghYM;Kt3ibav?H4y5P8@1y49=*4p5rE{5e@WToC2Fj1BQjy;L z0B)1tn?A~Cy|w8JtkLL)C@|$%K_*dEOVM=)w}*@wMZ6o&U>&D4xzt0Yaw}vobulrN zTT{MM^v3(x3_i|ztk38h#Y(eSx4~=45ND!q_n`brSx<4eC!>9j@q!nNmE65|udhav zNvtWxU>1zg5mj=ZLp{8V-cHeMd{A4dY^33TG2qB%!LTx-n*8Tb4^OZr(085{!_-|R zJ7L5lRHhh{Su|0WZ3=YgNKe_@AqNFp)XGsdCx9Pm1fH0f8QV0dLio541Mcprk)@Bu9nFhCCMhd&_#$|9Dw8~q%q#y097bVmm!o5qO>9; z0Qpfx>ZwZk0O*w^LWG5owh{)9@QCr^G%2^h2&N>75sM&gsYrRxW?C+Dk-;EK646C2 zSri(GG%47zU~A%~1Y!fxFI~dq%~ZLM*60-w8;RZP5sJJimB)E$>}V?FqNOFwHFrhG zy`)_cIv6DxV#5+)QD^|_v>BK4(ZoX}h{fpW$OtH)-npp=ZxtbolOz)nqNAgv2%X}9 zD}}^+aeCJ4SZ<~hIhw5GmdO!Jg^Ma5p~^XbW3;qVcs(-G7$GbU3q&QhqF|H;2sT6; zRvIEDDh{$rnF5yJrGdgpv~eXDB}eKaXyLb2!gSDZj|5MyD;wW%Cn8#2$uEsEMT!hp zQERQ>d{i8_RDK;VmWqVei&6DmQDJQj!}Zj8h2eF6#d0~)ptx6&HC2EfOdo(RtswM` zJyEcXDt78(MfMcXM7-38O>tb}Jt)$kxrhX+A|I{F`H8PfE8rg*i)#2FWKb2km&Tti ztq_(i1;D5PbP9m?XvNkxSeQdraLc8orYOk@k?g67gUAXQLS1Ae)h|+dk|#Gx73;!Q z;LS!R0GN3}6?>^-e#vqJq{b*AB0LCrRFIQBIh0CaJwhBJm&=e!R5}j{Q$>o(C?*vq zM?fe?5$YBb4;z{6!TB&TuD8wSEL}!DvyWU79_&A3>J)i0oW^d+wv zUm<-+?+q{O`@GtJ@UW379-Je){2&STQrI%kr)Z zk%0t?WGLFuSN~f7fkTH=`Uplhal$z2oB`~JMWMm-OhLRidmEBrBpEJ234spNpfv;a zg9d|0nWGsKC3CIk(tt@(Vr0bPg{Ck*Xf(k~l8E{`B{I@9!aO`>m;lx)56+9RkcsQN zkh)7*cmtEXgqx|o7l~3OFWEE2BXQ&!5AG>;QIA75YjPB2n4%1k!sPMeiTaWxX_U#w zyLGY`6kkXMPlAoZ$rO_q^Hv_(@0?r2pqFQgz!llq|iqwUVA5UMw zB#kjKxY?V+*Wu+%Y;Pk4nmL`rv?w|T^loJ@Al^qS#E`aGeD=*gy}RHeQ39(Zm?| z9OEffz+?O-dJG@jNo`~tT;Y9|P`D{lSTvjYVn!ns zxXDZO81`BdHYt$arMjE?5f(jtL`29qkFf@**YGjkqQ}tQ$}?HW@=|oKFa>QF-kfuM zaflD~U4h5=;I&vIhxE{ry#YvR3S%O$C&C)aFYbYn-n#GbQAUK(jP8lS+qi@g1E16~ zzJT+O&L!|#ir|K0oOK)MF~$Jh6m0Yny@&T}sbzfw(8k{36w60UP2@z!mxg#7nH#22 zqSvtA&RX7=`k)^VAB>TFpn&wN;sJG7H_B^BPeIH4QtRylB-(wU?#TUihjHpD87+7Y z>Wt(sHOZ2{^g}<`79tmSM)o%VN*gir(im~HNB`Ey{%Y7w(5iQu7#S7W57}ReY}o7BxNLF1AA4M6r+=suvA9@$?_ycuu6P7Xl!SNXy=`y2f7g83YV zHTSoF%4+$c%4-pq{ZIbC`225t)Et2anI9DM*MAnVb%3wB4%j+Xd6@qH|GQGi7PC0? zuNsF+xc~k6|1|wfTSR17EtA)33IVTcw3Xs=n>mRO$vTe?ees<_E9>-Q^&#MO?mHN;w5>CafgZvS z0`EM1ZzbdO&+0-T=vrD-=xdE1hJ6ISeaw|=tkbWmgh0?geoVv8a{b!_5KY$)`~04! zvFh(iArSOkGRr}76T81R0nqfOVd>@is{ddW0$$KRf2jiXkERZPX97Umb8pBZ z@(_T~?>8&dzUGd9***gAH0h^5t+dthQ3(Mr*m>TuMqO^{{1+!60^e4;XsxUE&ol&B zou>V61N-xdMt@}j(8=Ea6I)d_daL{6^LF+Q3$(RS0}OUS9ZDU4&~&$X$2AQP{`=a@ z=qkPCU*`#kA=GWn%?GzyJ2JM3eO)FX#+?1woqyD>vo6w4>M{Wl_(zxL)J6S$v4b($TT1S$v2K8C4?Y2TUGuu>ejs$G2cCd}Jzkvr(0@ie=mg|-&f^}s^|G=BZVz|` z;_Y0+>cM`p`vXou-rhZ~9_)Y7sxcPk2Ur6Hhh`ttgMFq_U&~HeTbu>Q=HJwpeP{js zufn2J%fGPZKbXhvj`zO`i_WcT+TuN!ky=oXJisELYt**##j_TTbrZF7z5i8M@6xkw zO6!2`(8Nv~W;OoSyL#3^W8I+ZTR7Zr2J&`pbL*zGF6b@py8AeQ39^;s*t7;v_Ony@rl@{*U)4MC zr>9H#t!X{)zN&TLhjwn|rvvr9`>Mu)KgP6mEpLCl@4l)!@Ksmb6=|Dd?7phY?pI|! zv~TWuws)_{O*h2u%hvTz(fo?Dfd<)qSvycX_;IV|a}BfmvU1@4F0CqhpX2l{{jG%c z|M7O;$C{K+K8|a+-Iv<5^_^Qemk)l}Z@AqTb0GiacGk`38glnV9Z2ZZ(z^M0?7jYS zUuwjye_eXsYU!m3iH6;Ml|^@KVbgrBVRv6=dtl|a$p$p+?rU+!=1#WvAlQ99#4``; zuCC^DYWFsknvdnD{&HVcJP7L0+|joAc)w-+<-V%eA8B>nSF&*pyZe$_Iag{vmY?V< zZr0lu-?wnG8T^?3^_=^%ZAxM5%0(Fsy!#qkIUC);yRY??&tw~T_jS^G=R;>e1Mj~6 ze5%p_Xz1P7g2oj)Pul*5-hF*;dnVZ6yRYlEhtdtb`zk9NVpA2;(7Ug)vKSZZ0nos^ zFRX_9-K{p?boceG?Gjnvf8A?ueFcVDUl z6`P<2-hHX|Q_D9&4ZQnO?f=n+q7DA>EU?()L4Umk+aI;qe$LA=h+K&d&~KCqW^7hthxlF z;M38qRr{x&ANExjkZ#7?@4V2atMKgON(}0 zo_i&!{)+(0U6@tA1S10~+Br3Ox$RBJrK}sjI>Dc3?;OvKNrzUmh ztT#aj0mh+gi^sb3?7Ok3Cd$M8zPHsTh~5XH6P(crPxl(L>){%zLEDOoO%OFtL!fhL z+^kKf9xpGcL+N`B+VB7M_Z6EU#lG4JEg$dNbKrY*EPubhxypz?Ealf=%{+|(I>G(X zC%gBWbg(kvVgCL5{lz-9!c1^t zEArq^sxOI5JMcGV$kopl_3z!Q$5T(XcCR>qE^oc^0cH4&+*^0({^HCNR&Hw_FL?DE z9RAPKe`TS{cz@2TFF*fG*ADF-Y3AZ&bpT(<0k$GHZ`b*`KCxAvMYuEd#hyK1c=;6{ z!;U(2(7hvTCcN@e&+c8GXxplpTO&ui8XsSy&d?PZozU%tkzd+2^pC~Qc5eUp6P=%a zwpZ_0XKXm|U?uxSyG$N^UVQH9PVL*YZ0hRlK#gmszm?jq{;6ITJ3jMLz!@#_^!J7y zPqu2>q-l%Rk9FwMz2}R41}*$3!`4Gc9IDb4f1KDf z`IVQRf2PZm?O2!B$vAaEU6FBF3_nLbxZ&BA&RW`YcnVe2+dDRLb*Ej?^%-=<;Kf@r zE4re@lHl{oi#?z2{6w2pO&F$82fQ>+DD}m+IH;Lz3XGmovl-MDx$nAnzp1}(f!$;&vr+b zKhoT-j^j#TB}`NhrwRisLkJapx4>OwYDV_ ma5^ICtZ;L4!z}+BU2bDq`Gbx$yZbL3tSjvBuXjIa!~YLq{ZZxs literal 423650 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⪼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 z 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%0D!h_xPC!KX49E2TGGGs*XO{wWh#xca)%*-xiD?k@ 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%0A}y?J9L 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


    JX_!cM~k8*Dei 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 diff --git a/python/resources/pycharm_core_about.png b/python/resources/pycharm_core_about.png index 1bd18ae109b7466df30accf9f3d90caf71827c0d..6f081ca210d676b35766e44a35b3799ff2f77ad1 100644 GIT binary patch literal 22873 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 UkzW%4c=2DH>|AZ@Y<%PY2OLIoWB>pF literal 43746 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 HNbvsvN4X!L diff --git a/python/resources/pycharm_core_about@2x.png b/python/resources/pycharm_core_about@2x.png index 31aa960cd133a51645a3e90e7049a95837bc7701..398b766df1c239fe1f5900e66ae3e7a94da58f9d 100644 GIT binary patch literal 49395 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

    gOL@OC+l3LX4QW-@X|(vR^(C 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 diff --git a/python/resources/pycharm_core_logo@2x.png b/python/resources/pycharm_core_logo@2x.png index 06fc318351f38dc1b54ecc55b61abfcfae363003..151e752c24d4638e980810ec96cb238ad746c86d 100644 GIT binary patch literal 69866 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

    C?b1OJrG^)oCGMy(}|7zo>EZ&>4XtP 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
    ocxxUbzIcxo@E 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 literal 113826 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 z zAPFdH{5G;lr>+glvveqkk65U)RQbKD{g{#YlCfVPb4y zaGnhcZyii|Ac%dBqqUaEQZ3t?)(X>R)N_{QIG-c%yfyS8({dY!fDn+Bkq}kiPufEM zot*vgFqvR*wfW-Ze0u|Cs&OoL3*H^GsBuht$XP^~tYwkcU@cZZCJgCet_3*H8S0XFn}Kdllj)mWIp+k(lA&-crVPaiC|+qbhY3yZs>@)-0&mO%WwqF05lUjD=wI3qBDowN{wyCoz!pdrH#3~|GlVJ(0rD@u=H9b9! z4x%@AzdR)MRFTVVYZNUoPm1O$ZomyA z3a*RJE9k5>FIMx~R2|wPJaZ~FkzNdmgQL6-%^+sdI!zIZo)$P$JRMgpGbuB#|C?S^ zU!26I!S`~$vESW=Vwv1i;p@}!@xIy9651;@FDrQ3DSWfrEzG%noTAZzKrv|ZqEZyT z@PT|#(I#^zR-|1)nMKP^JN5<7bGoDD-*ZaJ^vCPriNW^9^T%#q#?J_{L)fymr~UfT zVe!Qy#tU!4ytvxE5W|9nYIP-KhLQ%xr5#f=b@|P1Rv!!I#u8w@W>VrUuB)yxxMyLq zE>bEtts%mLT~8u^VnxKOW&;;hO@9n8Dx|A3PNK_%M6m&oPeAcUKPhG)t_O@@xD=iXTt;}zW4RH7V(_F3Ja?&N7~W@LoQ+@OGSX%Bb&ytnJWp`%ci z&lfg2UB*v0-;4Rpt~c6oW=^W8L%2jbdtP0)}uJ?0t3xzpAOH9eSOh-($BhvYxCl_A-AnW{$fEc zOLg{ABbQ=B8H$T=E?z03xpn543E@sn{&nZvq214ud}KWPt)$lxMzDI4#TN_!xcKOS z>8`BxF~%pZAkDA5PY4F`MTFEQV;&>QN_}$(3UC zjJss1oSFMVx?nX);rH{t+Y|M-P z&F}brT`X=6HobyLGjh=pXYJ`qH+?egpD2(kXf{vazg_M-Cq0?Y(76b=)Y`-Q_KOZ$ zqc*XT(Y$c;kD-+6>Gu(dE-HqLGI{Lfj>f`zTLuopQ z=buJJcjZJCz-5boDZMQ6Oa^}$O59)(?9~H1g}C(d7-bGiYbtwhcD=rSTaP}=X3Zdh zSlOl3P=f#q;BsNDQ0o?O@xSYV)w`$3m~3OONXAvH{dW|Yug^C~*|qS9Wxu0etWAF* zsZp|q5Y>kiW)jRfjy=|aEg!))AeuI29UD87#_dt#d9r^z5XkKrBbTpzyF|{IT|^pc zQQVm5K>4rH%t{2KGUR8cF=`#E1%6Hy|I=Z*p^nn$qfSepLF-b5o_{lJ&^p3C3?2k9<&zO+KrOxI91bYQZ zZ+YSN(nKF5r{rslOKLuB!VQD%vm9aI!i{I>ApB^64QkvOqP54+(oc!&6~*f@i)KO9 z-^2MdZ%SDRhS(W^*5i5N0Yxa?HA!_FDcfj2JcTuVL9ccd2?Que4QK}eg9X~*OS?wd zW13plV%=x6HH_eQMDx3tL0#!oagtx3x^!`W`v(o0Ir7*6!6-}Goy#^UxG;EljEM<$ zt@`&K_!S8G<9)wC`y)AzG>@2In*9?*C>1bTTk!22_TvHHb81<$soCi|BP0SvKj^W`e(lEHAzvj-y(RWjB8l2*J)d z)E3@BE?ckbH}BO8p!`fV(kHLZ-=OxRse$YM`I2mwOz%dwm;T8ju%?^0PsiAWZcfeS zYlq$2@HkJGuie9bR>T!E($ly1e|swhtJ&+=Ov~`rEH24ezb3NF<-bhu&)EmGWN7Qv z#LH@gTQ7yP{qdhcEnH8!HmR+lX?-rdTIfffN5?}NI)mC5M>KLF`6bHaGRW~THp6Fe zSu~}>1Z<%B>VyPQn*CIm?IUU}J_N=CQN@|%%0h7!uD8l<_H95_JpC+UFh`;Vc!?QPgKu#>1#K zYCX7#M}?5wK>Li_U)=z|UiF2#{3oY)(0V{D6GYD;24HFwSdN?rj`Os98?wDf;AT{@ z*`hoO01Q`MBK=U;%xw}SdQ;3uYWy+Jx8#z4AbZjHv=9Df-C5L0tQ4quP;sloKgN<} z^W^jn@+1AfinJ@i2fN_GWLYOjEK|Est4;4nFfs*53QX|F5#|j%u>& z_Cy4v2+{&lUwTUbsY>tCTOgFsqV&*2x}snNX@VdS1f&Rr76PG*G((Xl2uQDjqDYaV zQj{`J;Qj8JduP^~HTfqbIc1-{_u1#S%XzRIwC42nH+cFg?wX1r=27n}`=|F9!*cX&|%FwS^j&xI>XX15|$R)V)Oe;ho4SaBK7$foU4 zV+a*u-T4q#Im3poWUC&yaL_e(SZ%RnJ6nZ{byKlzBAwNGvisz#EN4$ml^YnAQbsk? z!&~a3WWiPw28wr$GHaegyo+&2$0~TYy!%AXX4d_h8-EAWv!;i}N32G-Zdl+bA78EW z?ii85I#eO5PiGm)4G#@7KuFLdAs$&861*olz?o9^ckuCwt5pLs;|+~-Chwi8I4exb z^43+L8E$9<1JsstDWu#D2S?Saxo-!59_`ub4teZj{h;rGM749ZtfBcLRGc-1)+jG^ zC%ss2vpsECCgTlr&<5(YWB1c)rdd?{migUx>bCpiJ2aAL6BT=r9HjDUQ2ZK7z zD#keW@R{6uPQ0(jNR* zEW5BUj(%OM%|GTPHYq~zO=07@=aX2M$6ETd1pY)%*OIJa?w3wBwm(``zq40NS*LoJ z@|OBpDM^K3>~N@H!IKF0Q8Nm#<_`wCS}i;Y2|c8*NfT~@5g;rqNpS8lUfjB{%uy3w ztMXSY)iw+Q`4kZcn|K^Z9Ghd~13Siv6UszX7{`@{laTH4i*WwvQd(e~T2)am`0I`BNH9BDtzaO#2q^H3Cm?K6WLs2CSD8|9 zlHG>g`jeq*Vx+nzqGS*JoQw)dQ}$e zs6Geswt#s6?%4t?b;|1Jz^Q%;BD-0adJpA=tk1T<^^dg}7}^a-*=`;oy8-8y%iFpw zIJ3ey7J$JGbqG)PIWxT~=k$ufun$*D`!*!p$Eu+-31A_+kc?SPR-KyySWRR6RW7Y% z^-GeXq+7-XLxb=Y8!zOc(cxI(1m@YX^wVI0c@bZx@u5ghGCSccw8uIQ1{usq(TU;5k&h=H8NMqP8Pj-L}aG-WO(vi#Y zc6b3F4QIfWQ6)gHIA{Pmpbo?Hv4mb%jkGLud!WOy_$j2KYlF9{5clF*xBoFRV*&CLd|xt`m{DrTPom{4Hh({V2cCSSoe(?v?NA0bWFd7<7m)H{+E|H zMc6Ntq1=epYi+ZG@3|Y!@l9}(Pc;AUJv8Y}E^uv0fk#&f3@K`me`8Uns(ouRJ-i(KusaI9kcgR7^9Y8_Ho%v0!1O0l5(lU;~Cq= zFHw_I{~WTky$dTBf=6ZdI%$VqraYe*cpPBLD%sX@XKf^GD?H>aHf`C^m*$>8r(4`W z_8=oyJMXhswQ;nZyoy*F_t>xb@L)!K z&cuw9duMq>db~L<9=e;a7-PvGgijbp9@7Nj7nU{#f4{e+o!@B1*R+v1HrIGfKz zJ7r86+~i=&q9FzN=}ZOW*=;&mARQMv4Z1}x0gl~5qlNAZ3xli0f^xVQZtg=i57*O+ z)ol%vafVerx<6#cbM{@5zE+VpXm`?C{xY;j@+}CLnmrAFgEjz#3Dy>XLh-!a({`T} zEXLdC?%i_T-No9;EZX}v&*fdW;`(@pPgeA?hz%?p1tZwiFDrSYzU5rAIIhNU0E*JpmlQ4+MV0pgx zwY1GC^TBqD@C4x^!GCsm;`@3UO1>F?x$cO35jtFVQ0e!*bGv^3aS8W+i2ZN$OR?%8 z_xQ=*A`kSe0vH$hnmX6M2~L(4$yj=d2Bq6tt)DJL1zVql27Qh$u2!07bxLx)C#SL> zSRLSBaZn`uO59KgW?BDSKV4TfP7A|fQ*2!xinKl|A)g-9=tP1j2pwh=ByZobKxnf- zjs&QwYo@Txg`R#^PHYoTXj!2GdK%@LN>*#hzfJuS+Sf5)U@NUHAAlz;ZF~^T6Ww$~ z=G|Wi+SFS7eMO6=>dzD3>#~s0`I3HV-Cb`7wip*@uNoW&bVmpXlj2?PR`#C?|F+SqDB7IAjW>Q!Wf?>wMPvmPmpdg4!V%k zFbq0pxa=41+_y@TtL7(3yb-$&*4*IxMGFh?x(P)AObrbj=Z9q8ql(wR3UHDbOcHLtUl>u$;C-Iuz%d0ghTb*ZX#t9h?2;zVcv;CP~PU3Ke_ zdcTZuQtwgW^}nHZGlazC9UkA6<93uyMbK0hb-6h*| z+jqb2rB8Oc=OtdA_x5`|{3*B6coVF!8o;O%F9;hC?rual;KZl|!MSWeYVEG@su@vf`pR3Q1lR%g__~`l6+k|z%-}uyZgE3%H&d-kPz6&C zM$nlSC?xqxi4HAb)HP1PI+t>qnLO(RvQSn#ieoQsZ}s=Hi%Vpe?Kya?IwBPg^N%|W zCV%fgo?J9_xUUwldCc~RMpD=<_m_$CDrf8LLPRa*=RN12u71awxc%^){g$d9FB|VR zytzAJ5msEc{IofE;j@ahUC7WRet0artokS1Yw_;v_U1&~U!RhH8uRXtv>pU6_s@O@ z`?;|$I<_AD*~k>mi1GbhZ@+6bXtnYz!<1eRTNkF{>l>FQ?GykXx9LAGY5%Qj?~I zb1bej3;px!*~0ftyB}*d8@_L*Y_BhxNqtOHGf!20;lBR<#>7i84qAgqU7U+k-&-fw z8V+xoas!Yj*+oA){EIj!&LvAn`I?7IzDLyFWgu34#2aESPQ*d9sBU{(JuWTy%TF7X zM(aDt>o(Y_te;{+cKcQWedG!4SvpFd9%gt{y7&xZu41=QfFu*fQ`B$2zvO*_A8$lj z#xuoTcDEWtSvg3wQ^Fc+fb5Ic#sA7<`oda4x`|3>-9+hN%ZQ+hBWSqv)yL?O2@%U& z^KW$RV7Y-2t7Z0IKg6n|-GCT4c<9@%Q3F@0fw`kqeIGjBZ925ZR+%HzrRiYUsda3y zXYG#;_R)y%s|OPOj2tVq7=2LFu{Dkl)|{D5rjW7FyV;-fHc}iWw8i%R8%IyRPPwcH zdddItE#v0T$O|Nqh@Hvmr_1gd$}!#<#(vi$lM(JX2#R8zOiz%l`o(26f%}x_#@~6z(%5| z^+QN|-q?>7>XI-}E$hi5b<_rwS;Dh3l_u({IyAgke^dpA3e7IB)mpCEDAx#buc{|@ z&h~BFvYHy@mfDZ)*Laz)(;$BhFjC{WW z@98^t8)DJ=s-iL)7>HTfIF=a-`i<&FQnCy)S%(t~IspGs{R_F57G!j!+C+C9nj;C? z>}YlEs~mYZ^~4^|?PcwG+czR8I4>r6WFqK)f&m{xhH=*9VQig-KZD8IE-*2_NM z65UT3PL@Yr09Y4^$ZRs~ zu_XL?F8f5bvFhE3xmYk{T22mwD|M-RXquU5SPPUcG}mC1AKDC#LTubxKhzW?1f24tgf)jX*AUQM!4i8wSA1vnvGt+VVCgn67pD= zMznh0CJ(#pGN54^A8IX&O~cfC_Bys}p~bU{-?J1}_o{aGwmE#gqkKgoqM>VZ09N$w zpW5RdnL8SJaDRhw>+&WnY3rcI&v#N}Ee1Mx4_hPbc>mn^5D5w1mOP={){P2XELBto zolx9q^WOLP+-7hImn1j^JJb#ce}E1>QNmi6>en8S8}3>cBX&fs4|s|Wx=*Q_5Sx2u z*YxqFNYF#V@{mKO+!hcqAt5QQrwmH+zNXdiO9_3j_Polq(B#5{W4-O=k{gIn{HU$s zOkmMaeQ=-Ui-{jlI|9Pzrgf(GVA5!HXz^R7E<@WvXdT`6i_4-l9afyF(Q&j*H+3H8 zR7g9O-_X5=?}@pKO`ni?{AUJLbNb{D2Z}Sx6^KsOkrT_XfDDIj^R{7@+lX-cz?x0- zd_&6#ySttK>TX%78>S8fdUmjfo@LwA%wY)4LZpnscZVCHwxz#$!DI>2>gliPlcoG} z`0ISz5K`}A;NmvnCFI5o5Un_%XoG|VYEcCPOJ9dO^kH4nW&fl<;eW#p8Y%O&1y?5@p}w`2Eb-F@yKzXr;UM^ zU11PRL=0aukTpH|$bF1*%`$lY?3tvJ(!{O9S*9f)jp=G`f3g+-id|%>< z*Tx`n$I=mFN)d(0y0vMC`^!-mVV*jjzpDu!qp3gsc_ScIi{&e+x|cCq4DTAvx6d-+ z*)^KF9e5QCV{{PP|HdNpI8!WVUVR>lF~t44%#a>TQHB&eQM+AW?YcfzR%-L~@%jZo z2KBt;Ug-{k^7q}Fu+5`tPc3cx;dVSZOWZ!nRvEmkkYaCJ5u2ky?ckNTQ&k2=h;cMn zbI!mR-}a>rJf9MLmTn{=NUOdk=p~rBe;nRs>m<=d%6z=kDwWGr2d>U{vQ^=3kLfe8 z4W|;X^iU3nDjPaNyKYk!c-BrPUa4oSGH2|WqEWbZ2cGN|>yajY*R7>I%C3mV4v06i zWFS0cad)WEcX0Ec8x-y<>vLh8G6Y5|Kk6c-<8{}b-FN7U+g2nql&(!{uIXlhJX|TD z;`~tPNiX`@%jZ2Kh!5?c?+S$>=kV)KWuV99~fM@J(eM4-%Suwb9od0qM=#Tp$f zCmEMS$G2*I&pj;IZ#);;Y``#3QO9Cz@p?94D^l zp`4IezUh)z@Em#LzAog={`EE2rcAs}iGYe8f-QFO&y}jP#51QZwo91kd5ZRb$IaL+ zCawnjexs*m|Mt7ZjDQpo2Vdv4GN=?9T;aBNX-KBtw)_P&<>8joX87n3wO_s z6m?#_I4QrNGg6N0)O6fK3zr1LiW<^4B=pm&QXD5MT33?Be)Nwejn4aWG-tV%w&^f& zaZBAce7;bS_B~Op++?TXwbTOr`@;9mwdy$e_q%QZv(cgRmw=RbfiYh8eYiC>3(m9G zVNh{Ze{iERP?q(f!^=|U3X)4=Ib|xjU*z{Cp15U>tIJvguGP_MqVwvY;#4Zo=!Utqivf}|UI9y*a4Gs7>YW(o#DtZ^HUd%ZH*dh3K0j1k^*MC#p{g|X^JS*^sWbVn zGM|wciLgzYNO?RVJ}w158VVXUbCOH2Yr0)7GujMhv^KZa`*BceYawVKboT@=+WLr9BD>}SraW0nIT|{-g}Zujw;Ho ztB=Rk4eb`83mkkocuCv)bD{SQy!>yvhk5u~9gt&R*k!+mf^}dYc30mlFNgSXc*zVgz|)nIBpMVhbHHvSk+_wvi+uO5F;FxXo4Uc5GE-yn0oO`~PsM)9^Xp6Yq7&x5x; z;;C<@>3u#_g%3Q-DjqGdfODYUK&`$ukQTbrCQX3slEna`Xi%;X4(0_2)OYb6-@V24 zJ;kT(ayzCTUbV>i>J8TS6`k4A$6#K|(xBV+0bp_@Qgoi2BKZlAx}78a`$b*fdSGBZ z4J{SA%^N*IsVqwQ0c*eRwd|DaR^!ot69fL|p|vBwa*N2Tz%(woW#n-jDR6W?=->V_VI> zL*V4@=zhSh+ZIc3 zl2Dg4?xL7QL%zILa}==jy*LOjrcznWQ(euo zkloso;}S=~HX?+LK>@(jn6vco>vg|QAJV+p&&$wq0B&J&Ys8|-8gbj zEAY7Uc!^LXrV;wM(@=jM16#LqVin@X_3I%;^pKEPT#!^h{N!=GPFzp93{#5&>CVE& z1J^!9LH(__rdE*o(7%$VToOK`<7Be3H^!D3Eg>5TM{)} z0ZMyl0UAHbi1ULl(iCq*Tbn&Ad%4|BN1pUU(4N_1QRst1Tt`%AZXKDEZ_9Pzkqi#& z?E3bx9YLAf?L9exE%Gu8+2V7ypF)j`w|SjFLgBXg8ZSa;!i9_~`Kqx~4M@wrzw=4Q z7|{+6VC6^;aoS&6bRo8AVZ;}821BK9uM(pI>6c}#}1_{0k9bG>5(NL>K z`K4p<-|kW&gYa{r9#-Coh6gfltJmINbQSF=91$v6XNHJ7y{w{U+)EQ6SFp@oD}e-= z`akEfaas{xec4HOhL3n`$O?>V0}WuZy(~C=m+&X(lnGv+sABY|@a@iaF(YM5f4)iy zyJYbtQ$i!1RnbH7aiQJE%t9OD#;P0oO3?JBp41=izc*i$2VPimxYVE1@gNv98>N)G z5?5(;ft9(=Gonlj;pDmN7;^X12a*^tlpLsZ35IP5PyLl)hhML-O&Jw!(9;Rc7jbMR zIy|MNa1DGNHA{%0Ipck($Hz8k43B>G$xy!GCmZA9NQB}2xjwJlE{`>RKjtxmgVJMH zQIsduvpc2Azw@_muEY^nKYPi_?+TAi&S@2vQc>`T?OI6{4O7%5h86=rxF7+%dzGD- zO`F1vtn*s_2s`Snqm6~Bj&DcUPzOQP(WRzS`G@V zw*ehk*jL5d{uU-AlHRVvikPbp7pn71ZcoaQt;080srH$*4a_7S3tN+)~~9O36Pyk=%aDFC{wa8)w267ESQFPV|S&@HgBy)$x2nHaAIs{}Ri}w`fk- z)Chp`O+l|o3VNjS*eUi%XlEikE6s@j3~`ahYDzA_ee+3QRJ(%*blt4vu8u*=`)GGO zdBENDzWKMbR}tU52XzN_-Oex-DCp5Xo)XRb5rtqY)BMf|VUqsW{(GAdYLL8j>HXck z6H&SifomDX4RF;(ad^h*b~t2{1svEv_J~G^61}8zUHR4?zOrqJZ4S^#;PkKpAWeq% zPUFH;8kPw0#J%wMa91W?g0y87bpk>sUy)d5;H^Mdo~$Tk`$a!peCvg@9m{0h<$9iJ zP>u3WscCKFbTKVHS4XX6^Q`!(4!5pZK>9#&8yUC;)twu1rkn}RIZAbtdBGWx|Y_5a-BBy zOKUhCrX~YW6psxMNkF;+$-r}ZSSXvoL1O*yl6U<+#Wk2?igiBW=muiUXN*FHisRE( zXf>8Uq^FBwOJ4+%myw~K%E`z#Cc~(P&zGFfa4U1LvYyPf7M^?7>)d7TkEXPw}7Hl zRx;ueqNbL0OU1@H*3@sMu9+0AiN6-8Jgz=U4HB=R@rLDkt6L!SfZIiREm5V0*Ibmz&l? zyhM>cFEhc{mnKCAKCiJ#3 z4gMMbAOn6g42Q{u^^zLLJ@o=S6{0AQQ1uFK1g$etNr(Y~7cbGCFbSNPI*rrgQsy#R zCWoF+X2f6qvm6orr9{r7RQ9=9BYI`9DnD;$n6W;Sm(_FHA&FW0pa{ z3;^L8cq1kV80kh_3vtQ@_{U^5=JpF@1Fw@u7O?dXJSX%LMCi)>NOG1B+vBXE|HoX? z)=dTKGY68D<^o3Vdh&KXCW_zo_HWa&ImEz$KmZw-9q9~=j^53t0VD+=UNIXMdFt!x z9R8{CDJl7ir|}#siRR3jJ==ix{qO5g#{>83z)_-48Q(3^kCnUfK(#dFs3vZbR{@^V znd=Q~Wg5UAvzcgQNNm*WsI))Yf40^e&V2pgAiGu>o6Pq~@z29(#Ay}5i;uWC`545` zx4Lr)5!nXJ?)RL47Ryt`|D#-9OI+be#WwsBi-PI*te0 zk(}w;e{IFyR|m!;j$>~=bwfs$Jh#7ld1Q@Wo{##JPDkV*eT5$8bqBwVV!@wV^cBW* zj^EGLxfFRsVav|NJw3{9a^+NJ`YlNGgr6O_g!|tF6?ysy?xT8()O^Wwg4Xxb;ct>E z-~S;YJFVKf1sV1kBN8bfv_s@QQ3@pI>v78v&t0uFNA=bSM~i zy8d)n5%~7}XCm8x;ozuIxbr-R7iG!#t$;o2i)wzr*XPNV{qw4>o%m15>Y;+F! z&McB^wng*+dfpsCIy)LY_>pAInfe1%U&Uj6#u=M; zY0xxIZ09@*457e&3I1I|A>0Nz=gg{$u71H>C40_nIAs$ty+%TkpW(B>j6#HQF?_fD z@jk9IgzRkf-k~R!TLP3;KCj8WbZ>PuC|>$koxB%VZUxm$^f1hM+{ZX<3k-hXRSLcj zd%mq7k~Y1)dCv1}!7q-tGN>kkO`kVh>WiQM`m>R}aoiL9U{l28$fEW1V)VC2KeDsM zOxXjs?PIj@{q^66=tB5*4qmlaz}!+TvR)So+;Vrc&%d*B8n|8$UUKOA>nEu{mpL%5 zGWUZ{r6Z{$6xk}SrW)8-K(>pdO%1z6T=Tu0lWGwTU+ZeP+-=ou^U(HzmP z^3{kMKVvn=t>`^5<#ZRYugzl}C94Ialv-Y8dP7JN*?IQR&-DL)2y# zyvfVqb*DdG-J8HTW&ZN5QGd_C4^zWIEDg&_0E60{`}%x;J$1t&s%H#{jY7Eg7?5H0 z46Rhazp864qb>0p9i0>hiVzOdHI(v*4~EY z$(-}B;HZpOz(%P)upW5W_DIq{@#J9oI%=cnZBv)t#Gk_GB02#U2%$A9WK%?c%1X3a z0$I}!GTazuV}LBNl|TFh@M$`R@`Ksi(<-~uZ)chpiOULLHRfC~N~^N9^wq;R7)C!4 zv6)3aZ|{wpb@a6m!girR&lx9od_eN!0%)VaDF;mx!fr&UZS5F5R19dA@ z6$>o22{S@D|GYYSyD3N|wkv$3#n-C9ai*NwdU&KJIIk=ufNRnA1->&!B=h#4cI`sUL{{9t6caw^81o^(eQ>=d(g|67@Pt^j-G9Nz2;HCaaOJV`XfV415R| ztREGk7=MZwZBO3UUgKY1)Gs${@>i;LCO>|j7R&sq^tby9p8H1r-%O?jEkTfo)D-3; z=)?SN9iFEfVvU~t)n}$O(m0o}8#DYk{S_*7Iyt0WjodworHbvzXe;TgUoaH)jSzr( zD*sO=wLyfLfYybJsYbD8fmC5+hVortL~7R+=7``!7fWl%x$bnJ>Ls9$bfQj*?Sg8; zsR9!_Bcv-uG^7W4!B!8iI~ja(sMG)PY6cpI)+kK>5|!#5`4_JAA?T$)I$0P01=lw| z#J_W~o7Mou;MT24G$}+;FC-%lt*4XYp^v=(?!k6;ulP8ra0<_YHur0TFlHdgJ5f#1 z;L~}LVm^J1I0JivK7GFgkag%A^U-~%90p6;t|lLYbBU*4IkWxpYRemG6`Y{(3?9yt zwDB1_jqHd^PU+g+s1iylRQ(&$X;aKx0jlgy7NYw4m)J|M6K0c^m*~nrvXowDF=Syj zptz~`dGF*J3&vXSed51792!EA-AyW2oNm`C;r%r!w_YA}fK`&)y0n`KF)v_1@Lmpp6n|;Ow@;N5-xIgb%Xfns;1g=;QFyvH z9oqZvpvh>s=+1lS2~%tq**Z@K=DWVl2?MRiTd{nn`W3{5f6B| zrg@ku)WeKasWj(ov=ab~Lo!ttoX(-EEVgP|kuWh&|Iy@8DLO*>exh?s;KSlj)>|Go z&^7TEo~%!`httNtQw4u7qTm3sd1f00DK6uJ-^fG_^9?EYM|f?p{2UvW1ja;RkkNos z9=4AE3xGgLydP55W1ozB(u@lHrQ4Lp&oi-4;Bkt!UZg57_6vUSF{d}9bm`g=CT|LY z_DLNyxlq4#ik06~GDF5Ac+Pq5O;#c*+ zk7qb;JybUBtSp;E{UBM~jV}0NBTxwC9+ml)g8aNs@6gK|`V3e%@hA1IVs$Vx`43d* zFeM)s3%VgAGSqG{DR%K3ee~*7cp3(!56j&7f=7vbEl+}uMAL05r z2$N^7{5@_FOr zsOko5L48u27bEAxMN+kPKxgyTEE>Wr@B-(X;D4gOa|-_hDgWQVj0oV*US|sOU#RmO fnEu}ZV(h`G%Zof$rntR9Vo!Y?6YWY(1nPeQGXCWk From ae64c30eb924f510dcd674106c05bce15259766d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 13:46:55 +0100 Subject: [PATCH 094/825] inference: ensure to convert disjunction type to lub (IDEA-150364) --- .../ExpressionCompatibilityConstraint.java | 6 ++++- .../graphInference/DisjunctionTypes.java | 25 +++++++++++++++++++ .../GraphInferenceHighlightingTest.java | 4 +++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DisjunctionTypes.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java index b41c9b682873..df6028036b92 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java @@ -50,7 +50,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm return assignmentCompatible; } - final PsiType exprType = myExpression.getType(); + PsiType exprType = myExpression.getType(); if (exprType instanceof PsiLambdaParameterType) { return false; @@ -67,6 +67,10 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm } if (exprType != null && exprType != PsiType.NULL) { + if (exprType instanceof PsiDisjunctionType) { + exprType = ((PsiDisjunctionType)exprType).getLeastUpperBound(); + } + constraints.add(new TypeCompatibilityConstraint(myT, exprType)); } return true; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DisjunctionTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DisjunctionTypes.java new file mode 100644 index 000000000000..a310471923d9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DisjunctionTypes.java @@ -0,0 +1,25 @@ +class Test { + public static void main(String[] args) throws Exception { + try { + } + catch (Exception | Error e) { + throw identity(identity(e)); + } + + try { + } + catch (Exception | Error e) { + throw identity(e); + } + + try { + } + catch (Exception | Error e) { + throw e; + } + } + + public static T identity(T throwable) { + return throwable; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 0e724b542202..5b6ce1e04f13 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -359,6 +359,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase doTest(); } + public void testDisjunctionTypes() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } From 2ccb8c9d9c6a07223183d599464adbd07d319e8c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 14:03:46 +0100 Subject: [PATCH 095/825] convert anonym to inner: check vararg params (IDEA-150379) --- .../AnonymousToInnerHandler.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java index ea17b3c672b7..c4cc54bcfe74 100644 --- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerHandler.java @@ -37,6 +37,7 @@ import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.classMembers.ElementNeedsThis; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -115,7 +116,22 @@ public class AnonymousToInnerHandler implements RefactoringActionHandler { Map variableInfoMap = new LinkedHashMap(); collectUsedVariables(variableInfoMap, myAnonClass); - myVariableInfos = variableInfoMap.values().toArray(new VariableInfo[variableInfoMap.values().size()]); + final VariableInfo[] infos = variableInfoMap.values().toArray(new VariableInfo[variableInfoMap.values().size()]); + myVariableInfos = infos; + Arrays.sort(myVariableInfos, new Comparator() { + @Override + public int compare(VariableInfo o1, VariableInfo o2) { + final PsiType type1 = o1.variable.getType(); + final PsiType type2 = o2.variable.getType(); + if (type1 instanceof PsiEllipsisType) { + return 1; + } + if (type2 instanceof PsiEllipsisType) { + return -1; + } + return ArrayUtil.find(infos, o1) > ArrayUtil.find(infos, o2) ? 1 : -1; + } + }); if (!showRefactoringDialog()) return; CommandProcessor.getInstance().executeCommand( From 8c04e64f091aaeaad6ca37350fbbdc2789defc3d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 14:24:44 +0100 Subject: [PATCH 096/825] move members: ignore conflict if resolution was with static problems (IDEA-149968) --- .../refactoring/util/RefactoringConflictsUtil.java | 6 ++++-- .../after/Outer.java | 13 +++++++++++++ .../before/Outer.java | 12 ++++++++++++ .../com/intellij/refactoring/MoveMembersTest.java | 4 ++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/after/Outer.java create mode 100644 java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/before/Outer.java diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java index 7fb6a78b0bef..2d3480f02f26 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringConflictsUtil.java @@ -16,7 +16,6 @@ package com.intellij.refactoring.util; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; @@ -217,7 +216,10 @@ public class RefactoringConflictsUtil { } else if (newContext instanceof PsiClass && refMember instanceof PsiField && refMember.getContainingClass() == member.getContainingClass()) { final PsiField fieldInSubClass = ((PsiClass)newContext).findFieldByName(refMember.getName(), false); - if (fieldInSubClass != null && fieldInSubClass != refMember) { + if (fieldInSubClass != null && + !refMember.hasModifierProperty(PsiModifier.STATIC) && + fieldInSubClass != refMember && + !member.hasModifierProperty(PsiModifier.STATIC)) { conflicts.putValue(refMember, CommonRefactoringUtil.capitalize(RefactoringUIUtil.getDescription(fieldInSubClass, true) + " would hide " + RefactoringUIUtil.getDescription(refMember, true) + " which is used by moved " + RefactoringUIUtil.getDescription(member, false))); diff --git a/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/after/Outer.java b/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/after/Outer.java new file mode 100644 index 000000000000..72b623ce54b6 --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/after/Outer.java @@ -0,0 +1,13 @@ +class A { + + String myFoo; +} + +class B { + String myFoo; + + public static void foo(A a) { + System.out.println(myFoo); + System.out.println(a.myFoo); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/before/Outer.java b/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/before/Outer.java new file mode 100644 index 000000000000..a69b4f169185 --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/staticProblemsShouldNotRaiseAConflict/before/Outer.java @@ -0,0 +1,12 @@ +class A { + public static void foo(A a) { + System.out.println(myFoo); + System.out.println(a.myFoo); + } + + String myFoo; +} + +class B { + String myFoo; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java index 8561f61120e7..51f896f1c9d2 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java @@ -194,6 +194,10 @@ public class MoveMembersTest extends MultiFileTestCase { doTest("ImportingClass.Constants", "ImportingClass.ImportantConstants", 0); } + public void testStaticProblemsShouldNotRaiseAConflict() throws Exception { + doTest("A", "B", 0); + } + public void testFromNestedToOuterMethodRef() throws Exception { final LanguageLevelProjectExtension projectExtension = LanguageLevelProjectExtension.getInstance(getProject()); final LanguageLevel oldLevel = projectExtension.getLanguageLevel(); From c201af56b6d6269ded0b64d6b6e659eebb5657ee Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 15:55:42 +0100 Subject: [PATCH 097/825] generate toString: javadoc detection (IDEA-150016) --- .../jetbrains/java/generate/template/TemplateResource.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/template/TemplateResource.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/template/TemplateResource.java index 66bbc40ce690..07547226c8a5 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/template/TemplateResource.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/template/TemplateResource.java @@ -122,7 +122,7 @@ public class TemplateResource implements Serializable { */ @Nullable public String getJavaDoc() { - int i = template.indexOf("*/"); + int i = template.trim().startsWith("/*") ? template.indexOf("*/") : -1; if (i == -1) { return null; } @@ -163,7 +163,8 @@ public class TemplateResource implements Serializable { } private static String getMethodSignature(String template) { - String s = after(template, "*/").trim(); + final String trimmed = template.trim(); + String s = trimmed.startsWith("/*") ? after(trimmed, "*/") : trimmed; StringBuffer signature = new StringBuffer(); From aba892efefa59d5c526cec5db9e2c470d658ad4e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 14 Jan 2016 18:29:07 +0300 Subject: [PATCH 098/825] dumb-aware run configurations: EA-77744 --- .../intellij/execution/impl/ExecutionManagerImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java index 329fb249b4a4..62bad2f71358 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java @@ -40,6 +40,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -344,7 +345,14 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable if (!Registry.is("dumb.aware.run.configurations")) { DumbService.getInstance(myProject).runWhenSmart(startRunnable); } else { - startRunnable.run(); + try { + DumbService.getInstance(myProject).setAlternativeResolveEnabled(true); + startRunnable.run(); + } catch (IndexNotReadyException ignored) { + ExecutionUtil.handleExecutionError(environment, new ExecutionException("cannot start while indexing is in progress.")); + } finally { + DumbService.getInstance(myProject).setAlternativeResolveEnabled(false); + } } } } From f726604b18754e0c92286e7b3af5a89792680f7a Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 8 Jan 2016 15:15:30 +0100 Subject: [PATCH 099/825] method with primitive return type is not an actual clone() method --- .../src/com/siyeh/ig/psiutils/CloneUtils.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java index 89b9ab9757fd..770a1ba4c596 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2016 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +54,9 @@ public class CloneUtils { } else { // for 1.5 and after, clone may be covariant + if (method.getReturnType() instanceof PsiPrimitiveType) { + return false; + } javaLangObject = null; } return MethodUtils.methodMatches(method, null, javaLangObject, From 886c8fdc756ce1168f05f623888dac0c48b75125 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 8 Jan 2016 15:18:16 +0100 Subject: [PATCH 100/825] IG: simplify and add test --- .../ig/security/NonFinalCloneInspection.java | 18 +++------- .../security/NonFinalCloneInspection.java | 8 ----- .../non_final_clone/NonFinalClone.java | 8 +++++ .../security/NonFinalCloneInspectionTest.java | 36 +++++++++++++++++++ 4 files changed, 49 insertions(+), 21 deletions(-) delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/security/NonFinalCloneInspection.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/security/non_final_clone/NonFinalClone.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/security/NonFinalCloneInspectionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/NonFinalCloneInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/NonFinalCloneInspection.java index 170f4a689c56..cc8bc9522946 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/NonFinalCloneInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/security/NonFinalCloneInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2016 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,10 @@ package com.siyeh.ig.security; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiParameterList; -import com.siyeh.HardcodedMethodConstants; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.CloneUtils; import org.jetbrains.annotations.NotNull; public class NonFinalCloneInspection extends BaseInspection { @@ -50,24 +49,17 @@ public class NonFinalCloneInspection extends BaseInspection { @Override public void visitMethod(@NotNull PsiMethod method) { super.visitMethod(method); - final String name = method.getName(); - if (!HardcodedMethodConstants.CLONE.equals(name)) { + if (!CloneUtils.isClone(method)) { return; } - final PsiParameterList parameterList = method.getParameterList(); - if (parameterList.getParametersCount() != 0) { - return; - } - if (method.hasModifierProperty(PsiModifier.FINAL) - || method.hasModifierProperty(PsiModifier.ABSTRACT)) { + if (method.hasModifierProperty(PsiModifier.FINAL) || method.hasModifierProperty(PsiModifier.ABSTRACT)) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } - if (containingClass.hasModifierProperty(PsiModifier.FINAL) - || containingClass.isInterface()) { + if (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isInterface()) { return; } registerMethodError(method); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/security/NonFinalCloneInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/security/NonFinalCloneInspection.java deleted file mode 100644 index d842ab3f382f..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/security/NonFinalCloneInspection.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.siyeh.igtest.security; - - -public class NonFinalCloneInspection implements Cloneable{ - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } -} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/security/non_final_clone/NonFinalClone.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/security/non_final_clone/NonFinalClone.java new file mode 100644 index 000000000000..9482d115970e --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/security/non_final_clone/NonFinalClone.java @@ -0,0 +1,8 @@ +package com.siyeh.igtest.security; + + +public class NonFinalClone implements Cloneable{ + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/security/NonFinalCloneInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/security/NonFinalCloneInspectionTest.java new file mode 100644 index 000000000000..c924d9c59acd --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/security/NonFinalCloneInspectionTest.java @@ -0,0 +1,36 @@ +/* + * 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. + */ +package com.siyeh.ig.security; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class NonFinalCloneInspectionTest extends LightInspectionTestCase { + + public void testNonFinalClone() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new NonFinalCloneInspection(); + } +} \ No newline at end of file From 47e26ece65139285fca20042365e90c3350965cf Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 14 Jan 2016 19:10:37 +0300 Subject: [PATCH 101/825] IDEA-148164 Fix horisontal scrolling for right-to-left orientation --- .../src/com/intellij/ui/components/AbstractScrollBarUI.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-api/src/com/intellij/ui/components/AbstractScrollBarUI.java b/platform/platform-api/src/com/intellij/ui/components/AbstractScrollBarUI.java index 97ba2f587332..a0f6905badd0 100644 --- a/platform/platform-api/src/com/intellij/ui/components/AbstractScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/ui/components/AbstractScrollBarUI.java @@ -226,6 +226,7 @@ abstract class AbstractScrollBarUI extends ScrollBarUI { int value = getValue(); int maxX = myTrackBounds.x + myTrackBounds.width - width; int x = (value < max - extent) ? (myTrackBounds.width - width) * (value - min) / (range - extent) : maxX; + if (!myScrollBar.getComponentOrientation().isLeftToRight()) x = myTrackBounds.x - x + maxX; myThumbBounds.setBounds(adjust(x, myTrackBounds.x, maxX), myTrackBounds.y, width, myTrackBounds.height); } } From 1ee5b29520256cfd3dda71972f588e0694285117 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Fri, 25 Dec 2015 18:19:56 +0300 Subject: [PATCH 102/825] [vcs-log] VcsLog.getSelectedCommits returns list of CommitIds instead of Hashes --- .../src/com/intellij/vcs/log/CommitId.java | 0 .../api/src/com/intellij/vcs/log/VcsLog.java | 2 +- .../intellij/vcs/log/VcsLogDataProvider.java | 2 +- .../com/intellij/vcs/log/VcsLogHashMap.java | 2 +- .../vcs/log/data/AbstractDataGetter.java | 8 ++++---- .../com/intellij/vcs/log/data/DataPack.java | 2 +- .../vcs/log/data/VcsLogDataHolder.java | 4 ++-- .../vcs/log/data/VcsLogHashMapImpl.java | 10 +++++----- .../com/intellij/vcs/log/impl/VcsLogImpl.java | 12 +++++------ .../intellij/vcs/log/ui/frame/MainFrame.java | 8 ++++---- .../vcs/log/ui/tables/GraphTableModel.java | 12 +++++------ .../vcs/log/data/VcsLogRefresherTest.java | 2 +- .../vcs/log/data/VisiblePackBuilderTest.kt | 20 +++++++++---------- 13 files changed, 42 insertions(+), 42 deletions(-) rename platform/vcs-log/{impl => api}/src/com/intellij/vcs/log/CommitId.java (100%) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/CommitId.java b/platform/vcs-log/api/src/com/intellij/vcs/log/CommitId.java similarity index 100% rename from platform/vcs-log/impl/src/com/intellij/vcs/log/CommitId.java rename to platform/vcs-log/api/src/com/intellij/vcs/log/CommitId.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index 5718742f492f..f2f25061fd8f 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -32,7 +32,7 @@ public interface VcsLog { * Returns commits currently selected in the log. */ @NotNull - List getSelectedCommits(); + List getSelectedCommits(); /** * Returns details of the selected commits if all of them have been loaded. diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java index 55caadd9a270..597afd40082b 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; public interface VcsLogDataProvider { @NotNull - Hash getHash(int commitIndex); + CommitId getCommitId(int commitIndex); int getCommitIndex(@NotNull Hash hash, @NotNull VirtualFile root); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogHashMap.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogHashMap.java index 0c337b545250..8e65ee917e7c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogHashMap.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/VcsLogHashMap.java @@ -28,7 +28,7 @@ public interface VcsLogHashMap { int getCommitIndex(@NotNull Hash hash, @NotNull VirtualFile root); @NotNull - Hash getHash(int commitIndex); + CommitId getCommitId(int commitIndex); /** * Iterates over known commid id to find the first one which satisfies given condition. diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java index a4ce8cce6ed9..874fec2aba06 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java @@ -88,7 +88,7 @@ abstract class AbstractDataGetter implements Di @Nullable public T getCommitData(int row, @NotNull GraphTableModel tableModel) { assert EventQueue.isDispatchThread(); - Integer hash = tableModel.getCommitIdAtRow(row); + Integer hash = tableModel.getIdAtRow(row); T details = getFromCache(hash); if (details != null) { return details; @@ -140,7 +140,7 @@ abstract class AbstractDataGetter implements Di @Override public Hash compute() { - return myHashMap.getHash(commitId); + return myHashMap.getCommitId(commitId).getHash(); } }, taskNumber, root)); } @@ -158,7 +158,7 @@ abstract class AbstractDataGetter implements Di int below) { MultiMap commits = MultiMap.create(); for (int row = Math.max(0, selectedRow - above); row < selectedRow + below && row < model.getRowCount(); row++) { - Integer hash = model.getCommitIdAtRow(row); + Integer hash = model.getIdAtRow(row); VirtualFile root = model.getRoot(row); commits.putValue(root, hash); } @@ -170,7 +170,7 @@ abstract class AbstractDataGetter implements Di List hashStrings = ContainerUtil.map(entry.getValue(), new Function() { @Override public String fun(Integer commitId) { - return myHashMap.getHash(commitId).asString(); + return myHashMap.getCommitId(commitId).getHash().asString(); } }); List details = readDetails(myLogProviders.get(entry.getKey()), entry.getKey(), hashStrings); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java index 4aebe3f5750d..d230f3bda0b5 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java @@ -55,7 +55,7 @@ public class DataPack { @NotNull @Override public Hash fun(Integer commitIndex) { - return hashMap.getHash(commitIndex); + return hashMap.getCommitId(commitIndex).getHash(); } }; GraphColorManagerImpl colorManager = new GraphColorManagerImpl(refsModel, hashGetter, getRefManagerMap(providers)); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index 669db7dc3935..62014f0a99ae 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -126,8 +126,8 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { @Override @NotNull - public Hash getHash(int commitIndex) { - return myHashMap.getHash(commitIndex); + public CommitId getCommitId(int commitIndex) { + return myHashMap.getCommitId(commitIndex); } @Override diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMapImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMapImpl.java index 5fc13c493b89..bb3f4dcbcd36 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMapImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMapImpl.java @@ -61,7 +61,7 @@ public class VcsLogHashMapImpl implements Disposable, VcsLogHashMap { @NotNull @Override - public Hash getHash(int commitIndex) { + public CommitId getCommitId(int commitIndex) { throw new UnsupportedOperationException("Illegal access to empty hash map by index " + commitIndex); } @@ -125,7 +125,7 @@ public class VcsLogHashMapImpl implements Disposable, VcsLogHashMap { } @Nullable - private CommitId doGetHash(int index) throws IOException { + private CommitId doGetCommitId(int index) throws IOException { return myPersistentEnumerator.valueOf(index); } @@ -145,13 +145,13 @@ public class VcsLogHashMapImpl implements Disposable, VcsLogHashMap { @Override @NotNull - public Hash getHash(int commitIndex) { + public CommitId getCommitId(int commitIndex) { try { - CommitId commitId = doGetHash(commitIndex); + CommitId commitId = doGetCommitId(commitIndex); if (commitId == null) { throw new RuntimeException("Unknown commit index: " + commitIndex); // TODO this shouldn't happen => need to recreate the map } - return commitId.getHash(); + return commitId; } catch (IOException e) { throw new RuntimeException(e); // TODO map is corrupted => need to recreate it diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index 9efa903e864e..492f3843d5fb 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -45,16 +45,16 @@ public class VcsLogImpl implements VcsLog { @Override @NotNull - public List getSelectedCommits() { - List hashes = ContainerUtil.newArrayList(); + public List getSelectedCommits() { + List commitIds = ContainerUtil.newArrayList(); JBTable table = myUi.getTable(); for (int row : table.getSelectedRows()) { - Hash hash = ((GraphTableModel)table.getModel()).getHashAtRow(row); - if (hash != null) { - hashes.add(hash); + CommitId commitId = ((GraphTableModel)table.getModel()).getCommitIdAtRow(row); + if (commitId != null) { + commitIds.add(commitId); } } - return hashes; + return commitIds; } @NotNull diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 5657db8e12eb..66b2fd0bee33 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -326,11 +326,11 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { })); } else if (VcsDataKeys.VCS_REVISION_NUMBERS == key) { - List hashes = myUI.getVcsLog().getSelectedCommits(); - sink.put(key, ArrayUtil.toObjectArray(ContainerUtil.map(hashes, new Function() { + List hashes = myUI.getVcsLog().getSelectedCommits(); + sink.put(key, ArrayUtil.toObjectArray(ContainerUtil.map(hashes, new Function() { @Override - public VcsRevisionNumber fun(Hash hash) { - return convertToRevisionNumber(hash); + public VcsRevisionNumber fun(CommitId commitId) { + return convertToRevisionNumber(commitId.getHash()); } }), VcsRevisionNumber.class)); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index b374beef1c59..6f87dd1ef81d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -61,7 +61,7 @@ public class GraphTableModel extends AbstractTableModel { int head = myDataPack.getVisibleGraph().getRowInfo(rowIndex).getOneOfHeads(); Collection refs = myDataPack.getRefsModel().refsToCommit(head); if (refs.isEmpty()) { - LOG.error("No references pointing to head " + myDataHolder.getHash(head) + " identified for commit at row " + rowIndex, + LOG.error("No references pointing to head " + myDataHolder.getCommitId(head) + " identified for commit at row " + rowIndex, new Attachment("details.txt", getErrorDetails())); // take the first root: it is the right choice in one-repo case, though it will likely fail in multi-repo case return myDataPack.getLogProviders().keySet().iterator().next(); @@ -76,7 +76,7 @@ public class GraphTableModel extends AbstractTableModel { List> commits = myDataPack.getPermanentGraph().getAllCommits(); for (int i = 0; i < 100 && i < commits.size(); i++) { GraphCommit commit = commits.get(i); - sb.append(String.format("%s -> %s\n", myDataHolder.getHash(commit.getId()).toShortString(), getParents(commit))); + sb.append(String.format("%s -> %s\n", myDataHolder.getCommitId(commit.getId()).getHash().toShortString(), getParents(commit))); } sb.append("\nALL REFS:\n"); printRefs(sb, myDataPack.getRefsModel().getAllRefsByRoot()); @@ -88,7 +88,7 @@ public class GraphTableModel extends AbstractTableModel { return StringUtil.join(commit.getParents(), new Function() { @Override public String fun(Integer integer) { - return myDataHolder.getHash(integer).toShortString(); + return myDataHolder.getCommitId(integer).getHash().toShortString(); } }, ", "); } @@ -117,13 +117,13 @@ public class GraphTableModel extends AbstractTableModel { } @NotNull - public Integer getCommitIdAtRow(int row) { + public Integer getIdAtRow(int row) { return myDataPack.getVisibleGraph().getRowInfo(row).getCommit(); } @Nullable - public Hash getHashAtRow(int row) { - return myDataHolder.getHash(getCommitIdAtRow(row)); + public CommitId getCommitIdAtRow(int row) { + return myDataHolder.getCommitId(getIdAtRow(row)); } public int getRowOfCommit(@NotNull final Hash hash, @NotNull VirtualFile root) { diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java index acf26d51c312..2c50ebdee6f6 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java @@ -236,7 +236,7 @@ public class VcsLogRefresherTest extends VcsLogPlatformTest { @NotNull @Override public Hash fun(Integer integer) { - return myDataHolder.getHash(integer); + return myDataHolder.getCommitId(integer).getHash(); } }; return new TimedVcsCommitImpl(convertor.fun(commit.getId()), ContainerUtil.map(commit.getParents(), convertor), diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt index e844da1f80de..592fca3eb5a9 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt @@ -116,7 +116,7 @@ class VisiblePackBuilderTest { assertDoesNotContain(visibleGraph, 1) } - private fun GraphCommit.toVcsCommit(map: VcsLogHashMap) = TimedVcsCommitImpl(map.getHash(this.getId()), map.getHashes(this.getParents()), 1) + private fun GraphCommit.toVcsCommit(map: VcsLogHashMap) = TimedVcsCommitImpl(map.getCommitId(this.getId()).hash, map.getHashes(this.getParents()), 1) fun assertDoesNotContain(graph: VisibleGraph, id: Int) { assertTrue(null == (1..graph.getVisibleCommitCount()).firstOrNull { graph.getRowInfo(it - 1).getCommit() == id }) @@ -130,16 +130,16 @@ class VisiblePackBuilderTest { val data: HashMap, Data>) { val root: VirtualFile = MockVirtualFile("root") val providers: Map = mapOf(root to TestVcsLogProvider(root)) - val hashMap = generateHashMap(commits.maxBy { it.getId() }!!.getId()) + val hashMap = generateHashMap(commits.maxBy { it.getId() }!!.getId(), root) fun build(filters: VcsLogFilterCollection): VisiblePack { val refs = refs.mapTo(HashSet(), { - VcsRefImpl(hashMap.getHash(it.commit), it.name, BRANCH_TYPE, root) + VcsRefImpl(hashMap.getCommitId(it.commit).hash, it.name, BRANCH_TYPE, root) }) val dataPack = DataPack.build(commits, mapOf(root to refs), providers, hashMap, true) val detailsCache = data.entries.map { - val hash = hashMap.getHash(it.key.getId()) + val hash = hashMap.getCommitId(it.key.getId()).hash val metadata = if (it.value.user == null) null else VcsCommitMetadataImpl(hash, hashMap.getHashes(it.key.getParents()), 1L, root, it.value.subject, @@ -161,17 +161,17 @@ class VisiblePackBuilderTest { return builder.build(dataPack, PermanentGraph.SortType.Normal, filters, CommitCountStage.INITIAL).first } - fun generateHashMap(num: Int): VcsLogHashMap { + fun generateHashMap(num: Int, root: VirtualFile): VcsLogHashMap { val map = HashMap() for (i in 1..num) { map.put(HashImpl.build(i.toString()), i) } - return ConstantVcsLogHashMap(map) + return ConstantVcsLogHashMap(map, root) } } - fun VcsLogHashMap.getHashes(ids: List) = ids.map { getHash(it) } + fun VcsLogHashMap.getHashes(ids: List) = ids.map { getCommitId(it).hash } fun noFilters(): VcsLogFilterCollection = VcsLogFilterCollectionImpl(null, null, null, null, null, null, null) @@ -225,12 +225,12 @@ class VisiblePackBuilderTest { fun done() = Graph(commits, refs, data) } - class ConstantVcsLogHashMap(val map: Map) : VcsLogHashMap { - val reverseMap = map.entries.map { Pair(it.value, it.key) }.toMap() + class ConstantVcsLogHashMap(val map: Map, val root: VirtualFile) : VcsLogHashMap { + val reverseMap = map.entrySet().map { Pair(it.value, it.key) }.toMap() override fun getCommitIndex(hash: Hash, root: VirtualFile) = map.get(hash)!! - override fun getHash(commitIndex: Int) = reverseMap.get(commitIndex)!! + override fun getCommitId(commitIndex: Int) = CommitId(reverseMap.get(commitIndex)!!, root) override fun findCommitId(condition: Condition): CommitId? = throw UnsupportedOperationException() } From 34b90688e98fd42a0416c927cd57c4fc8c9579c0 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Mon, 8 Jun 2015 16:20:53 +0300 Subject: [PATCH 103/825] [vcs-log] introduce lazy list with commit details/hashes and check no more then 100 first commits in action update methods IDEA-141067 --- .../dvcs/cherrypick/VcsCherryPickAction.java | 18 +++-- .../com/intellij/dvcs/ui/VcsLogAction.java | 17 ++-- .../dvcs/ui/VcsLogSingleCommitAction.java | 79 +++++++++++++++---- .../api/src/com/intellij/vcs/log/VcsLog.java | 4 +- .../com/intellij/vcs/log/impl/VcsLogImpl.java | 46 ++++++----- .../com/intellij/vcs/log/impl/VcsLogUtil.java | 20 +++++ .../vcs/log/ui/tables/GraphTableModel.java | 2 +- ...ithubShowCommitInBrowserFromLogAction.java | 16 +++- .../action/mq/HgMqAppliedPatchAction.java | 6 +- .../action/mq/HgQImportFromLogAction.java | 6 +- 10 files changed, 151 insertions(+), 63 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index 8a2f487be400..bd648865da74 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -18,7 +18,6 @@ package com.intellij.dvcs.cherrypick; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; @@ -30,12 +29,17 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerEx; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashMap; -import com.intellij.vcs.log.*; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.impl.VcsLogUtil; import icons.DvcsImplIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,10 +47,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsCherryPickAction extends DumbAwareAction { - private static final String NAME = "Cherry-Pick"; - private static final Logger LOG = Logger.getInstance(VcsCherryPickAction.class); - @NotNull private final Set myIdsInProgress; public VcsCherryPickAction() { @@ -58,7 +59,7 @@ public class VcsCherryPickAction extends DumbAwareAction { public void actionPerformed(AnActionEvent e) { final Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - final List commits = log.getSelectedDetails(); + final List commits = VcsLogUtil.collectLoadedSelectedDetails(log, false); for (VcsFullCommitDetails commit : commits) { myIdsInProgress.add(commit.getId()); @@ -108,7 +109,8 @@ public class VcsCherryPickAction extends DumbAwareAction { for (VcsFullCommitDetails commit : commits) { VcsCherryPicker cherryPicker = getCherryPickerForCommit(project, projectLevelVcsManager, commit); if (cherryPicker == null) { - LOG.warn("Cherry pick is not supported for " + commit.getRoot().getName()); + VcsNotifier.getInstance(project).notifyWeakError( + "Cherry pick is not supported for commit " + commit.getId().toShortString() + " from root " + commit.getRoot().getName()); return Collections.emptyMap(); } List list = resultMap.get(cherryPicker); @@ -142,7 +144,7 @@ public class VcsCherryPickAction extends DumbAwareAction { return; } - final List details = log.getSelectedDetails(); + final List details = VcsLogUtil.collectLoadedSelectedDetails(log, true); VcsCherryPicker enabledCherryPicker = ContainerUtil.find(cherryPickers, new Condition() { @Override public boolean value(VcsCherryPicker picker) { diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 23622c3f25e9..936eda2291a7 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -23,12 +23,14 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.impl.VcsLogUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,9 +42,8 @@ public abstract class VcsLogAction extends DumbAwareAct public void actionPerformed(@NotNull AnActionEvent e) { Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - List details = log.getSelectedDetails(); - MultiMap grouped = groupByRootWithCheck(project, details); - assert grouped != null; + MultiMap grouped = getGroupedCommits(project, log, false); + if (grouped == null) return; actionPerformed(project, grouped); } @@ -55,8 +56,7 @@ public abstract class VcsLogAction extends DumbAwareAct return; } - List details = log.getSelectedDetails(); - MultiMap grouped = groupByRootWithCheck(project, details); + MultiMap grouped = getGroupedCommits(project, log, true); if (grouped == null) { e.getPresentation().setEnabledAndVisible(false); } @@ -87,11 +87,16 @@ public abstract class VcsLogAction extends DumbAwareAct protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root); @Nullable - private MultiMap groupByRootWithCheck(@NotNull Project project, @NotNull List commits) { + private MultiMap getGroupedCommits(@NotNull Project project, @NotNull VcsLog log, boolean fromUpdate) { + List commits = VcsLogUtil.collectLoadedSelectedDetails(log, fromUpdate); MultiMap map = MultiMap.create(); for (VcsFullCommitDetails commit : commits) { Repo root = getRepositoryForRoot(project, commit.getRoot()); if (root == null) { // commit from some other VCS + if (!fromUpdate) { + VcsNotifier.getInstance(project).notifyWeakError( + "Can not perform action on commit " + commit.getId().toShortString() + " from root " + commit.getRoot().getName()); + } return null; } map.putValue(root, commit); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java index 9b9c7434cf9d..5c11a232d003 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,32 +15,83 @@ */ package com.intellij.dvcs.ui; +import com.intellij.dvcs.repo.AbstractRepositoryManager; import com.intellij.dvcs.repo.Repository; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.util.containers.MultiMap; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.data.LoadingDetails; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.Map; +import java.util.List; -public abstract class VcsLogSingleCommitAction extends VcsLogAction { +public abstract class VcsLogSingleCommitAction extends DumbAwareAction { @Override - protected boolean isEnabled(@NotNull MultiMap grouped) { - return grouped.values().size() == 1; + public void actionPerformed(@NotNull AnActionEvent e) { + Project project = e.getRequiredData(CommonDataKeys.PROJECT); + VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); + + VcsFullCommitDetails details = ContainerUtil.getFirstItem(log.getSelectedDetails()); + assert details != null; + Repo repository = getRepositoryForRoot(project, details.getRoot()); + assert repository != null; + + actionPerformed(repository, details); } @Override - protected void actionPerformed(@NotNull Project project, @NotNull MultiMap grouped) { - assert grouped.size() == 1; - Map.Entry> entry = grouped.entrySet().iterator().next(); - Repo repository = entry.getKey(); - Collection commits = entry.getValue(); - assert commits.size() == 1; - actionPerformed(repository, commits.iterator().next()); + public void update(@NotNull AnActionEvent e) { + Project project = e.getProject(); + VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG); + if (project == null || log == null) { + e.getPresentation().setEnabledAndVisible(false); + return; + } + + List selectedDetails = log.getSelectedDetails(); + if (selectedDetails.isEmpty()) { + e.getPresentation().setEnabledAndVisible(false); + } + else { + VcsFullCommitDetails details = ContainerUtil.getFirstItem(selectedDetails); + if (details == null || details instanceof LoadingDetails) { + e.getPresentation().setEnabledAndVisible(false); + } + else { + Repo repository = getRepositoryForRoot(project, details.getRoot()); + + if (repository == null) { + e.getPresentation().setEnabledAndVisible(false); + } + else { + e.getPresentation().setVisible(isVisible(project, repository, details)); + e.getPresentation().setEnabled(selectedDetails.size() == 1 && isEnabled(repository, details)); + } + } + } } protected abstract void actionPerformed(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit); + protected boolean isEnabled(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit) { + return true; + } + + protected boolean isVisible(@NotNull final Project project, @NotNull Repo repository, @NotNull VcsFullCommitDetails commit) { + return !getRepositoryManager(project).isExternal(repository); + } + + @NotNull + protected abstract AbstractRepositoryManager getRepositoryManager(@NotNull Project project); + + @Nullable + protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index f2f25061fd8f..297c8d6c9ca4 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -35,8 +35,8 @@ public interface VcsLog { List getSelectedCommits(); /** - * Returns details of the selected commits if all of them have been loaded. - * To avoid data inconsistency, if at least one of the selected commits have no details loaded, empty list is returned. + * Returns details of the selected commits. + * For commits that are not loaded an instance of LoadingDetails is returned. */ @NotNull List getSelectedDetails(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index 492f3843d5fb..d62eb930726c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -16,7 +16,6 @@ package com.intellij.vcs.log.impl; import com.intellij.openapi.util.Condition; -import com.intellij.ui.table.JBTable; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.VcsLogDataHolder; @@ -26,6 +25,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.AbstractList; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Future; @@ -34,7 +35,6 @@ import java.util.concurrent.Future; * */ public class VcsLogImpl implements VcsLog { - @NotNull private final VcsLogDataHolder myDataHolder; @NotNull private final VcsLogUiImpl myUi; @@ -46,31 +46,37 @@ public class VcsLogImpl implements VcsLog { @Override @NotNull public List getSelectedCommits() { - List commitIds = ContainerUtil.newArrayList(); - JBTable table = myUi.getTable(); - for (int row : table.getSelectedRows()) { - CommitId commitId = ((GraphTableModel)table.getModel()).getCommitIdAtRow(row); - if (commitId != null) { - commitIds.add(commitId); + final int[] rows = myUi.getTable().getSelectedRows(); + return new AbstractList() { + @NotNull + @Override + public CommitId get(int index) { + return ((GraphTableModel)myUi.getTable().getModel()).getCommitIdAtRow(rows[index]); } - } - return commitIds; + + @Override + public int size() { + return rows.length; + } + }; } @NotNull @Override public List getSelectedDetails() { - List details = ContainerUtil.newArrayList(); - JBTable table = myUi.getTable(); - for (int row : table.getSelectedRows()) { - GraphTableModel model = (GraphTableModel)table.getModel(); - VcsFullCommitDetails commitDetails = model.getFullCommitDetails(row); - if (commitDetails == null) { - return ContainerUtil.emptyList(); + final int[] rows = myUi.getTable().getSelectedRows(); + return new AbstractList() { + @NotNull + @Override + public VcsFullCommitDetails get(int index) { + return myDataHolder.getCommitDetailsGetter().getCommitData(rows[index], (GraphTableModel)myUi.getTable().getModel()); } - details.add(commitDetails); - } - return details; + + @Override + public int size() { + return rows.length; + } + }; } @Nullable diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java index 2fc4be9755a3..90c95916c75e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java @@ -23,6 +23,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.*; +import com.intellij.vcs.log.data.LoadingDetails; import com.intellij.vcs.log.graph.VisibleGraph; import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; @@ -31,6 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsLogUtil { + private static final int DETAILS_LIMIT = 100; @NotNull public static MultiMap groupRefsByRoot(@NotNull Collection refs) { @@ -168,6 +170,24 @@ public class VcsLogUtil { return new HashSet(rootsAndFiles.second.get(root)); } + // If this method stumbles on LoadingDetails instance it returns empty list + // Also, can be slow when many details are selected + public static List collectLoadedSelectedDetails(@NotNull VcsLog log, boolean limitDetails) { + List result = ContainerUtil.newArrayList(); + + for (VcsFullCommitDetails next : log.getSelectedDetails()) { + if (next instanceof LoadingDetails) { + return Collections.emptyList(); + } + else { + result.add(next); + if (result.size() >= DETAILS_LIMIT && limitDetails) break; + } + } + + return result; + } + @NotNull public static Collection getVisibleBranches(@NotNull VcsLog log, VcsLogUiImpl logUi) { VcsLogFilterCollection filters = logUi.getFilterUi().getFilters(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 6f87dd1ef81d..4c88002ae2fa 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -121,7 +121,7 @@ public class GraphTableModel extends AbstractTableModel { return myDataPack.getVisibleGraph().getRowInfo(row).getCommit(); } - @Nullable + @NotNull public CommitId getCommitIdAtRow(int row) { return myDataHolder.getCommitId(getIdAtRow(row)); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java index 4491a1a020db..baaaaed26de7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java @@ -18,9 +18,11 @@ package org.jetbrains.plugins.github; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.Project; +import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.data.LoadingDetails; import git4idea.GitUtil; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; @@ -38,19 +40,25 @@ public class GithubShowCommitInBrowserFromLogAction extends GithubShowCommitInBr e.getPresentation().setEnabledAndVisible(false); return; } - List commits = log.getSelectedDetails(); - if (commits.size() != 1) { + List selectedDetails = log.getSelectedDetails(); + if (selectedDetails.size() != 1) { e.getPresentation().setEnabledAndVisible(false); return; } - GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(commits.get(0).getRoot()); + VcsFullCommitDetails details = ContainerUtil.getFirstItem(selectedDetails); + if (details == null || details instanceof LoadingDetails) { + e.getPresentation().setEnabledAndVisible(false); + return; + } + GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(details.getRoot()); e.getPresentation().setEnabledAndVisible(repository != null && GithubUtil.isRepositoryOnGitHub(repository)); } @Override public void actionPerformed(@NotNull AnActionEvent e) { Project project = e.getRequiredData(CommonDataKeys.PROJECT); - VcsFullCommitDetails commit = e.getRequiredData(VcsLogDataKeys.VCS_LOG).getSelectedDetails().get(0); + VcsFullCommitDetails commit = ContainerUtil.getFirstItem(e.getRequiredData(VcsLogDataKeys.VCS_LOG).getSelectedDetails()); + assert commit != null && !(commit instanceof LoadingDetails); GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(commit.getRoot()); openInBrowser(project, repository, commit.getId().asString()); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java index 6ba98090a0b3..4195eb83f7f7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java @@ -17,7 +17,6 @@ package org.zmlx.hg4idea.action.mq; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgNameWithHashInfo; @@ -27,9 +26,8 @@ import org.zmlx.hg4idea.repo.HgRepository; public abstract class HgMqAppliedPatchAction extends HgLogSingleCommitAction { @Override - protected boolean isEnabled(@NotNull MultiMap grouped) { - return super.isEnabled(grouped) && - isAppliedPatch(grouped.keySet().iterator().next(), grouped.values().iterator().next()); + protected boolean isEnabled(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { + return super.isEnabled(repository, commit) && isAppliedPatch(repository, commit); } public static boolean isAppliedPatch(@NotNull HgRepository repository, @NotNull final VcsFullCommitDetails commitDetails) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java index a271cd87005e..24e247337d0d 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java @@ -15,7 +15,6 @@ */ package org.zmlx.hg4idea.action.mq; -import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.action.HgLogSingleCommitAction; @@ -30,8 +29,7 @@ public class HgQImportFromLogAction extends HgLogSingleCommitAction { } @Override - protected boolean isEnabled(@NotNull MultiMap grouped) { - return super.isEnabled(grouped) && - !HgMqAppliedPatchAction.isAppliedPatch(grouped.keySet().iterator().next(), grouped.values().iterator().next()); + protected boolean isEnabled(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { + return super.isEnabled(repository, commit) && !HgMqAppliedPatchAction.isAppliedPatch(repository, commit); } } From 3d79dd47895daed7bf4b623b00392e5cbe15bd28 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 3 Sep 2015 20:39:59 +0300 Subject: [PATCH 104/825] [git] commit time in test is in ms while git uses seconds --- plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java index 6a2c5a8eff19..43a8b0671667 100644 --- a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java +++ b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java @@ -256,7 +256,7 @@ public class GitLogProviderTest extends GitSingleRepoTest { @Override public VcsCommitMetadata fun(String record) { String[] items = ArrayUtil.toStringArray(StringUtil.split(record, "|", true, false)); - long time = Long.valueOf(items[2]); + long time = Long.valueOf(items[2]) * 1000; return new VcsCommitMetadataImpl(TO_HASH.fun(items[0]), ContainerUtil.map(items[1].split(" "), TO_HASH), time, myProjectRoot, items[3], defaultUser, items[4], defaultUser, time); } From 066253c58664845376baa3b400c35f5f87db631e Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 3 Sep 2015 20:45:20 +0300 Subject: [PATCH 105/825] [git] load short and full details in chunks --- .../src/git4idea/log/GitLogProvider.java | 28 +++++-- .../git4idea/log/GitLogProviderTest.java | 77 +++++++++++++++++++ .../tests/git4idea/test/GitExecutor.java | 7 +- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 6fb284755d3b..ed5b9afeea23 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -33,6 +33,7 @@ import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl; import com.intellij.vcs.log.impl.HashImpl; import com.intellij.vcs.log.impl.LogDataImpl; import com.intellij.vcs.log.util.StopWatch; +import com.intellij.vcsUtil.VcsFileUtil; import git4idea.*; import git4idea.branch.GitBranchUtil; import git4idea.branch.GitBranchesCollection; @@ -334,17 +335,32 @@ public class GitLogProvider implements VcsLogProvider { @Override public List readShortDetails(@NotNull VirtualFile root, @NotNull List hashes) throws VcsException { - return GitHistoryUtils.readMiniDetails(myProject, root, hashes); + List result = ContainerUtil.newArrayList(); + List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); + + for (List hashesChunk : hashesChunks) { + result.addAll(GitHistoryUtils.readMiniDetails(myProject, root, hashesChunk)); + } + + return result; } @NotNull @Override public List readFullDetails(@NotNull VirtualFile root, @NotNull List hashes) throws VcsException { - String noWalk = GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(myVcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk"; - List params = new ArrayList(); - params.add(noWalk); - params.addAll(hashes); - return GitHistoryUtils.history(myProject, root, ArrayUtil.toStringArray(params)); + List result = ContainerUtil.newArrayList(); + List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); + + for (List hashesChunk : hashesChunks) { + String noWalk = GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(myVcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk"; + List params = new ArrayList(); + params.add(noWalk); + params.addAll(hashesChunk); + + result.addAll(GitHistoryUtils.history(myProject, root, ArrayUtil.toStringArray(params))); + } + + return result; } @NotNull diff --git a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java index 43a8b0671667..03b6b76ecd4c 100644 --- a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java +++ b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java @@ -23,18 +23,21 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.CollectConsumer; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.VcsLogBranchFilterImpl; import com.intellij.vcs.log.impl.*; import com.intellij.vcs.log.ui.filter.VcsLogUserFilterImpl; +import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitVcs; import git4idea.test.GitSingleRepoTest; import git4idea.test.GitTestUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Set; @@ -180,6 +183,68 @@ public class GitLogProviderTest extends GitSingleRepoTest { assertEquals(hashes, actualHashes); } + public void test_short_details() throws Exception { + prepareLongHistory(VcsFileUtil.FILE_PATH_LIMIT * 2 / 40); + List log = log(); + + final List hashes = ContainerUtil.newArrayList(); + myLogProvider.readAllHashes(myProjectRoot, new Consumer() { + @Override + public void consume(TimedVcsCommit timedVcsCommit) { + hashes.add(timedVcsCommit.getId().asString()); + } + }); + + List shortDetails = myLogProvider.readShortDetails(myProjectRoot, hashes); + + Function shortDetailsToString = getShortDetailsToString(); + assertOrderedEquals(ContainerUtil.map(shortDetails, shortDetailsToString), ContainerUtil.map(log, shortDetailsToString)); + } + + public void test_full_details() throws Exception { + prepareLongHistory(VcsFileUtil.FILE_PATH_LIMIT * 2 / 40); + List log = log(); + + final List hashes = ContainerUtil.newArrayList(); + myLogProvider.readAllHashes(myProjectRoot, new Consumer() { + @Override + public void consume(TimedVcsCommit timedVcsCommit) { + hashes.add(timedVcsCommit.getId().asString()); + } + }); + + List fullDetails = myLogProvider.readFullDetails(myProjectRoot, hashes); + + // we do not check for changes here + final Function shortDetailsToString = getShortDetailsToString(); + Function metadataToString = new Function() { + @Override + public String fun(VcsCommitMetadata details) { + return shortDetailsToString.fun(details) + "\n" + details.getFullMessage(); + } + }; + assertOrderedEquals(ContainerUtil.map(fullDetails, metadataToString), ContainerUtil.map(log, metadataToString)); + } + + @NotNull + private Function getShortDetailsToString() { + return new Function() { + @Override + public String fun(VcsShortCommitDetails details) { + String result = ""; + + result += details.getId().toShortString() + "\n"; + result += details.getAuthorTime() + "\n"; + result += details.getAuthor() + "\n"; + result += details.getCommitTime() + "\n"; + result += details.getCommitter() + "\n"; + result += details.getSubject(); + + return result; + } + }; + } + /** * Generates some history with two branches: master and feature, and made by two users. * Returns hashes of this history filtered by the given parameters: @@ -228,6 +293,18 @@ public class GitLogProviderTest extends GitSingleRepoTest { tac("b.txt"); } + private static void prepareLongHistory(int size) throws IOException { + for (int i = 0; i < size; i++) { + String file = "a" + (i % 10) + ".txt"; + if (i < 10) { + tac(file); + } + else { + modify(file); + } + } + } + private static void createTaggedBranch() { String hash = last(); tac("c.txt"); diff --git a/plugins/git4idea/tests/git4idea/test/GitExecutor.java b/plugins/git4idea/tests/git4idea/test/GitExecutor.java index 3a952a0281a6..5b87a216b0ee 100644 --- a/plugins/git4idea/tests/git4idea/test/GitExecutor.java +++ b/plugins/git4idea/tests/git4idea/test/GitExecutor.java @@ -29,7 +29,6 @@ import java.util.List; import static org.junit.Assert.assertFalse; /** - * * @author Kirill Likhodedov */ public class GitExecutor extends Executor { @@ -126,6 +125,12 @@ public class GitExecutor extends Executor { return addCommit("touched " + file); } + @NotNull + public static String modify(@NotNull String file) throws IOException { + overwrite(file, "content" + Math.random()); + return addCommit("modified " + file); + } + @NotNull public static String last() { return git("log -1 --pretty=%H"); From 937ddd2ef6fdd84c18ce037e4fb7b7ffdfbb8af1 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 3 Sep 2015 21:23:10 +0300 Subject: [PATCH 106/825] [hg] load short and full details in chunks --- .../org/zmlx/hg4idea/log/HgHistoryUtil.java | 70 ++++++++++++------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java index ac15597263ac..e8b2084f1ae4 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java @@ -35,6 +35,7 @@ import com.intellij.util.Function; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; +import com.intellij.vcsUtil.VcsFileUtil; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -98,8 +99,8 @@ public class HgHistoryUtil { public static List history(@NotNull final Project project, @NotNull final VirtualFile root, int limit, - @NotNull List parameters) throws VcsException { - return history(project, root, limit, parameters, false); + @NotNull List hashParameters) throws VcsException { + return history(project, root, limit, hashParameters, false); } /** @@ -113,14 +114,22 @@ public class HgHistoryUtil { public static List history(@NotNull final Project project, @NotNull final VirtualFile root, int limit, - @NotNull List parameters, + @NotNull List hashParameters, boolean silent) throws VcsException { HgVcs hgvcs = HgVcs.getInstance(project); assert hgvcs != null; final HgVersion version = hgvcs.getVersion(); String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); - HgCommandResult result = getLogResult(project, root, version, limit, parameters, HgChangesetUtil.makeTemplate(templates)); - return createFullCommitsFromResult(project, root, result, version, silent); + + List result = ContainerUtil.newArrayList(); + List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashParameters); + + for (List hashesChunk : hashesChunks) { + HgCommandResult logResult = getLogResult(project, root, version, limit, hashesChunk, HgChangesetUtil.makeTemplate(templates)); + result.addAll(createFullCommitsFromResult(project, root, logResult, version, silent)); + } + + return result; } public static List createFullCommitsFromResult(@NotNull Project project, @@ -243,33 +252,44 @@ public class HgHistoryUtil { if (factory == null) { return Collections.emptyList(); } + HgVcs hgvcs = HgVcs.getInstance(project); assert hgvcs != null; HgVersion version = hgvcs.getVersion(); List templateList = HgBaseLogParser.constructDefaultTemplate(version); templateList.add("{desc}"); String[] templates = ArrayUtil.toStringArray(templateList); - HgCommandResult result = getLogResult(project, root, version, -1, prepareHashes(hashes), HgChangesetUtil.makeTemplate(templates)); - return getCommitRecords(project, result, new HgBaseLogParser() { - @Override - protected VcsShortCommitDetails convertDetails(@NotNull String rev, - @NotNull String changeset, - @NotNull SmartList parents, - @NotNull Date revisionDate, - @NotNull String author, - @NotNull String email, - @NotNull List attributes) { - String message = parseAdditionalStringAttribute(attributes, MESSAGE_INDEX); - String subject = extractSubject(message); - List parentsHash = new SmartList(); - for (HgRevisionNumber parent : parents) { - parentsHash.add(factory.createHash(parent.getChangeset())); + + List result = ContainerUtil.newArrayList(); + List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); + + for (List hashesChunk : hashesChunks) { + HgCommandResult logResult = + getLogResult(project, root, version, -1, prepareHashes(hashesChunk), HgChangesetUtil.makeTemplate(templates)); + + result.addAll(getCommitRecords(project, logResult, new HgBaseLogParser() { + @Override + protected VcsShortCommitDetails convertDetails(@NotNull String rev, + @NotNull String changeset, + @NotNull SmartList parents, + @NotNull Date revisionDate, + @NotNull String author, + @NotNull String email, + @NotNull List attributes) { + String message = parseAdditionalStringAttribute(attributes, MESSAGE_INDEX); + String subject = extractSubject(message); + List parentsHash = new SmartList(); + for (HgRevisionNumber parent : parents) { + parentsHash.add(factory.createHash(parent.getChangeset())); + } + return factory + .createShortDetails(factory.createHash(changeset), parentsHash, revisionDate.getTime(), root, subject, author, email, author, + email, revisionDate.getTime()); } - return factory.createShortDetails(factory.createHash(changeset), parentsHash, - revisionDate.getTime(), root, - subject, author, email, author, email, revisionDate.getTime()); - } - }); + })); + } + + return result; } @NotNull From 75425014da93e4f4fcd552eca52e731a945b6662 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Mon, 7 Sep 2015 21:07:47 +0300 Subject: [PATCH 107/825] [vcs-log] check for progress indicator being cancelled while processing arguments by chunks --- .../util/ThrowableNotNullFunction.java | 23 +++++ .../src/com/intellij/vcsUtil/VcsFileUtil.java | 57 +++++++++--- .../src/git4idea/log/GitLogProvider.java | 46 +++++----- .../hg4idea/command/HgCommitTypeCommand.java | 2 +- .../zmlx/hg4idea/command/HgRemoveCommand.java | 2 +- .../org/zmlx/hg4idea/log/HgHistoryUtil.java | 92 +++++++++---------- 6 files changed, 140 insertions(+), 82 deletions(-) create mode 100644 platform/util/src/com/intellij/openapi/util/ThrowableNotNullFunction.java diff --git a/platform/util/src/com/intellij/openapi/util/ThrowableNotNullFunction.java b/platform/util/src/com/intellij/openapi/util/ThrowableNotNullFunction.java new file mode 100644 index 000000000000..01918b8d115b --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/ThrowableNotNullFunction.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.util; + +import org.jetbrains.annotations.NotNull; + +public interface ThrowableNotNullFunction { + @NotNull + R fun(@NotNull T t) throws E; +} diff --git a/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java b/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java index a9a21547233d..f98646c30aab 100644 --- a/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java +++ b/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java @@ -15,13 +15,17 @@ */ package com.intellij.vcsUtil; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.ThrowableNotNullFunction; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,25 +45,54 @@ public class VcsFileUtil { public static final int FILE_PATH_LIMIT = 7600; /** - * Chunk paths on the command line + * Execute function for each chunk of arguments. Check for being cancelled in process. * - * @param files the paths to chunk - * @return the a list of list of relative paths + * @param arguments the arguments to chunk + * @param processor function to execute on each chunk + * @param type of result value + * @return list of result values + * @throws VcsException */ - public static List> chunkRelativePaths(List files) { + @NotNull + public static List foreachChunk(@NotNull List arguments, + @NotNull ThrowableNotNullFunction, List, VcsException> processor) + throws VcsException { + List result = ContainerUtil.newArrayList(); + List> chunks = chunkArguments(arguments); + + for (List chunk : chunks) { + if (ProgressManager.getInstance().getProgressIndicator() != null && + ProgressManager.getInstance().getProgressIndicator().isCanceled()) { + return result; + } + + result.addAll(processor.fun(chunk)); + } + + return result; + } + + /** + * Chunk arguments on the command line + * + * @param arguments the arguments to chunk + * @return a list of lists of arguments + */ + @NotNull + public static List> chunkArguments(@NotNull List arguments) { ArrayList> rc = new ArrayList>(); int start = 0; int size = 0; int i = 0; - for (; i < files.size(); i++) { - String p = files.get(i); + for (; i < arguments.size(); i++) { + String p = arguments.get(i); if (size + p.length() > FILE_PATH_LIMIT) { if (start == i) { - rc.add(files.subList(i, i + 1)); + rc.add(arguments.subList(i, i + 1)); start = i + 1; } else { - rc.add(files.subList(start, i)); + rc.add(arguments.subList(start, i)); start = i; } size = 0; @@ -68,8 +101,8 @@ public class VcsFileUtil { size += p.length(); } } - if (start != files.size()) { - rc.add(files.subList(start, i)); + if (start != arguments.size()) { + rc.add(arguments.subList(start, i)); } return rc; } @@ -82,7 +115,7 @@ public class VcsFileUtil { * @return chunked relative paths */ public static List> chunkPaths(VirtualFile root, Collection files) { - return chunkRelativePaths(toRelativePaths(root, files)); + return chunkArguments(toRelativePaths(root, files)); } /** @@ -93,7 +126,7 @@ public class VcsFileUtil { * @return chunked relative paths */ public static List> chunkFiles(@NotNull VirtualFile root, @NotNull Collection files) { - return chunkRelativePaths(toRelativeFiles(root, files)); + return chunkArguments(toRelativeFiles(root, files)); } public static String getRelativeFilePath(VirtualFile file, @NotNull final VirtualFile baseDir) { diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index ed5b9afeea23..a35f3add5162 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -18,6 +18,7 @@ package git4idea.log; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ThrowableNotNullFunction; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; @@ -333,34 +334,35 @@ public class GitLogProvider implements VcsLogProvider { @NotNull @Override - public List readShortDetails(@NotNull VirtualFile root, @NotNull List hashes) + public List readShortDetails(@NotNull final VirtualFile root, @NotNull List hashes) throws VcsException { - List result = ContainerUtil.newArrayList(); - List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); - - for (List hashesChunk : hashesChunks) { - result.addAll(GitHistoryUtils.readMiniDetails(myProject, root, hashesChunk)); - } - - return result; + return VcsFileUtil + .foreachChunk(hashes, new ThrowableNotNullFunction, List, VcsException>() { + @NotNull + @Override + public List fun(@NotNull List hashes) throws VcsException { + return GitHistoryUtils.readMiniDetails(myProject, root, hashes); + } + }); } @NotNull @Override - public List readFullDetails(@NotNull VirtualFile root, @NotNull List hashes) throws VcsException { - List result = ContainerUtil.newArrayList(); - List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); + public List readFullDetails(@NotNull final VirtualFile root, @NotNull List hashes) + throws VcsException { + return VcsFileUtil + .foreachChunk(hashes, new ThrowableNotNullFunction, List, VcsException>() { + @NotNull + @Override + public List fun(@NotNull List hashes) throws VcsException { + String noWalk = GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(myVcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk"; + List params = new ArrayList(); + params.add(noWalk); + params.addAll(hashes); - for (List hashesChunk : hashesChunks) { - String noWalk = GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(myVcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk"; - List params = new ArrayList(); - params.add(noWalk); - params.addAll(hashesChunk); - - result.addAll(GitHistoryUtils.history(myProject, root, ArrayUtil.toStringArray(params))); - } - - return result; + return GitHistoryUtils.history(myProject, root, ArrayUtil.toStringArray(params)); + } + }); } @NotNull diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitTypeCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitTypeCommand.java index 1ddad28a6c4c..ad5078e3492b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitTypeCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitTypeCommand.java @@ -90,7 +90,7 @@ public abstract class HgCommitTypeCommand { return file.getRelativePath(); } }); - List> chunkedCommits = VcsFileUtil.chunkRelativePaths(relativePaths); + List> chunkedCommits = VcsFileUtil.chunkArguments(relativePaths); executeChunked(chunkedCommits); } myRepository.update(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRemoveCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRemoveCommand.java index 9fffe1ba397a..9ccdbac32b0b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRemoveCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRemoveCommand.java @@ -48,7 +48,7 @@ public class HgRemoveCommand { public void execute(@NotNull Collection hgFiles) { for( Map.Entry> entry : HgUtil.getRelativePathsByRepository(hgFiles).entrySet()) { List filePaths = entry.getValue(); - for (List chunkFiles : VcsFileUtil.chunkRelativePaths(filePaths)) { + for (List chunkFiles : VcsFileUtil.chunkArguments(filePaths)) { List parameters = new LinkedList(); parameters.addAll(chunkFiles); parameters.add(0, "--after"); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java index e8b2084f1ae4..83770418c739 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java @@ -19,6 +19,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.openapi.util.ThrowableNotNullFunction; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FileStatus; @@ -112,24 +113,23 @@ public class HgHistoryUtil { */ @NotNull public static List history(@NotNull final Project project, - @NotNull final VirtualFile root, - int limit, - @NotNull List hashParameters, - boolean silent) throws VcsException { + @NotNull final VirtualFile root, final int limit, + @NotNull List hashParameters, final boolean silent) + throws VcsException { HgVcs hgvcs = HgVcs.getInstance(project); assert hgvcs != null; final HgVersion version = hgvcs.getVersion(); - String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); + final String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version); - List result = ContainerUtil.newArrayList(); - List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashParameters); - - for (List hashesChunk : hashesChunks) { - HgCommandResult logResult = getLogResult(project, root, version, limit, hashesChunk, HgChangesetUtil.makeTemplate(templates)); - result.addAll(createFullCommitsFromResult(project, root, logResult, version, silent)); - } - - return result; + return VcsFileUtil + .foreachChunk(hashParameters, new ThrowableNotNullFunction, List, VcsException>() { + @NotNull + @Override + public List fun(@NotNull List strings) throws VcsException { + HgCommandResult logResult = getLogResult(project, root, version, limit, strings, HgChangesetUtil.makeTemplate(templates)); + return createFullCommitsFromResult(project, root, logResult, version, silent); + } + }); } public static List createFullCommitsFromResult(@NotNull Project project, @@ -244,7 +244,7 @@ public class HgHistoryUtil { } @NotNull - public static List readMiniDetails(@NotNull Project project, + public static List readMiniDetails(@NotNull final Project project, @NotNull final VirtualFile root, @NotNull List hashes) throws VcsException { @@ -255,41 +255,41 @@ public class HgHistoryUtil { HgVcs hgvcs = HgVcs.getInstance(project); assert hgvcs != null; - HgVersion version = hgvcs.getVersion(); + final HgVersion version = hgvcs.getVersion(); List templateList = HgBaseLogParser.constructDefaultTemplate(version); templateList.add("{desc}"); - String[] templates = ArrayUtil.toStringArray(templateList); + final String[] templates = ArrayUtil.toStringArray(templateList); - List result = ContainerUtil.newArrayList(); - List> hashesChunks = VcsFileUtil.chunkRelativePaths(hashes); + return VcsFileUtil.foreachChunk(prepareHashes(hashes), + new ThrowableNotNullFunction, List, VcsException>() { + @NotNull + @Override + public List fun(@NotNull List strings) throws VcsException { + HgCommandResult logResult = + getLogResult(project, root, version, -1, strings, HgChangesetUtil.makeTemplate(templates)); - for (List hashesChunk : hashesChunks) { - HgCommandResult logResult = - getLogResult(project, root, version, -1, prepareHashes(hashesChunk), HgChangesetUtil.makeTemplate(templates)); - - result.addAll(getCommitRecords(project, logResult, new HgBaseLogParser() { - @Override - protected VcsShortCommitDetails convertDetails(@NotNull String rev, - @NotNull String changeset, - @NotNull SmartList parents, - @NotNull Date revisionDate, - @NotNull String author, - @NotNull String email, - @NotNull List attributes) { - String message = parseAdditionalStringAttribute(attributes, MESSAGE_INDEX); - String subject = extractSubject(message); - List parentsHash = new SmartList(); - for (HgRevisionNumber parent : parents) { - parentsHash.add(factory.createHash(parent.getChangeset())); - } - return factory - .createShortDetails(factory.createHash(changeset), parentsHash, revisionDate.getTime(), root, subject, author, email, author, - email, revisionDate.getTime()); - } - })); - } - - return result; + return getCommitRecords(project, logResult, new HgBaseLogParser() { + @Override + protected VcsShortCommitDetails convertDetails(@NotNull String rev, + @NotNull String changeset, + @NotNull SmartList parents, + @NotNull Date revisionDate, + @NotNull String author, + @NotNull String email, + @NotNull List attributes) { + String message = parseAdditionalStringAttribute(attributes, MESSAGE_INDEX); + String subject = extractSubject(message); + List parentsHash = new SmartList(); + for (HgRevisionNumber parent : parents) { + parentsHash.add(factory.createHash(parent.getChangeset())); + } + return factory + .createShortDetails(factory.createHash(changeset), parentsHash, revisionDate.getTime(), root, + subject, author, email, author, email, revisionDate.getTime()); + } + }); + } + }); } @NotNull From 947b4537d701bec3a94bbefee14a774302e314f5 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 17 Jun 2015 18:58:46 +0300 Subject: [PATCH 108/825] [vcs-log] load full details in background 1. log actions and cherry-pick load details in backgound task in action performed 2. deal with select all problem IDEA-118190 --- .../dvcs/cherrypick/VcsCherryPickAction.java | 123 ++++++----- .../com/intellij/dvcs/ui/VcsLogAction.java | 26 ++- .../src/com/intellij/vcsUtil/VcsFileUtil.java | 7 +- .../api/src/com/intellij/vcs/log/VcsLog.java | 13 ++ .../vcs/log/data/AbstractDataGetter.java | 203 +++++++++++++----- .../com/intellij/vcs/log/data/DataGetter.java | 10 + .../com/intellij/vcs/log/impl/VcsLogImpl.java | 15 +- .../vcs/log/ui/frame/DetailsPanel.java | 4 - .../intellij/vcs/log/ui/frame/MainFrame.java | 53 +++-- .../vcs/log/ui/tables/GraphTableModel.java | 16 +- .../vcs/log/data/VisiblePackBuilderTest.kt | 9 +- 11 files changed, 329 insertions(+), 150 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index bd648865da74..cc7ed702028c 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; @@ -32,9 +33,9 @@ import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerEx; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.hash.HashMap; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; @@ -57,39 +58,17 @@ public class VcsCherryPickAction extends DumbAwareAction { @Override public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); + final Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - final List commits = VcsLogUtil.collectLoadedSelectedDetails(log, false); - for (VcsFullCommitDetails commit : commits) { - myIdsInProgress.add(commit.getId()); - } - - FileDocumentManager.getInstance().saveAllDocuments(); - final ChangeListManagerEx changeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(project); - changeListManagerEx.blockModalNotifications(); - - new Task.Backgroundable(project, "Cherry-picking", false) { - public void run(@NotNull ProgressIndicator indicator) { - try { - List sortedCommits = sortCommits(commits); - Map> groupedCommits = groupByVcs(project, sortedCommits); - for (Map.Entry> entry : groupedCommits.entrySet()) { - entry.getKey().cherryPick(entry.getValue()); - } - } - finally { - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - changeListManagerEx.unblockModalNotifications(); - for (VcsFullCommitDetails commit : commits) { - myIdsInProgress.remove(commit.getId()); - } - } - }); - } + log.requestSelectedDetails(new Consumer>() { + @Override + public void consume(Set details) { + ProgressManager.getInstance().run(new CherryPickingTask(project, details)); } - }.queue(); + }, null); } /** @@ -101,27 +80,6 @@ public class VcsCherryPickAction extends DumbAwareAction { return commits; } - - private static Map> groupByVcs(@NotNull Project project, - @NotNull List commits) { - final ProjectLevelVcsManager projectLevelVcsManager = ProjectLevelVcsManager.getInstance(project); - Map> resultMap = new HashMap>(); - for (VcsFullCommitDetails commit : commits) { - VcsCherryPicker cherryPicker = getCherryPickerForCommit(project, projectLevelVcsManager, commit); - if (cherryPicker == null) { - VcsNotifier.getInstance(project).notifyWeakError( - "Cherry pick is not supported for commit " + commit.getId().toShortString() + " from root " + commit.getRoot().getName()); - return Collections.emptyMap(); - } - List list = resultMap.get(cherryPicker); - if (list == null) { - resultMap.put(cherryPicker, list = new ArrayList()); // ordered set!! - } - list.add(commit); - } - return resultMap; - } - @Nullable private static VcsCherryPicker getCherryPickerFor(@NotNull Project project, @NotNull final VcsKey key) { return ContainerUtil.find(Extensions.getExtensions(VcsCherryPicker.EXTENSION_POINT_NAME, project), new Condition() { @@ -191,4 +149,67 @@ public class VcsCherryPickAction extends DumbAwareAction { VcsKey key = vcs.getKeyInstanceMethod(); return getCherryPickerFor(project, key); } + + private class CherryPickingTask extends Task.Backgroundable { + private final Project myProject; + private final ProjectLevelVcsManager myProjectLevelVcsManager; + private final Map> myGroupedCommits = ContainerUtil.newHashMap(); + private final Collection myAllCommits; + private final ChangeListManagerEx myChangeListManagerEx; + + public CherryPickingTask(@NotNull Project project, @NotNull Set details) { + super(project, "Cherry-Picking"); + myProject = project; + myProjectLevelVcsManager = ProjectLevelVcsManager.getInstance(myProject); + myAllCommits = details; + myChangeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); + myChangeListManagerEx.blockModalNotifications(); + } + + public boolean processDetails(@NotNull VcsFullCommitDetails details) { + myIdsInProgress.add(details.getId()); + + VcsCherryPicker cherryPicker = getCherryPickerForCommit(myProject, myProjectLevelVcsManager, details); + if (cherryPicker == null) { + VcsNotifier.getInstance(myProject).notifyWeakError( + "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); + return false; + } + List list = myGroupedCommits.get(cherryPicker); + if (list == null) { + myGroupedCommits.put(cherryPicker, list = new ArrayList()); // ordered set!! + } + list.add(details); + return true; + } + + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + boolean isOk = true; + for (VcsFullCommitDetails details : myAllCommits) { + if (!processDetails(details)) { + isOk = false; + break; + } + } + + if (isOk) { + for (Map.Entry> entry : myGroupedCommits.entrySet()) { + entry.getKey().cherryPick(sortCommits(entry.getValue())); + } + } + } + finally { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + myChangeListManagerEx.unblockModalNotifications(); + for (VcsFullCommitDetails commit : myAllCommits) { + myIdsInProgress.remove(commit.getId()); + } + } + }); + } + } + } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 936eda2291a7..51adc76500ca 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.VcsFullCommitDetails; @@ -34,17 +35,24 @@ import com.intellij.vcs.log.impl.VcsLogUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; +import java.util.Collection; +import java.util.Set; public abstract class VcsLogAction extends DumbAwareAction { @Override public void actionPerformed(@NotNull AnActionEvent e) { - Project project = e.getRequiredData(CommonDataKeys.PROJECT); + final Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - MultiMap grouped = getGroupedCommits(project, log, false); - if (grouped == null) return; - actionPerformed(project, grouped); + + log.requestSelectedDetails(new Consumer>() { + @Override + public void consume(Set details) { + MultiMap grouped = groupCommits(project, details, false); + if (grouped == null) return; + actionPerformed(project, grouped); + } + }, null); } @Override @@ -88,7 +96,13 @@ public abstract class VcsLogAction extends DumbAwareAct @Nullable private MultiMap getGroupedCommits(@NotNull Project project, @NotNull VcsLog log, boolean fromUpdate) { - List commits = VcsLogUtil.collectLoadedSelectedDetails(log, fromUpdate); + return groupCommits(project, VcsLogUtil.collectLoadedSelectedDetails(log, fromUpdate), fromUpdate); + } + + @Nullable + private MultiMap groupCommits(@NotNull Project project, + Collection commits, + boolean fromUpdate) { MultiMap map = MultiMap.create(); for (VcsFullCommitDetails commit : commits) { Repo root = getRepositoryForRoot(project, commit.getRoot()); diff --git a/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java b/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java index f98646c30aab..9c8161ab40ca 100644 --- a/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java +++ b/platform/vcs-impl/src/com/intellij/vcsUtil/VcsFileUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.vcsUtil; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; @@ -61,10 +62,8 @@ public class VcsFileUtil { List> chunks = chunkArguments(arguments); for (List chunk : chunks) { - if (ProgressManager.getInstance().getProgressIndicator() != null && - ProgressManager.getInstance().getProgressIndicator().isCanceled()) { - return result; - } + ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) indicator.checkCanceled(); result.addAll(processor.fun(chunk)); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index 297c8d6c9ca4..2813efbf647d 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -15,12 +15,15 @@ */ package com.intellij.vcs.log; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.concurrent.Future; /** @@ -41,6 +44,16 @@ public interface VcsLog { @NotNull List getSelectedDetails(); + /** + * Sends a request to load details that are currently selected. + * Details are loaded in background. If a progress indicator is specified it is used during loading process. + * After all details are loaded they are provided to the consumer in the EDT. + * + * @param consumer called in EDT after all details are loaded. + * @param indicator progress indicator to use in loading process, can be null. + */ + void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator); + /** * Returns names of branches which contain the given commit, or null if this information is unavailable. */ diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java index 874fec2aba06..2e7c59c23441 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java @@ -1,10 +1,16 @@ package com.intellij.vcs.log.data; import com.intellij.openapi.Disposable; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.PerformInBackgroundOption; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.ContainerUtil; @@ -20,23 +26,22 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -import java.util.ArrayList; -import java.util.Collection; +import java.util.*; import java.util.List; -import java.util.Map; /** * The DataGetter realizes the following pattern of getting some data (parametrized by {@code T}) from the VCS: *

      - *
    • it tries to get it from the cache;
    • - *
    • if it fails, it tries to get it from the VCS, and additionally loads several commits around the requested one, - * to avoid querying the VCS if user investigates details of nearby commits.
    • - *
    • The loading happens asynchronously: a fake {@link LoadingDetails} object is returned
    • + *
    • it tries to get it from the cache;
    • + *
    • if it fails, it tries to get it from the VCS, and additionally loads several commits around the requested one, + * to avoid querying the VCS if user investigates details of nearby commits.
    • + *
    • The loading happens asynchronously: a fake {@link LoadingDetails} object is returned
    • *
    * * @author Kirill Likhodedov */ abstract class AbstractDataGetter implements Disposable, DataGetter { + private static final Logger LOG = Logger.getInstance(AbstractDataGetter.class); private static final int UP_PRELOAD_COUNT = 20; private static final int DOWN_PRELOAD_COUNT = 40; @@ -62,19 +67,23 @@ abstract class AbstractDataGetter implements Di myLogProviders = logProviders; myCache = cache; Disposer.register(parentDisposable, this); - myLoader = new SequentialLimitedLifoExecutor(this, MAX_LOADING_TASKS, - new ThrowableConsumer() { + myLoader = + new SequentialLimitedLifoExecutor(this, MAX_LOADING_TASKS, new ThrowableConsumer() { + @Override + public void consume(final TaskDescriptor task) throws VcsException { + preLoadCommitData(task.myCommits); + notifyLoaded(); + } + }); + } + + private void notifyLoaded() { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override - public void consume(TaskDescriptor task) throws VcsException { - preLoadCommitData(task.myCommits); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { - @Override - public void run() { - for (Runnable loadingFinishedListener : myLoadingFinishedListeners) { - loadingFinishedListener.run(); - } - } - }); + public void run() { + for (Runnable loadingFinishedListener : myLoadingFinishedListeners) { + loadingFinishedListener.run(); + } } }); } @@ -85,7 +94,7 @@ abstract class AbstractDataGetter implements Di } @Override - @Nullable + @NotNull public T getCommitData(int row, @NotNull GraphTableModel tableModel) { assert EventQueue.isDispatchThread(); Integer hash = tableModel.getIdAtRow(row); @@ -93,8 +102,104 @@ abstract class AbstractDataGetter implements Di if (details != null) { return details; } - runLoadAroundCommitData(row, tableModel); - return myCache.get(hash); // now it is in the cache as "Loading Details". + + runLoadCommitsData(tableModel, createRowsIterable(row, UP_PRELOAD_COUNT, DOWN_PRELOAD_COUNT, tableModel.getRowCount())); + + T result = myCache.get(hash); + assert result != null; // now it is in the cache as "Loading Details" (runLoadCommitsData puts it there) + return result; + } + + private static Iterable createRowsIterable(final int row, final int above, final int below, final int maxRows) { + return new Iterable() { + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + private int myIndex = Math.max(0, row - above); + + @Override + public boolean hasNext() { + return myIndex < row + below && myIndex < maxRows; + } + + @Override + public Integer next() { + int next = myIndex; + myIndex++; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Removing elements is not supported."); + } + }; + } + }; + } + + @Override + public void loadCommitsData(@NotNull List rows, + @NotNull GraphTableModel tableModel, + @NotNull Consumer> consumer, + @Nullable ProgressIndicator indicator) { + assert EventQueue.isDispatchThread(); + loadCommitsData(getCommitsForRows(rows, tableModel), consumer, indicator); + } + + private void loadCommitsData(@NotNull final MultiMap commits, + @NotNull final Consumer> consumer, + @Nullable ProgressIndicator indicator) { + final Set result = ContainerUtil.newHashSet(); + final MultiMap toLoad = MultiMap.create(); + + long taskNumber = myCurrentTaskIndex++; + + for (VirtualFile root : commits.keySet()) { + Collection hashesForRoot = commits.get(root); + for (final Integer commitId : hashesForRoot) { + T details = getFromCache(commitId); + if (details == null || details instanceof LoadingDetails) { + toLoad.putValue(root, commitId); + cacheCommit(commitId, root, taskNumber); + } + else { + result.add(details); + } + } + } + + if (toLoad.isEmpty()) { + consumer.consume(result); + } + else { + Task.Backgroundable task = + new Task.Backgroundable(null, "Loading Selected Details", true, PerformInBackgroundOption.ALWAYS_BACKGROUND) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + indicator.checkCanceled(); + try { + result.addAll(preLoadCommitData(toLoad)); + notifyLoaded(); + } + catch (VcsException e) { + LOG.error(e); + } + } + + @Override + public void onSuccess() { + consumer.consume(result); + } + }; + if (indicator != null) { + ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, indicator); + } + else { + ProgressManager.getInstance().run(task); + } + } } @Override @@ -125,47 +230,48 @@ abstract class AbstractDataGetter implements Di @Nullable protected abstract T getFromAdditionalCache(int commitId); - private void runLoadAroundCommitData(int row, @NotNull GraphTableModel tableModel) { + private void runLoadCommitsData(@NotNull GraphTableModel tableModel, @NotNull Iterable rows) { long taskNumber = myCurrentTaskIndex++; - MultiMap commits = getCommitsAround(row, tableModel, UP_PRELOAD_COUNT, DOWN_PRELOAD_COUNT); + MultiMap commits = getCommitsForRows(rows, tableModel); for (Map.Entry> hashesByRoots : commits.entrySet()) { VirtualFile root = hashesByRoots.getKey(); Collection hashes = hashesByRoots.getValue(); - // fill the cache with temporary "Loading" values to avoid producing queries for each commit that has not been cached yet, - // even if it will be loaded within a previous query for (final int commitId : hashes) { - if (!myCache.isKeyCached(commitId)) { - myCache.put(commitId, (T)new LoadingDetails(new Computable(){ - - @Override - public Hash compute() { - return myHashMap.getCommitId(commitId).getHash(); - } - }, taskNumber, root)); - } + cacheCommit(commitId, root, taskNumber); } } - TaskDescriptor task = new TaskDescriptor(commits); - myLoader.queue(task); + myLoader.queue(new TaskDescriptor(commits)); + } + + private void cacheCommit(final int commitId, VirtualFile root, long taskNumber) { + // fill the cache with temporary "Loading" values to avoid producing queries for each commit that has not been cached yet, + // even if it will be loaded within a previous query + if (!myCache.isKeyCached(commitId)) { + myCache.put(commitId, (T)new LoadingDetails(new Computable() { + + @Override + public Hash compute() { + return myHashMap.getCommitId(commitId).getHash(); + } + }, taskNumber, root)); + } } @NotNull - private static MultiMap getCommitsAround(int selectedRow, - @NotNull GraphTableModel model, - int above, - int below) { + private static MultiMap getCommitsForRows(@NotNull Iterable rows, @NotNull GraphTableModel model) { MultiMap commits = MultiMap.create(); - for (int row = Math.max(0, selectedRow - above); row < selectedRow + below && row < model.getRowCount(); row++) { - Integer hash = model.getIdAtRow(row); + for (int row : rows) { + Integer commitId = model.getIdAtRow(row); VirtualFile root = model.getRoot(row); - commits.putValue(root, hash); + commits.putValue(root, commitId); } return commits; } - private void preLoadCommitData(@NotNull MultiMap commits) throws VcsException { + private Set preLoadCommitData(@NotNull MultiMap commits) throws VcsException { + Set result = ContainerUtil.newHashSet(); for (Map.Entry> entry : commits.entrySet()) { List hashStrings = ContainerUtil.map(entry.getValue(), new Function() { @Override @@ -174,8 +280,10 @@ abstract class AbstractDataGetter implements Di } }); List details = readDetails(myLogProviders.get(entry.getKey()), entry.getKey(), hashStrings); + result.addAll(details); saveInCache(details); } + return result; } public void saveInCache(final List details) { @@ -202,11 +310,10 @@ abstract class AbstractDataGetter implements Di } private static class TaskDescriptor { - private final MultiMap myCommits; + @NotNull private final MultiMap myCommits; - private TaskDescriptor(MultiMap commits) { + private TaskDescriptor(@NotNull MultiMap commits) { myCommits = commits; } } - } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java index 4da4b90a5ed7..1e4b485c102c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java @@ -15,15 +15,25 @@ */ package com.intellij.vcs.log.data; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.util.Consumer; import com.intellij.vcs.log.VcsShortCommitDetails; import com.intellij.vcs.log.ui.tables.GraphTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; +import java.util.Set; + public interface DataGetter { @Nullable T getCommitData(int row, @NotNull GraphTableModel tableModel); + void loadCommitsData(@NotNull List rows, + @NotNull GraphTableModel tableModel, + @NotNull Consumer> consumer, + @Nullable ProgressIndicator indicator); + @Nullable T getCommitDataIfAvailable(int hash); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index d62eb930726c..a3be80855d75 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -15,7 +15,11 @@ */ package com.intellij.vcs.log.impl; +import com.google.common.primitives.Ints; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Condition; +import com.intellij.ui.table.JBTable; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.VcsLogDataHolder; @@ -25,9 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collection; +import java.util.*; import java.util.List; import java.util.concurrent.Future; @@ -35,6 +37,7 @@ import java.util.concurrent.Future; * */ public class VcsLogImpl implements VcsLog { + private static final int SLICE_SIZE = 50; @NotNull private final VcsLogDataHolder myDataHolder; @NotNull private final VcsLogUiImpl myUi; @@ -79,6 +82,12 @@ public class VcsLogImpl implements VcsLog { }; } + @Override + public void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator) { + List rowsList = Ints.asList(myUi.getTable().getSelectedRows()); + myDataHolder.getCommitDetailsGetter().loadCommitsData(rowsList, (GraphTableModel)myUi.getTable().getModel(), consumer, indicator); + } + @Nullable @Override public Collection getContainingBranches(@NotNull Hash commitHash) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java index 7a2784a3ddf6..392a4be00560 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java @@ -168,10 +168,6 @@ class DetailsPanel extends JPanel implements ListSelectionListener { int row = rows[0]; GraphTableModel tableModel = (GraphTableModel)myGraphTable.getModel(); VcsFullCommitDetails commitData = myLogDataHolder.getCommitDetailsGetter().getCommitData(row, tableModel); - if (commitData == null) { - showMessage("No commits selected"); - return; - } if (commitData instanceof LoadingDetails) { myLoadingPanel.startLoading(); myCommitDetailsPanel.setData(null); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 66b2fd0bee33..de2c00977bd5 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -4,6 +4,8 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.actions.RefreshAction; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.progress.EmptyProgressIndicator; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; @@ -12,6 +14,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.TextRevisionNumber; +import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser; import com.intellij.openapi.vcs.changes.committed.RepositoryChangesBrowser; import com.intellij.openapi.vcs.changes.ui.ChangesBrowser; import com.intellij.openapi.vcs.history.VcsRevisionNumber; @@ -19,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLoadingPanel; import com.intellij.util.ArrayUtil; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -44,6 +48,7 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.util.*; import java.util.List; +import java.util.Set; import static com.intellij.util.ObjectUtils.assertNotNull; import static com.intellij.util.containers.ContainerUtil.getFirstItem; @@ -154,7 +159,6 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { myLogDataHolder.getCommitDetailsGetter().addDetailsLoadedListener(new Runnable() { @Override public void run() { - selectionChangeListener.valueChanged(null); myDetailsPanel.valueChanged(null); } }); @@ -291,11 +295,6 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { myBranchesPanel.setVisible(visible); } - @Nullable - public List getSelectedChanges() { - return myGraphTable.getSelectedChanges(); - } - @Override public void calcData(DataKey key, DataSink sink) { if (VcsLogDataKeys.VCS_LOG == key) { @@ -308,7 +307,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { sink.put(key, myLogDataHolder); } else if (VcsDataKeys.CHANGES == key || VcsDataKeys.SELECTED_CHANGES == key) { - List selectedChanges = getSelectedChanges(); + List selectedChanges = myGraphTable.getSelectedChanges(); if (selectedChanges != null) { sink.put(key, ArrayUtil.toObjectArray(selectedChanges, Change.class)); } @@ -363,6 +362,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { private class CommitSelectionListener implements ListSelectionListener { private final ChangesBrowser myChangesBrowser; + private ProgressIndicator myLastRequest; public CommitSelectionListener(ChangesBrowser changesBrowser) { myChangesBrowser = changesBrowser; @@ -371,23 +371,38 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { @Override public void valueChanged(@Nullable ListSelectionEvent event) { if (event != null && event.getValueIsAdjusting()) return; + + if (myLastRequest != null) myLastRequest.cancel(); + myLastRequest = null; + int rows = getGraphTable().getSelectedRowCount(); - if (rows < 1 || rows > MAX_SELECTED_COMMITS) { + if (rows < 1) { myChangesLoadingPane.stopLoading(); - myChangesBrowser.getViewer().setEmptyText(rows < 1 ? "" : "Too many commits selected."); + myChangesBrowser.getViewer().setEmptyText(""); myChangesBrowser.setChangesToDisplay(Collections.emptyList()); } else { - List selectedChanges = getSelectedChanges(); - if (selectedChanges != null) { - myChangesLoadingPane.stopLoading(); - myChangesBrowser.setChangesToDisplay(selectedChanges); - } - else { - myChangesBrowser.setChangesToDisplay(Collections.emptyList()); - setDefaultEmptyText(myChangesBrowser); - myChangesLoadingPane.startLoading(); - } + myChangesBrowser.setChangesToDisplay(Collections.emptyList()); + setDefaultEmptyText(myChangesBrowser); + myChangesLoadingPane.startLoading(); + + final EmptyProgressIndicator indicator = new EmptyProgressIndicator(); + myLastRequest = indicator; + myLog.requestSelectedDetails(new Consumer>() { + @Override + public void consume(Set detailsList) { + if (myLastRequest == indicator && !(indicator.isCanceled())) { + myLastRequest = null; + List changes = ContainerUtil.newArrayList(); + for (VcsFullCommitDetails details : detailsList) { + changes.addAll(details.getChanges()); + } + changes = CommittedChangesTreeBrowser.zipChanges(changes); + myChangesLoadingPane.stopLoading(); + myChangesBrowser.setChangesToDisplay(changes); + } + } + }, indicator); } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 4c88002ae2fa..f8a958ff7e99 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -152,16 +152,6 @@ public class GraphTableModel extends AbstractTableModel { return COLUMN_COUNT; } - @Nullable - private VcsShortCommitDetails getShortDetails(int rowIndex) { - return myLogDataHolder.getMiniDetailsGetter().getCommitData(rowIndex, this); - } - - @Nullable - public VcsFullCommitDetails getFullCommitDetails(int rowIndex) { - return myLogDataHolder.getCommitDetailsGetter().getCommitData(rowIndex, this); - } - /** * Requests the proper data provider to load more data from the log & recreate the model. * @@ -180,7 +170,7 @@ public class GraphTableModel extends AbstractTableModel { requestToLoadMore(EmptyRunnable.INSTANCE); } - VcsShortCommitDetails data = getShortDetails(rowIndex); + VcsShortCommitDetails data = myLogDataHolder.getMiniDetailsGetter().getCommitData(rowIndex, this); switch (columnIndex) { case ROOT_COLUMN: return getRoot(rowIndex); @@ -225,8 +215,8 @@ public class GraphTableModel extends AbstractTableModel { public List getSelectedChanges(@NotNull List selectedRows) { List changes = new ArrayList(); for (int row : selectedRows) { - VcsFullCommitDetails commitData = getFullCommitDetails(row); - if (commitData == null || commitData instanceof LoadingDetails) { + VcsFullCommitDetails commitData = myLogDataHolder.getCommitDetailsGetter().getCommitData(row, this); + if (commitData instanceof LoadingDetails) { return null; } changes.addAll(commitData.getChanges()); diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt index 592fca3eb5a9..cae52f9b911f 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt @@ -16,8 +16,10 @@ package com.intellij.vcs.log.data import com.intellij.mock.MockVirtualFile +import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.util.Condition import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.Consumer import com.intellij.util.Function import com.intellij.vcs.log.* import com.intellij.vcs.log.graph.GraphCommit @@ -149,11 +151,14 @@ class VisiblePackBuilderTest { val commitDetailsGetter = object : DataGetter { override fun getCommitData(row: Int, tableModel: GraphTableModel): VcsFullCommitDetails? { - return null; + return null + } + + override fun loadCommitsData(rows: MutableList, tableModel: GraphTableModel, consumer: Consumer>, indicator: ProgressIndicator?) { } override fun getCommitDataIfAvailable(hash: Int): VcsFullCommitDetails? { - return null; + return null } } val builder = VisiblePackBuilder(providers, hashMap, detailsCache, commitDetailsGetter) From 5b1d958fb14404979a4d079845a8a0e3aa87b417 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 17 Jun 2015 21:17:06 +0300 Subject: [PATCH 109/825] [vcs-log] limit copied subjects in log --- .../src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index 44d8f41bb8d5..b98a81344177 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -43,6 +43,7 @@ import com.intellij.vcs.log.data.VisiblePack; import com.intellij.vcs.log.graph.*; import com.intellij.vcs.log.graph.actions.GraphAction; import com.intellij.vcs.log.graph.actions.GraphAnswer; +import com.intellij.vcs.log.impl.VcsLogUtil; import com.intellij.vcs.log.printer.idea.GraphCellPainter; import com.intellij.vcs.log.printer.idea.PositionUtil; import com.intellij.vcs.log.printer.idea.SimpleGraphCellPainter; @@ -288,7 +289,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C @Override public void performCopy(@NotNull DataContext dataContext) { - List details = myUI.getVcsLog().getSelectedDetails(); + List details = VcsLogUtil.collectLoadedSelectedDetails(myUI.getVcsLog(), true); if (!details.isEmpty()) { CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(details, new Function() { @Override From 1dc28ad858936975c1b027340636a5a778274543 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Fri, 19 Jun 2015 15:42:43 +0300 Subject: [PATCH 110/825] [vcs-log] limit number of commits that data provider processes --- .../intellij/vcs/log/ui/frame/MainFrame.java | 31 +++++++++++++------ .../vcs/log/ui/frame/VcsLogGraphTable.java | 16 +++++----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index de2c00977bd5..6af5656ec921 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -25,7 +25,6 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.table.ComponentsListFocusTraversalPolicy; import com.intellij.vcs.CommittedChangeListForRevision; import com.intellij.vcs.log.*; @@ -48,15 +47,13 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.util.*; import java.util.List; -import java.util.Set; import static com.intellij.util.ObjectUtils.assertNotNull; import static com.intellij.util.containers.ContainerUtil.getFirstItem; -import static com.intellij.vcs.log.impl.VcsLogUtil.groupByRoot; public class MainFrame extends JPanel implements TypeSafeDataProvider { - public static final int MAX_SELECTED_COMMITS = 100; + public static final int MAX_SELECTED_COMMITS = 1000; @NotNull private final VcsLogDataHolder myLogDataHolder; @NotNull private final VcsLogUiImpl myUI; @NotNull private final Project myProject; @@ -307,15 +304,16 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { sink.put(key, myLogDataHolder); } else if (VcsDataKeys.CHANGES == key || VcsDataKeys.SELECTED_CHANGES == key) { - List selectedChanges = myGraphTable.getSelectedChanges(); + List selectedChanges = myGraphTable.getSelectedChanges(MAX_SELECTED_COMMITS); if (selectedChanges != null) { sink.put(key, ArrayUtil.toObjectArray(selectedChanges, Change.class)); } } else if (VcsDataKeys.CHANGE_LISTS == key) { List details = myUI.getVcsLog().getSelectedDetails(); - sink.put(key, ContainerUtil.map2Array(details, CommittedChangeListForRevision.class, - new Function() { + if (details.size() > MAX_SELECTED_COMMITS) return; + sink.put(key, ContainerUtil + .map2Array(details, CommittedChangeListForRevision.class, new Function() { @Override public CommittedChangeListForRevision fun(@NotNull VcsFullCommitDetails details) { return new CommittedChangeListForRevision(details.getSubject(), details.getFullMessage(), details.getCommitter().getName(), @@ -326,6 +324,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } else if (VcsDataKeys.VCS_REVISION_NUMBERS == key) { List hashes = myUI.getVcsLog().getSelectedCommits(); + if (hashes.size() > MAX_SELECTED_COMMITS) return; sink.put(key, ArrayUtil.toObjectArray(ContainerUtil.map(hashes, new Function() { @Override public VcsRevisionNumber fun(CommitId commitId) { @@ -334,8 +333,22 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { }), VcsRevisionNumber.class)); } else if (VcsDataKeys.VCS == key) { - MultiMap commitsByRoots = groupByRoot(myUI.getVcsLog().getSelectedDetails()); - Set roots = commitsByRoots.keySet(); + List commits = myUI.getVcsLog().getSelectedCommits(); + Collection logProviders = myUI.getVcsLog().getLogProviders(); + if (logProviders.size() == 1) { + if (!commits.isEmpty()) { + sink.put(key, myLogDataHolder.getLogProvider(assertNotNull(getFirstItem(commits)).getRoot()).getSupportedVcs()); + } + return; + } + if (commits.size() > MAX_SELECTED_COMMITS) return; + + Set roots = ContainerUtil.map2Set(commits, new Function() { + @Override + public VirtualFile fun(CommitId commitId) { + return commitId.getRoot(); + } + }); if (roots.size() == 1) { sink.put(key, myLogDataHolder.getLogProvider(assertNotNull(getFirstItem(roots))).getSupportedVcs()); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index b98a81344177..c886b680948b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -261,23 +261,23 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C } @Nullable - public List getSelectedChanges() { + public List getSelectedChanges(int maxChanges) { TableModel model = getModel(); if (!(model instanceof GraphTableModel)) { return null; } - List changes = ((GraphTableModel)model).getSelectedChanges(sortSelectedRows()); - return changes == null ? null : CommittedChangesTreeBrowser.zipChanges(changes); - } - @NotNull - private List sortSelectedRows() { + int[] selectedRows = getSelectedRows(); + if (selectedRows.length > maxChanges) return null; + List rows = ContainerUtil.newArrayList(); - for (int row : getSelectedRows()) { + for (int row : selectedRows) { rows.add(row); } Collections.sort(rows, Collections.reverseOrder()); - return rows; + + List changes = ((GraphTableModel)model).getSelectedChanges(rows); + return changes == null ? null : CommittedChangesTreeBrowser.zipChanges(changes); } @Override From 97ee62a61944aaa8e03e0a04f3442d4b863f655e Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Fri, 19 Jun 2015 16:08:02 +0300 Subject: [PATCH 111/825] [vcs-log] always limit details --- .../dvcs/cherrypick/VcsCherryPickAction.java | 2 +- .../src/com/intellij/dvcs/ui/VcsLogAction.java | 16 +++++----------- .../com/intellij/vcs/log/impl/VcsLogUtil.java | 6 +++--- .../vcs/log/ui/frame/VcsLogGraphTable.java | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index cc7ed702028c..ecafcddc3c49 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -102,7 +102,7 @@ public class VcsCherryPickAction extends DumbAwareAction { return; } - final List details = VcsLogUtil.collectLoadedSelectedDetails(log, true); + final List details = VcsLogUtil.collectFirstPackOfLoadedSelectedDetails(log); VcsCherryPicker enabledCherryPicker = ContainerUtil.find(cherryPickers, new Condition() { @Override public boolean value(VcsCherryPicker picker) { diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 51adc76500ca..1f398e330578 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -48,7 +48,7 @@ public abstract class VcsLogAction extends DumbAwareAct log.requestSelectedDetails(new Consumer>() { @Override public void consume(Set details) { - MultiMap grouped = groupCommits(project, details, false); + MultiMap grouped = groupCommits(project, details); if (grouped == null) return; actionPerformed(project, grouped); } @@ -64,7 +64,7 @@ public abstract class VcsLogAction extends DumbAwareAct return; } - MultiMap grouped = getGroupedCommits(project, log, true); + MultiMap grouped = getGroupedCommits(project, log); if (grouped == null) { e.getPresentation().setEnabledAndVisible(false); } @@ -95,22 +95,16 @@ public abstract class VcsLogAction extends DumbAwareAct protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root); @Nullable - private MultiMap getGroupedCommits(@NotNull Project project, @NotNull VcsLog log, boolean fromUpdate) { - return groupCommits(project, VcsLogUtil.collectLoadedSelectedDetails(log, fromUpdate), fromUpdate); + private MultiMap getGroupedCommits(@NotNull Project project, @NotNull VcsLog log) { + return groupCommits(project, VcsLogUtil.collectFirstPackOfLoadedSelectedDetails(log)); } @Nullable - private MultiMap groupCommits(@NotNull Project project, - Collection commits, - boolean fromUpdate) { + private MultiMap groupCommits(@NotNull Project project, Collection commits) { MultiMap map = MultiMap.create(); for (VcsFullCommitDetails commit : commits) { Repo root = getRepositoryForRoot(project, commit.getRoot()); if (root == null) { // commit from some other VCS - if (!fromUpdate) { - VcsNotifier.getInstance(project).notifyWeakError( - "Can not perform action on commit " + commit.getId().toShortString() + " from root " + commit.getRoot().getName()); - } return null; } map.putValue(root, commit); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java index 90c95916c75e..7210122ac0f2 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java @@ -171,8 +171,8 @@ public class VcsLogUtil { } // If this method stumbles on LoadingDetails instance it returns empty list - // Also, can be slow when many details are selected - public static List collectLoadedSelectedDetails(@NotNull VcsLog log, boolean limitDetails) { + @NotNull + public static List collectFirstPackOfLoadedSelectedDetails(@NotNull VcsLog log) { List result = ContainerUtil.newArrayList(); for (VcsFullCommitDetails next : log.getSelectedDetails()) { @@ -181,7 +181,7 @@ public class VcsLogUtil { } else { result.add(next); - if (result.size() >= DETAILS_LIMIT && limitDetails) break; + if (result.size() >= DETAILS_LIMIT) break; } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index c886b680948b..08159c597ec9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -289,7 +289,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C @Override public void performCopy(@NotNull DataContext dataContext) { - List details = VcsLogUtil.collectLoadedSelectedDetails(myUI.getVcsLog(), true); + List details = VcsLogUtil.collectFirstPackOfLoadedSelectedDetails(myUI.getVcsLog()); if (!details.isEmpty()) { CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(details, new Function() { @Override From 83b1d98acf9dece8c6b1f08bda99c3b77eeaf1e6 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Sep 2015 21:17:00 +0300 Subject: [PATCH 112/825] [vcs-log] remove usages of VcsLog.getSelectedDetails from actions --- .../com/intellij/dvcs/ui/VcsLogAction.java | 59 ++++++++++++++----- .../dvcs/ui/VcsLogOneCommitPerRepoAction.java | 9 +-- .../dvcs/ui/VcsLogSingleCommitAction.java | 39 ++++++------ .../com/intellij/vcs/log/impl/VcsLogUtil.java | 7 ++- .../actions/GitCheckoutRevisionAction.java | 6 +- .../actions/GitCreateNewBranchAction.java | 10 ++-- .../git4idea/actions/GitCreateTagAction.java | 6 +- .../GitLogBranchOperationsActionGroup.java | 17 +++--- ...ithubShowCommitInBrowserFromLogAction.java | 19 +++--- .../HgCreateNewBranchFromLogAction.java | 11 ++-- .../action/HgCreateTagFromLogAction.java | 6 +- .../action/HgMergeWithRevisionFromLog.java | 7 ++- .../action/HgUpdateToFromLogAction.java | 6 +- .../action/mq/HgMqAppliedPatchAction.java | 8 +-- .../action/mq/HgQFinishFromLogAction.java | 6 +- .../action/mq/HgQGotoFromLogAction.java | 32 +++++++++- .../action/mq/HgQImportFromLogAction.java | 8 +-- .../action/mq/HgQRenameFromLogAction.java | 6 +- 18 files changed, 160 insertions(+), 102 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 1f398e330578..0dbaede776ad 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -23,19 +23,18 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; -import com.intellij.vcs.log.VcsFullCommitDetails; -import com.intellij.vcs.log.VcsLog; -import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.*; import com.intellij.vcs.log.impl.VcsLogUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.Map; import java.util.Set; public abstract class VcsLogAction extends DumbAwareAction { @@ -48,7 +47,13 @@ public abstract class VcsLogAction extends DumbAwareAct log.requestSelectedDetails(new Consumer>() { @Override public void consume(Set details) { - MultiMap grouped = groupCommits(project, details); + MultiMap grouped = groupCommits(project, details, new Function() { + @Override + public VirtualFile fun(VcsFullCommitDetails vcsFullCommitDetails) { + return vcsFullCommitDetails.getRoot(); + } + }); + if (grouped == null) return; actionPerformed(project, grouped); } @@ -64,7 +69,7 @@ public abstract class VcsLogAction extends DumbAwareAct return; } - MultiMap grouped = getGroupedCommits(project, log); + MultiMap grouped = groupFirstPackOfCommits(project, log); if (grouped == null) { e.getPresentation().setEnabledAndVisible(false); } @@ -76,9 +81,9 @@ public abstract class VcsLogAction extends DumbAwareAct protected abstract void actionPerformed(@NotNull Project project, @NotNull MultiMap grouped); - protected abstract boolean isEnabled(@NotNull MultiMap grouped); + protected abstract boolean isEnabled(@NotNull MultiMap grouped); - protected boolean isVisible(@NotNull final Project project, @NotNull MultiMap grouped) { + protected boolean isVisible(@NotNull final Project project, @NotNull MultiMap grouped) { return ContainerUtil.and(grouped.keySet(), new Condition() { @Override public boolean value(Repo repo) { @@ -94,16 +99,42 @@ public abstract class VcsLogAction extends DumbAwareAct @Nullable protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root); + /** + * Collects no more than VcsLogUtil.MAX_SELECTED_COMMITS and groups them by repository. + * To use only during update. + */ @Nullable - private MultiMap getGroupedCommits(@NotNull Project project, @NotNull VcsLog log) { - return groupCommits(project, VcsLogUtil.collectFirstPackOfLoadedSelectedDetails(log)); + private MultiMap groupFirstPackOfCommits(@NotNull Project project, @NotNull VcsLog log) { + MultiMap commitIds = + groupCommits(project, VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.DETAILS_LIMIT), + new Function() { + @Override + public VirtualFile fun(CommitId hash) { + return hash.getRoot(); + } + }); + if (commitIds == null) return null; + + MultiMap hashes = MultiMap.create(); + for (Map.Entry> entry: commitIds.entrySet()) { + hashes.putValues(entry.getKey(), ContainerUtil.map(entry.getValue(), new Function() { + @Override + public Hash fun(CommitId commitId) { + return commitId.getHash(); + } + })); + } + + return hashes; } @Nullable - private MultiMap groupCommits(@NotNull Project project, Collection commits) { - MultiMap map = MultiMap.create(); - for (VcsFullCommitDetails commit : commits) { - Repo root = getRepositoryForRoot(project, commit.getRoot()); + private MultiMap groupCommits(@NotNull Project project, + @NotNull Collection commits, + @NotNull Function rootGetter) { + MultiMap map = MultiMap.create(); + for (T commit : commits) { + Repo root = getRepositoryForRoot(project, rootGetter.fun(commit)); if (root == null) { // commit from some other VCS return null; } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java index 1b4be918a3e1..e0211797423d 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,16 +38,16 @@ public abstract class VcsLogOneCommitPerRepoAction exte } @Override - protected boolean isEnabled(@NotNull MultiMap grouped) { + protected boolean isEnabled(@NotNull MultiMap grouped) { return allValuesAreSingletons(grouped); } protected abstract void actionPerformed(@NotNull Project project, @NotNull Map commits); - private boolean allValuesAreSingletons(@NotNull MultiMap grouped) { - return !ContainerUtil.exists(grouped.entrySet(), new Condition>>() { + private boolean allValuesAreSingletons(@NotNull MultiMap grouped) { + return !ContainerUtil.exists(grouped.entrySet(), new Condition>>() { @Override - public boolean value(Map.Entry> entry) { + public boolean value(Map.Entry> entry) { return entry.getValue().size() != 1; } }); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java index 5c11a232d003..4134595da4ca 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java @@ -23,7 +23,8 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.CommitId; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogDataKeys; import com.intellij.vcs.log.data.LoadingDetails; @@ -39,12 +40,12 @@ public abstract class VcsLogSingleCommitAction extends Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - VcsFullCommitDetails details = ContainerUtil.getFirstItem(log.getSelectedDetails()); - assert details != null; - Repo repository = getRepositoryForRoot(project, details.getRoot()); + CommitId commit = ContainerUtil.getFirstItem(log.getSelectedCommits()); + assert commit != null; + Repo repository = getRepositoryForRoot(project, commit.getRoot()); assert repository != null; - actionPerformed(repository, details); + actionPerformed(repository, commit.getHash()); } @Override @@ -56,36 +57,32 @@ public abstract class VcsLogSingleCommitAction extends return; } - List selectedDetails = log.getSelectedDetails(); - if (selectedDetails.isEmpty()) { + List commits = log.getSelectedCommits(); + if (commits.isEmpty()) { e.getPresentation().setEnabledAndVisible(false); } else { - VcsFullCommitDetails details = ContainerUtil.getFirstItem(selectedDetails); - if (details == null || details instanceof LoadingDetails) { + CommitId commit = ContainerUtil.getFirstItem(commits); + assert commit != null; + Repo repository = getRepositoryForRoot(project, commit.getRoot()); + + if (repository == null) { e.getPresentation().setEnabledAndVisible(false); } else { - Repo repository = getRepositoryForRoot(project, details.getRoot()); - - if (repository == null) { - e.getPresentation().setEnabledAndVisible(false); - } - else { - e.getPresentation().setVisible(isVisible(project, repository, details)); - e.getPresentation().setEnabled(selectedDetails.size() == 1 && isEnabled(repository, details)); - } + e.getPresentation().setVisible(isVisible(project, repository, commit.getHash())); + e.getPresentation().setEnabled(commits.size() == 1 && isEnabled(repository, commit.getHash())); } } } - protected abstract void actionPerformed(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit); + protected abstract void actionPerformed(@NotNull Repo repository, @NotNull Hash commit); - protected boolean isEnabled(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit) { + protected boolean isEnabled(@NotNull Repo repository, @NotNull Hash commit) { return true; } - protected boolean isVisible(@NotNull final Project project, @NotNull Repo repository, @NotNull VcsFullCommitDetails commit) { + protected boolean isVisible(@NotNull final Project project, @NotNull Repo repository, @NotNull Hash hash) { return !getRepositoryManager(project).isExternal(repository); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java index 7210122ac0f2..cac6f46641be 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsLogUtil { - private static final int DETAILS_LIMIT = 100; + public static final int DETAILS_LIMIT = 100; @NotNull public static MultiMap groupRefsByRoot(@NotNull Collection refs) { @@ -188,6 +188,11 @@ public class VcsLogUtil { return result; } + @NotNull + public static List collectFirstPack(@NotNull List list, int max) { + return list.subList(0, Math.min(list.size(), max)); + } + @NotNull public static Collection getVisibleBranches(@NotNull VcsLog log, VcsLogUiImpl logUi) { VcsLogFilterCollection filters = logUi.getFilterUi().getFilters(); diff --git a/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java index b7ca9e963b01..2d9156f8f164 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java @@ -16,7 +16,7 @@ package git4idea.actions; import com.intellij.openapi.components.ServiceManager; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import git4idea.branch.GitBrancher; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; @@ -26,9 +26,9 @@ import java.util.Collections; public class GitCheckoutRevisionAction extends GitLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { + protected void actionPerformed(@NotNull GitRepository repository, @NotNull Hash commit) { GitBrancher brancher = ServiceManager.getService(repository.getProject(), GitBrancher.class); - brancher.checkout(commit.getId().asString(), false, Collections.singletonList(repository), null); + brancher.checkout(commit.asString(), false, Collections.singletonList(repository), null); } } diff --git a/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java index c23593908bee..96a6d509a0c4 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCreateNewBranchAction.java @@ -17,7 +17,7 @@ package git4idea.actions; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import git4idea.branch.GitBranchUtil; import git4idea.branch.GitBrancher; import git4idea.repo.GitRepository; @@ -28,11 +28,11 @@ import java.util.Collections; public class GitCreateNewBranchAction extends GitLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { + protected void actionPerformed(@NotNull GitRepository repository, @NotNull Hash commit) { Project project = repository.getProject(); - String reference = commit.getId().asString(); - final String name = GitBranchUtil.getNewBranchNameFromUser(project, Collections.singleton(repository), - "Checkout New Branch From " + reference); + String reference = commit.asString(); + final String name = + GitBranchUtil.getNewBranchNameFromUser(project, Collections.singleton(repository), "Checkout New Branch From " + reference); if (name != null) { GitBrancher brancher = ServiceManager.getService(project, GitBrancher.class); brancher.checkoutNewBranchStartingFrom(name, reference, Collections.singletonList(repository), null); diff --git a/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java b/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java index c346bca9a408..dded4fa5dc27 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCreateTagAction.java @@ -15,7 +15,7 @@ */ package git4idea.actions; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import git4idea.history.wholeTree.GitCreateNewTag; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; @@ -23,8 +23,8 @@ import org.jetbrains.annotations.NotNull; public class GitCreateTagAction extends GitLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { - String reference = commit.getId().asString(); + protected void actionPerformed(@NotNull GitRepository repository, @NotNull Hash commit) { + String reference = commit.asString(); new GitCreateNewTag(repository.getProject(), repository, reference, null).execute(); } diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitLogBranchOperationsActionGroup.java b/plugins/git4idea/src/git4idea/ui/branch/GitLogBranchOperationsActionGroup.java index 7d5cf05fe2e5..148f14f98d02 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitLogBranchOperationsActionGroup.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitLogBranchOperationsActionGroup.java @@ -59,19 +59,16 @@ public class GitLogBranchOperationsActionGroup extends ActionGroup implements Du return AnAction.EMPTY_ARRAY; } - List details = log.getSelectedDetails(); // this is temporary - if (details.size() != 1) return AnAction.EMPTY_ARRAY; + List commits = log.getSelectedCommits(); + if (commits.size() != 1) return AnAction.EMPTY_ARRAY; - VcsFullCommitDetails detail = details.get(0); + CommitId commit = commits.get(0); + GitRepositoryManager repositoryManager = ServiceManager.getService(project, GitRepositoryManager.class); + final GitRepository root = repositoryManager.getRepositoryForRoot(commit.getRoot()); + if (root == null) return AnAction.EMPTY_ARRAY; VcsLogDataPack dataPack = logUI.getDataPack(); - Collection allVcsRefs = ((RefsModel)dataPack.getRefs()).refsToCommit(detail.getId(), detail.getRoot()); - if (allVcsRefs.isEmpty()) return AnAction.EMPTY_ARRAY; - - VirtualFile rootFile = detail.getRoot(); - GitRepositoryManager repositoryManager = ServiceManager.getService(project, GitRepositoryManager.class); - final GitRepository root = repositoryManager.getRepositoryForRoot(rootFile); - if (root == null) return AnAction.EMPTY_ARRAY; + Collection allVcsRefs = ((RefsModel)dataPack.getRefs()).refsToCommit(commit.getHash(), commit.getRoot()); List vcsRefs = ContainerUtil.filter(allVcsRefs, new Condition() { @Override diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java index baaaaed26de7..95e5eaa13f2d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserFromLogAction.java @@ -19,7 +19,8 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.Project; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.CommitId; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogDataKeys; import com.intellij.vcs.log.data.LoadingDetails; @@ -40,27 +41,27 @@ public class GithubShowCommitInBrowserFromLogAction extends GithubShowCommitInBr e.getPresentation().setEnabledAndVisible(false); return; } - List selectedDetails = log.getSelectedDetails(); - if (selectedDetails.size() != 1) { + List selectedCommits = log.getSelectedCommits(); + if (selectedCommits.size() != 1) { e.getPresentation().setEnabledAndVisible(false); return; } - VcsFullCommitDetails details = ContainerUtil.getFirstItem(selectedDetails); - if (details == null || details instanceof LoadingDetails) { + CommitId commit = ContainerUtil.getFirstItem(selectedCommits); + if (commit == null) { e.getPresentation().setEnabledAndVisible(false); return; } - GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(details.getRoot()); + GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(commit.getRoot()); e.getPresentation().setEnabledAndVisible(repository != null && GithubUtil.isRepositoryOnGitHub(repository)); } @Override public void actionPerformed(@NotNull AnActionEvent e) { Project project = e.getRequiredData(CommonDataKeys.PROJECT); - VcsFullCommitDetails commit = ContainerUtil.getFirstItem(e.getRequiredData(VcsLogDataKeys.VCS_LOG).getSelectedDetails()); - assert commit != null && !(commit instanceof LoadingDetails); + CommitId commit = ContainerUtil.getFirstItem(e.getRequiredData(VcsLogDataKeys.VCS_LOG).getSelectedCommits()); + assert commit != null; GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(commit.getRoot()); - openInBrowser(project, repository, commit.getId().asString()); + openInBrowser(project, repository, commit.getHash().asString()); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateNewBranchFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateNewBranchFromLogAction.java index 24f4b4fe86d7..4e3a7d827796 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateNewBranchFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateNewBranchFromLogAction.java @@ -20,7 +20,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgVcsMessages; import org.zmlx.hg4idea.branch.HgBranchPopupActions; @@ -33,19 +32,17 @@ import static org.zmlx.hg4idea.util.HgUtil.getNewBranchNameFromUser; public class HgCreateNewBranchFromLogAction extends HgLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull final HgRepository repository, @NotNull VcsFullCommitDetails commit) { - final Hash revisionHash = commit.getId(); + protected void actionPerformed(@NotNull final HgRepository repository, @NotNull final Hash commit) { final Project project = repository.getProject(); FileDocumentManager.getInstance().saveAllDocuments(); - String shortHash = revisionHash.toShortString(); + String shortHash = commit.toShortString(); final String name = getNewBranchNameFromUser(repository, "Create New Branch From " + shortHash); if (name != null) { new Task.Backgroundable(project, HgVcsMessages.message("hg4idea.progress.updatingTo", shortHash)) { @Override public void run(@NotNull ProgressIndicator indicator) { - if (HgUpdateCommand.updateRepoToInCurrentThread(project, repository.getRoot(), revisionHash.asString(), false)) { - new HgBranchPopupActions.HgNewBranchAction(project, Collections.singletonList(repository), repository) - .createNewBranch(name); + if (HgUpdateCommand.updateRepoToInCurrentThread(project, repository.getRoot(), commit.asString(), false)) { + new HgBranchPopupActions.HgNewBranchAction(project, Collections.singletonList(repository), repository).createNewBranch(name); } } }.queue(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java index be1f8b5dd88e..ae06e7bffb1f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java @@ -15,7 +15,7 @@ */ package org.zmlx.hg4idea.action; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.repo.HgRepository; @@ -23,8 +23,8 @@ import java.util.Collections; public class HgCreateTagFromLogAction extends HgLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { - String revisionHash = commit.getId().asString(); + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { + String revisionHash = commit.asString(); new HgCreateTagAction().execute(repository.getProject(), Collections.singleton(repository), repository, revisionHash); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMergeWithRevisionFromLog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMergeWithRevisionFromLog.java index 925a126cd1e6..3bec04442a10 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMergeWithRevisionFromLog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMergeWithRevisionFromLog.java @@ -17,15 +17,16 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.command.HgMergeCommand; import org.zmlx.hg4idea.repo.HgRepository; public class HgMergeWithRevisionFromLog extends HgLogSingleCommitAction { + @Override - protected void actionPerformed(@NotNull final HgRepository repository, @NotNull VcsFullCommitDetails commit) { + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { FileDocumentManager.getInstance().saveAllDocuments(); - HgMergeCommand.mergeWith(repository, commit.getId().asString(), UpdatedFiles.create()); + HgMergeCommand.mergeWith(repository, commit.asString(), UpdatedFiles.create()); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java index aebc5a0b790c..28a9fd4acfbd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java @@ -19,18 +19,16 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.command.HgUpdateCommand; import org.zmlx.hg4idea.repo.HgRepository; public class HgUpdateToFromLogAction extends HgLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull final HgRepository repository, @NotNull VcsFullCommitDetails commit) { - final Hash revisionHash = commit.getId(); + protected void actionPerformed(@NotNull final HgRepository repository, @NotNull Hash commit) { final Project project = repository.getProject(); final VirtualFile root = repository.getRoot(); FileDocumentManager.getInstance().saveAllDocuments(); - HgUpdateCommand.updateRepoTo(project, root, revisionHash.asString(), null); + HgUpdateCommand.updateRepoTo(project, root, commit.asString(), null); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java index 4195eb83f7f7..cc3f413901b7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgMqAppliedPatchAction.java @@ -17,7 +17,7 @@ package org.zmlx.hg4idea.action.mq; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgNameWithHashInfo; import org.zmlx.hg4idea.action.HgLogSingleCommitAction; @@ -26,15 +26,15 @@ import org.zmlx.hg4idea.repo.HgRepository; public abstract class HgMqAppliedPatchAction extends HgLogSingleCommitAction { @Override - protected boolean isEnabled(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { + protected boolean isEnabled(@NotNull HgRepository repository, @NotNull Hash commit) { return super.isEnabled(repository, commit) && isAppliedPatch(repository, commit); } - public static boolean isAppliedPatch(@NotNull HgRepository repository, @NotNull final VcsFullCommitDetails commitDetails) { + public static boolean isAppliedPatch(@NotNull HgRepository repository, @NotNull final Hash hash) { return ContainerUtil.exists(repository.getMQAppliedPatches(), new Condition() { @Override public boolean value(HgNameWithHashInfo info) { - return info.getHash().equals(commitDetails.getId()); + return info.getHash().equals(hash); } }); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQFinishFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQFinishFromLogAction.java index 2bf4dd6f613e..fcb3e5bfb650 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQFinishFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQFinishFromLogAction.java @@ -15,15 +15,15 @@ */ package org.zmlx.hg4idea.action.mq; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.command.mq.HgQFinishCommand; import org.zmlx.hg4idea.repo.HgRepository; public class HgQFinishFromLogAction extends HgMqAppliedPatchAction { @Override - protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { - String revisionHash = commit.getId().asString(); + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { + String revisionHash = commit.asString(); new HgQFinishCommand(repository).execute(revisionHash); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java index 8baea933d1aa..d3169bcc2d09 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java @@ -15,13 +15,18 @@ */ package org.zmlx.hg4idea.action.mq; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgNameWithHashInfo; import org.zmlx.hg4idea.HgVcsMessages; @@ -29,10 +34,11 @@ import org.zmlx.hg4idea.command.mq.HgQGotoCommand; import org.zmlx.hg4idea.command.mq.HgQPopCommand; import org.zmlx.hg4idea.repo.HgRepository; +import java.util.Set; import java.util.List; public class HgQGotoFromLogAction extends HgMqAppliedPatchAction { - @Override + protected void actionPerformed(@NotNull final HgRepository repository, @NotNull final VcsFullCommitDetails commit) { final Project project = repository.getProject(); List parents = commit.getParents(); @@ -64,4 +70,28 @@ public class HgQGotoFromLogAction extends HgMqAppliedPatchAction { } }.queue(); } + + @Override + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { + throw new UnsupportedOperationException(); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + final Project project = e.getRequiredData(CommonDataKeys.PROJECT); + VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); + + log.requestSelectedDetails(new Consumer>() { + @Override + public void consume(Set selectedDetails) { + VcsFullCommitDetails fullCommitDetails = ContainerUtil.getFirstItem(selectedDetails); + + assert fullCommitDetails != null; + final HgRepository repository = getRepositoryForRoot(project, fullCommitDetails.getRoot()); + assert repository != null; + + actionPerformed(repository, fullCommitDetails); + } + }, null); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java index 24e247337d0d..d2321c99a2d3 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQImportFromLogAction.java @@ -15,7 +15,7 @@ */ package org.zmlx.hg4idea.action.mq; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.action.HgLogSingleCommitAction; import org.zmlx.hg4idea.command.mq.HgQImportCommand; @@ -23,13 +23,13 @@ import org.zmlx.hg4idea.repo.HgRepository; public class HgQImportFromLogAction extends HgLogSingleCommitAction { @Override - protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { - String revisionHash = commit.getId().asString(); + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { + String revisionHash = commit.asString(); new HgQImportCommand(repository).execute(revisionHash); } @Override - protected boolean isEnabled(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { + protected boolean isEnabled(@NotNull HgRepository repository, @NotNull Hash commit) { return super.isEnabled(repository, commit) && !HgMqAppliedPatchAction.isAppliedPatch(repository, commit); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQRenameFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQRenameFromLogAction.java index 373af3ca1649..c33a377e7bf7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQRenameFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQRenameFromLogAction.java @@ -15,14 +15,14 @@ */ package org.zmlx.hg4idea.action.mq; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.Hash; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.command.mq.HgQRenameCommand; import org.zmlx.hg4idea.repo.HgRepository; public class HgQRenameFromLogAction extends HgMqAppliedPatchAction { @Override - protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) { - new HgQRenameCommand(repository).execute(commit.getId()); + protected void actionPerformed(@NotNull HgRepository repository, @NotNull Hash commit) { + new HgQRenameCommand(repository).execute(commit); } } From b89b934fe7ffe1493c76801b29db97d1f4d81e80 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Sep 2015 22:17:49 +0300 Subject: [PATCH 113/825] [vcs-log] get rid of VcsLogUtil.collectFirstPackOfLoadedSelectedDetails() call from cherry pick action --- .../dvcs/cherrypick/VcsCherryPicker.java | 8 ++++-- .../dvcs/cherrypick/VcsCherryPickAction.java | 25 ++++++++++++++----- .../com/intellij/dvcs/ui/VcsLogAction.java | 2 +- .../com/intellij/vcs/log/impl/VcsLogUtil.java | 4 +-- .../git4idea/cherrypick/GitCherryPicker.java | 23 ++++++++++------- .../hg4idea/cherrypick/HgCherryPicker.java | 11 +++++--- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/platform/dvcs-api/src/com/intellij/dvcs/cherrypick/VcsCherryPicker.java b/platform/dvcs-api/src/com/intellij/dvcs/cherrypick/VcsCherryPicker.java index 97291ed90ce3..a3c2d57f6a07 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/cherrypick/VcsCherryPicker.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/cherrypick/VcsCherryPicker.java @@ -17,12 +17,16 @@ package com.intellij.dvcs.cherrypick; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Map; public abstract class VcsCherryPicker { @@ -52,8 +56,8 @@ public abstract class VcsCherryPicker { * Return true if all selected commits can be cherry-picked by this cherry-picker * * @param log additional log information - * @param details commits to cherry-pick + * @param commits commits to cherry-pick, grouped by version control root * @return */ - public abstract boolean isEnabled(@NotNull VcsLog log, @NotNull List details); + public abstract boolean isEnabled(@NotNull VcsLog log, @NotNull Map> commits); } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index ecafcddc3c49..164bba42359c 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -33,13 +33,11 @@ import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.VcsNotifier; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerEx; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; -import com.intellij.vcs.log.VcsLog; -import com.intellij.vcs.log.VcsLogDataKeys; +import com.intellij.vcs.log.*; import com.intellij.vcs.log.impl.VcsLogUtil; import icons.DvcsImplIcons; import org.jetbrains.annotations.NotNull; @@ -102,12 +100,13 @@ public class VcsCherryPickAction extends DumbAwareAction { return; } - final List details = VcsLogUtil.collectFirstPackOfLoadedSelectedDetails(log); + List details = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.COMMITS_LIMIT); + final Map> groupedByRoot = groupByRoot(details); VcsCherryPicker enabledCherryPicker = ContainerUtil.find(cherryPickers, new Condition() { @Override public boolean value(VcsCherryPicker picker) { //all commits should be from one vcs, if not then all pickers should return false - return picker.isEnabled(log, details); + return picker.isEnabled(log, groupedByRoot); } }); e.getPresentation().setEnabled(enabledCherryPicker != null); @@ -115,6 +114,20 @@ public class VcsCherryPickAction extends DumbAwareAction { enabledCherryPicker == null ? concatActionNamesForAllAvailable(cherryPickers) : enabledCherryPicker.getActionTitle()); } + @NotNull + private static Map> groupByRoot(@NotNull List details) { + Map> result = ContainerUtil.newHashMap(); + for (CommitId commit: details) { + List hashes = result.get(commit.getRoot()); + if (hashes == null) { + hashes = ContainerUtil.newArrayList(); + result.put(commit.getRoot(), hashes); + } + hashes.add(commit.getHash()); + } + return result; + } + @NotNull private static String concatActionNamesForAllAvailable(@NotNull final List pickers) { return StringUtil.join(pickers, new Function() { diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 0dbaede776ad..7e825650716a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -106,7 +106,7 @@ public abstract class VcsLogAction extends DumbAwareAct @Nullable private MultiMap groupFirstPackOfCommits(@NotNull Project project, @NotNull VcsLog log) { MultiMap commitIds = - groupCommits(project, VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.DETAILS_LIMIT), + groupCommits(project, VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.COMMITS_LIMIT), new Function() { @Override public VirtualFile fun(CommitId hash) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java index cac6f46641be..cf9c2990b068 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsLogUtil { - public static final int DETAILS_LIMIT = 100; + public static final int COMMITS_LIMIT = 100; @NotNull public static MultiMap groupRefsByRoot(@NotNull Collection refs) { @@ -181,7 +181,7 @@ public class VcsLogUtil { } else { result.add(next); - if (result.size() >= DETAILS_LIMIT) break; + if (result.size() >= COMMITS_LIMIT) break; } } diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPicker.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPicker.java index 594735134dec..42efbe99bfc6 100644 --- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPicker.java +++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPicker.java @@ -36,6 +36,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; import git4idea.GitLocalBranch; @@ -546,20 +548,23 @@ public class GitCherryPicker extends VcsCherryPicker { } @Override - public boolean isEnabled(@NotNull VcsLog log, @NotNull List details) { - if (details.isEmpty()) { + public boolean isEnabled(@NotNull VcsLog log, @NotNull Map> commits) { + if (commits.isEmpty()) { return false; } - for (VcsFullCommitDetails commit : details) { - GitRepository repository = myPlatformFacade.getRepositoryManager(myProject).getRepositoryForRoot(commit.getRoot()); + + for (VirtualFile root : commits.keySet()) { + GitRepository repository = myPlatformFacade.getRepositoryManager(myProject).getRepositoryForRoot(root); if (repository == null) { return false; } - GitLocalBranch currentBranch = repository.getCurrentBranch(); - Collection containingBranches = log.getContainingBranches(commit.getId()); - if (currentBranch != null && containingBranches != null && containingBranches.contains(currentBranch.getName())) { - // already is contained in the current branch - return false; + for (Hash commit : commits.get(root)) { + GitLocalBranch currentBranch = repository.getCurrentBranch(); + Collection containingBranches = log.getContainingBranches(commit); + if (currentBranch != null && containingBranches != null && containingBranches.contains(currentBranch.getName())) { + // already is contained in the current branch + return false; + } } } return true; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/cherrypick/HgCherryPicker.java b/plugins/hg4idea/src/org/zmlx/hg4idea/cherrypick/HgCherryPicker.java index 4085928aa82b..74e0fa81620e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/cherrypick/HgCherryPicker.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/cherrypick/HgCherryPicker.java @@ -23,6 +23,8 @@ import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; import org.jetbrains.annotations.NotNull; @@ -103,17 +105,18 @@ public class HgCherryPicker extends VcsCherryPicker { } @Override - public boolean isEnabled(@NotNull VcsLog log, @NotNull List details) { - if (details.isEmpty()) { + public boolean isEnabled(@NotNull VcsLog log, @NotNull Map> commits) { + if (commits.isEmpty()) { return false; } - for (VcsFullCommitDetails commit : details) { - HgRepository repository = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(commit.getRoot()); + for (VirtualFile root: commits.keySet()) { + HgRepository repository = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(root); if (repository == null) { return false; } } + return true; } } From 106a1d8ac6460318be8d63d916a32973ffcbb44d Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 30 Sep 2015 14:37:00 +0300 Subject: [PATCH 114/825] [vcs-log] main frame gets VcsDataKeys.CHANGES or VcsDataKeys.SELECTED_CHANGES from changes view; hence remove some unused methods from table and model --- .../intellij/vcs/log/ui/frame/MainFrame.java | 5 +--- .../vcs/log/ui/frame/VcsLogGraphTable.java | 20 --------------- .../vcs/log/ui/tables/GraphTableModel.java | 25 +++---------------- 3 files changed, 4 insertions(+), 46 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 6af5656ec921..efe7afb35df7 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -304,10 +304,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { sink.put(key, myLogDataHolder); } else if (VcsDataKeys.CHANGES == key || VcsDataKeys.SELECTED_CHANGES == key) { - List selectedChanges = myGraphTable.getSelectedChanges(MAX_SELECTED_COMMITS); - if (selectedChanges != null) { - sink.put(key, ArrayUtil.toObjectArray(selectedChanges, Change.class)); - } + sink.put(key, ArrayUtil.toObjectArray(myChangesBrowser.getCurrentDisplayedChanges(), Change.class)); } else if (VcsDataKeys.CHANGE_LISTS == key) { List details = myUI.getVcsLog().getSelectedDetails(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index 08159c597ec9..5e6856506dae 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -260,26 +260,6 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C } } - @Nullable - public List getSelectedChanges(int maxChanges) { - TableModel model = getModel(); - if (!(model instanceof GraphTableModel)) { - return null; - } - - int[] selectedRows = getSelectedRows(); - if (selectedRows.length > maxChanges) return null; - - List rows = ContainerUtil.newArrayList(); - for (int row : selectedRows) { - rows.add(row); - } - Collections.sort(rows, Collections.reverseOrder()); - - List changes = ((GraphTableModel)model).getSelectedChanges(rows); - return changes == null ? null : CommittedChangesTreeBrowser.zipChanges(changes); - } - @Override public void calcData(DataKey key, DataSink sink) { if (PlatformDataKeys.COPY_PROVIDER == key) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index f8a958ff7e99..58c397bac4eb 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -5,14 +5,15 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.CommitIdByStringCondition; -import com.intellij.vcs.log.data.LoadingDetails; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsRef; +import com.intellij.vcs.log.VcsShortCommitDetails; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VisiblePack; import com.intellij.vcs.log.graph.GraphCommit; @@ -204,26 +205,6 @@ public class GraphTableModel extends AbstractTableModel { return !myMoreRequested && myDataPack.canRequestMore(); } - /** - * Returns Changes for commits at selected rows.
    - * Rows are given in the order as they appear in the table, i. e. in reverse chronological order.
    - * Changes can be returned as-is, i.e. with duplicate changes for a single file. - * - * @return Changes selected in all rows, or null if this data is not ready yet. - */ - @Nullable - public List getSelectedChanges(@NotNull List selectedRows) { - List changes = new ArrayList(); - for (int row : selectedRows) { - VcsFullCommitDetails commitData = myLogDataHolder.getCommitDetailsGetter().getCommitData(row, this); - if (commitData instanceof LoadingDetails) { - return null; - } - changes.addAll(commitData.getChanges()); - } - return changes; - } - @Override public Class getColumnClass(int column) { switch (column) { From 4332ef2ee96e5e65a4a043c2cb3258fc2780cb45 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 01:09:47 +0300 Subject: [PATCH 115/825] [vcs-log] remove else clauses, use return instead --- .../dvcs/ui/VcsLogSingleCommitAction.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java index 4134595da4ca..aa40ad2ed3b7 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java @@ -27,7 +27,6 @@ import com.intellij.vcs.log.CommitId; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLog; import com.intellij.vcs.log.VcsLogDataKeys; -import com.intellij.vcs.log.data.LoadingDetails; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,20 +59,20 @@ public abstract class VcsLogSingleCommitAction extends List commits = log.getSelectedCommits(); if (commits.isEmpty()) { e.getPresentation().setEnabledAndVisible(false); + return; } - else { - CommitId commit = ContainerUtil.getFirstItem(commits); - assert commit != null; - Repo repository = getRepositoryForRoot(project, commit.getRoot()); - if (repository == null) { - e.getPresentation().setEnabledAndVisible(false); - } - else { - e.getPresentation().setVisible(isVisible(project, repository, commit.getHash())); - e.getPresentation().setEnabled(commits.size() == 1 && isEnabled(repository, commit.getHash())); - } + CommitId commit = ContainerUtil.getFirstItem(commits); + assert commit != null; + Repo repository = getRepositoryForRoot(project, commit.getRoot()); + + if (repository == null) { + e.getPresentation().setEnabledAndVisible(false); + return; } + + e.getPresentation().setVisible(isVisible(project, repository, commit.getHash())); + e.getPresentation().setEnabled(commits.size() == 1 && isEnabled(repository, commit.getHash())); } protected abstract void actionPerformed(@NotNull Repo repository, @NotNull Hash commit); From 09f371f91262976bc0fe9f716435e9458e2da8d5 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 02:17:13 +0300 Subject: [PATCH 116/825] [vcs-log] also log message when commit can not be cherry-picked --- .../com/intellij/dvcs/cherrypick/VcsCherryPickAction.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index 164bba42359c..16ce3e708594 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -18,6 +18,7 @@ package com.intellij.dvcs.cherrypick; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; @@ -46,6 +47,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsCherryPickAction extends DumbAwareAction { + private static final Logger LOG = Logger.getInstance(VcsCherryPickAction.class); private static final String NAME = "Cherry-Pick"; @NotNull private final Set myIdsInProgress; @@ -184,8 +186,10 @@ public class VcsCherryPickAction extends DumbAwareAction { VcsCherryPicker cherryPicker = getCherryPickerForCommit(myProject, myProjectLevelVcsManager, details); if (cherryPicker == null) { - VcsNotifier.getInstance(myProject).notifyWeakError( - "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); + String message = + "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName(); + VcsNotifier.getInstance(myProject).notifyWeakError(message); + LOG.warn(message); return false; } List list = myGroupedCommits.get(cherryPicker); From 3d2ffc9d058072d65b4d40b211230b8b3b46c1da Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 03:28:30 +0300 Subject: [PATCH 117/825] [vcs-log] merge MAX_SELECTED_COMMITS and COMMITS_LIMIT and increase the latter to 1000 --- .../com/intellij/dvcs/cherrypick/VcsCherryPickAction.java | 2 +- .../dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java | 2 +- .../impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java | 4 ++-- .../impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index 16ce3e708594..efff67a5486b 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -102,7 +102,7 @@ public class VcsCherryPickAction extends DumbAwareAction { return; } - List details = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.COMMITS_LIMIT); + List details = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.MAX_SELECTED_COMMITS); final Map> groupedByRoot = groupByRoot(details); VcsCherryPicker enabledCherryPicker = ContainerUtil.find(cherryPickers, new Condition() { @Override diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 7e825650716a..34ab175599cb 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -106,7 +106,7 @@ public abstract class VcsLogAction extends DumbAwareAct @Nullable private MultiMap groupFirstPackOfCommits(@NotNull Project project, @NotNull VcsLog log) { MultiMap commitIds = - groupCommits(project, VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.COMMITS_LIMIT), + groupCommits(project, VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.MAX_SELECTED_COMMITS), new Function() { @Override public VirtualFile fun(CommitId hash) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java index cf9c2990b068..becbcedaa84b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogUtil.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsLogUtil { - public static final int COMMITS_LIMIT = 100; + public static final int MAX_SELECTED_COMMITS = 1000; @NotNull public static MultiMap groupRefsByRoot(@NotNull Collection refs) { @@ -181,7 +181,7 @@ public class VcsLogUtil { } else { result.add(next); - if (result.size() >= COMMITS_LIMIT) break; + if (result.size() >= VcsLogUtil.MAX_SELECTED_COMMITS) break; } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index efe7afb35df7..5f5207a4f01b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -33,6 +33,7 @@ import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.data.VisiblePack; import com.intellij.vcs.log.graph.PermanentGraph; import com.intellij.vcs.log.graph.impl.facade.bek.BekSorter; +import com.intellij.vcs.log.impl.VcsLogUtil; import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.actions.IntelliSortChooserPopupAction; import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi; @@ -53,7 +54,6 @@ import static com.intellij.util.containers.ContainerUtil.getFirstItem; public class MainFrame extends JPanel implements TypeSafeDataProvider { - public static final int MAX_SELECTED_COMMITS = 1000; @NotNull private final VcsLogDataHolder myLogDataHolder; @NotNull private final VcsLogUiImpl myUI; @NotNull private final Project myProject; @@ -308,7 +308,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } else if (VcsDataKeys.CHANGE_LISTS == key) { List details = myUI.getVcsLog().getSelectedDetails(); - if (details.size() > MAX_SELECTED_COMMITS) return; + if (details.size() > VcsLogUtil.MAX_SELECTED_COMMITS) return; sink.put(key, ContainerUtil .map2Array(details, CommittedChangeListForRevision.class, new Function() { @Override @@ -321,7 +321,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } else if (VcsDataKeys.VCS_REVISION_NUMBERS == key) { List hashes = myUI.getVcsLog().getSelectedCommits(); - if (hashes.size() > MAX_SELECTED_COMMITS) return; + if (hashes.size() > VcsLogUtil.MAX_SELECTED_COMMITS) return; sink.put(key, ArrayUtil.toObjectArray(ContainerUtil.map(hashes, new Function() { @Override public VcsRevisionNumber fun(CommitId commitId) { @@ -338,7 +338,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } return; } - if (commits.size() > MAX_SELECTED_COMMITS) return; + if (commits.size() > VcsLogUtil.MAX_SELECTED_COMMITS) return; Set roots = ContainerUtil.map2Set(commits, new Function() { @Override From 7d369ab5a65d2c5c6e0414ccabfa3fbcd69b24c1 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 20:13:35 +0300 Subject: [PATCH 118/825] [vcs-log] introduce VcsCherryPickManager; move CherryPickingTask there and required methods --- platform/dvcs-impl/src/META-INF/dvcs.xml | 1 + .../dvcs/cherrypick/VcsCherryPickAction.java | 117 +------------ .../dvcs/cherrypick/VcsCherryPickManager.java | 154 ++++++++++++++++++ 3 files changed, 158 insertions(+), 114 deletions(-) create mode 100644 platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java diff --git a/platform/dvcs-impl/src/META-INF/dvcs.xml b/platform/dvcs-impl/src/META-INF/dvcs.xml index c045e58a9e3a..6a6de37de05a 100644 --- a/platform/dvcs-impl/src/META-INF/dvcs.xml +++ b/platform/dvcs-impl/src/META-INF/dvcs.xml @@ -38,6 +38,7 @@ + diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index efff67a5486b..5523461a1afd 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -17,25 +17,14 @@ package com.intellij.dvcs.cherrypick; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsKey; -import com.intellij.openapi.vcs.VcsNotifier; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vcs.changes.ChangeListManagerEx; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; @@ -47,47 +36,20 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class VcsCherryPickAction extends DumbAwareAction { - private static final Logger LOG = Logger.getInstance(VcsCherryPickAction.class); private static final String NAME = "Cherry-Pick"; - @NotNull private final Set myIdsInProgress; public VcsCherryPickAction() { super(NAME, null, DvcsImplIcons.CherryPick); - myIdsInProgress = ContainerUtil.newHashSet(); } @Override public void actionPerformed(AnActionEvent e) { FileDocumentManager.getInstance().saveAllDocuments(); - final Project project = e.getRequiredData(CommonDataKeys.PROJECT); + Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - log.requestSelectedDetails(new Consumer>() { - @Override - public void consume(Set details) { - ProgressManager.getInstance().run(new CherryPickingTask(project, details)); - } - }, null); - } - - /** - * Sort commits so that earliest ones come first: they need to be cherry-picked first. - */ - @NotNull - public static List sortCommits(@NotNull List commits) { - Collections.reverse(commits); - return commits; - } - - @Nullable - private static VcsCherryPicker getCherryPickerFor(@NotNull Project project, @NotNull final VcsKey key) { - return ContainerUtil.find(Extensions.getExtensions(VcsCherryPicker.EXTENSION_POINT_NAME, project), new Condition() { - @Override - public boolean value(VcsCherryPicker picker) { - return picker.getSupportedVcs().equals(key); - } - }); + VcsCherryPickManager.getInstance(project).cherryPick(log); } @Override @@ -148,85 +110,12 @@ public class VcsCherryPickAction extends DumbAwareAction { return ContainerUtil.mapNotNull(vcss, new Function() { @Override public VcsCherryPicker fun(AbstractVcs vcs) { - return vcs != null ? getCherryPickerFor(project, vcs.getKeyInstanceMethod()) : null; + return vcs != null ? VcsCherryPickManager.getInstance(project).getCherryPickerFor(vcs.getKeyInstanceMethod()) : null; } }); } return ContainerUtil.emptyList(); } - @Nullable - private static VcsCherryPicker getCherryPickerForCommit(@NotNull Project project, - @NotNull ProjectLevelVcsManager projectLevelVcsManager, - @NotNull VcsFullCommitDetails commitDetails) { - AbstractVcs vcs = projectLevelVcsManager.getVcsFor(commitDetails.getRoot()); - if (vcs == null) return null; - VcsKey key = vcs.getKeyInstanceMethod(); - return getCherryPickerFor(project, key); - } - private class CherryPickingTask extends Task.Backgroundable { - private final Project myProject; - private final ProjectLevelVcsManager myProjectLevelVcsManager; - private final Map> myGroupedCommits = ContainerUtil.newHashMap(); - private final Collection myAllCommits; - private final ChangeListManagerEx myChangeListManagerEx; - - public CherryPickingTask(@NotNull Project project, @NotNull Set details) { - super(project, "Cherry-Picking"); - myProject = project; - myProjectLevelVcsManager = ProjectLevelVcsManager.getInstance(myProject); - myAllCommits = details; - myChangeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); - myChangeListManagerEx.blockModalNotifications(); - } - - public boolean processDetails(@NotNull VcsFullCommitDetails details) { - myIdsInProgress.add(details.getId()); - - VcsCherryPicker cherryPicker = getCherryPickerForCommit(myProject, myProjectLevelVcsManager, details); - if (cherryPicker == null) { - String message = - "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName(); - VcsNotifier.getInstance(myProject).notifyWeakError(message); - LOG.warn(message); - return false; - } - List list = myGroupedCommits.get(cherryPicker); - if (list == null) { - myGroupedCommits.put(cherryPicker, list = new ArrayList()); // ordered set!! - } - list.add(details); - return true; - } - - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - boolean isOk = true; - for (VcsFullCommitDetails details : myAllCommits) { - if (!processDetails(details)) { - isOk = false; - break; - } - } - - if (isOk) { - for (Map.Entry> entry : myGroupedCommits.entrySet()) { - entry.getKey().cherryPick(sortCommits(entry.getValue())); - } - } - } - finally { - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - myChangeListManagerEx.unblockModalNotifications(); - for (VcsFullCommitDetails commit : myAllCommits) { - myIdsInProgress.remove(commit.getId()); - } - } - }); - } - } - } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java new file mode 100644 index 000000000000..c3d542f4fb07 --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -0,0 +1,154 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.dvcs.cherrypick; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangeListManagerEx; +import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.CommitId; +import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsLog; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class VcsCherryPickManager { + private static final Logger LOG = Logger.getInstance(VcsCherryPickManager.class); + @NotNull private final Project myProject; + @NotNull private final Set myIdsInProgress = ContainerUtil.newConcurrentSet(); + + public VcsCherryPickManager(@NotNull Project project) { + myProject = project; + } + + public void cherryPick(@NotNull VcsLog log) { + log.requestSelectedDetails(new Consumer>() { + @Override + public void consume(Set details) { + ProgressManager.getInstance().run(new CherryPickingTask(myProject, details)); + } + }, null); + } + + @Nullable + private VcsCherryPicker getCherryPickerForCommit(@NotNull ProjectLevelVcsManager projectLevelVcsManager, + @NotNull VcsFullCommitDetails commitDetails) { + AbstractVcs vcs = projectLevelVcsManager.getVcsFor(commitDetails.getRoot()); + if (vcs == null) return null; + VcsKey key = vcs.getKeyInstanceMethod(); + return getCherryPickerFor(key); + } + + @Nullable + public VcsCherryPicker getCherryPickerFor(@NotNull final VcsKey key) { + return ContainerUtil.find(Extensions.getExtensions(VcsCherryPicker.EXTENSION_POINT_NAME, myProject), new Condition() { + @Override + public boolean value(VcsCherryPicker picker) { + return picker.getSupportedVcs().equals(key); + } + }); + } + + private class CherryPickingTask extends Task.Backgroundable { + private final Project myProject; + private final ProjectLevelVcsManager myProjectLevelVcsManager; + private final Map> myGroupedCommits = ContainerUtil.newHashMap(); + private final Collection myAllCommits; + private final ChangeListManagerEx myChangeListManagerEx; + + public CherryPickingTask(@NotNull Project project, @NotNull Set details) { + super(project, "Cherry-Picking"); + myProject = project; + myProjectLevelVcsManager = ProjectLevelVcsManager.getInstance(myProject); + myAllCommits = details; + myChangeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); + myChangeListManagerEx.blockModalNotifications(); + } + + public boolean processDetails(@NotNull VcsFullCommitDetails details) { + myIdsInProgress.add(new CommitId(details.getId(), details.getRoot())); + + VcsCherryPicker cherryPicker = getCherryPickerForCommit(myProjectLevelVcsManager, details); + if (cherryPicker == null) { + String message = + "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName(); + VcsNotifier.getInstance(myProject).notifyWeakError(message); + LOG.warn(message); + return false; + } + List list = myGroupedCommits.get(cherryPicker); + if (list == null) { + myGroupedCommits.put(cherryPicker, list = new ArrayList()); // ordered set!! + } + list.add(details); + return true; + } + + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + boolean isOk = true; + for (VcsFullCommitDetails details : myAllCommits) { + if (!processDetails(details)) { + isOk = false; + break; + } + } + + if (isOk) { + for (Map.Entry> entry : myGroupedCommits.entrySet()) { + entry.getKey().cherryPick(sortCommits(entry.getValue())); + } + } + } + finally { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + myChangeListManagerEx.unblockModalNotifications(); + for (VcsFullCommitDetails details : myAllCommits) { + myIdsInProgress.remove(new CommitId(details.getId(), details.getRoot())); + } + } + }); + } + } + } + + @NotNull + private static List sortCommits(@NotNull List commits) { + Collections.reverse(commits); + return commits; + } + + public static VcsCherryPickManager getInstance(@NotNull Project project) { + return ServiceManager.getService(project, VcsCherryPickManager.class); + } +} From da6ec1194b46841edb06a69f4780cd31c7a06d20 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 20:41:27 +0300 Subject: [PATCH 119/825] [vcs-log] code issues in VcsCherryPickAction/Manager --- .../dvcs/cherrypick/VcsCherryPickAction.java | 41 ++++++++++++++----- .../dvcs/cherrypick/VcsCherryPickManager.java | 25 ++++------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index 5523461a1afd..e0e5b2387b36 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -27,13 +27,17 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.*; +import com.intellij.vcs.log.CommitId; +import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLog; +import com.intellij.vcs.log.VcsLogDataKeys; import com.intellij.vcs.log.impl.VcsLogUtil; import icons.DvcsImplIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.List; +import java.util.Map; public class VcsCherryPickAction extends DumbAwareAction { private static final String NAME = "Cherry-Pick"; @@ -56,32 +60,47 @@ public class VcsCherryPickAction extends DumbAwareAction { public void update(@NotNull AnActionEvent e) { super.update(e); e.getPresentation().setVisible(true); + final VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG); - Project project = getEventProject(e); - final List cherryPickers = getActiveCherryPickersForProject(project); + Project project = e.getProject(); + assert project != null; + + List cherryPickers = getActiveCherryPickersForProject(project); if (log == null || cherryPickers.isEmpty()) { e.getPresentation().setEnabledAndVisible(false); return; } - List details = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.MAX_SELECTED_COMMITS); - final Map> groupedByRoot = groupByRoot(details); - VcsCherryPicker enabledCherryPicker = ContainerUtil.find(cherryPickers, new Condition() { + List commits = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.MAX_SELECTED_COMMITS); + if (commits.isEmpty()) { + e.getPresentation().setEnabled(false); + return; + } + + VcsCherryPicker enabledCherryPicker = getEnabledCherryPicker(log, cherryPickers, commits); + e.getPresentation().setEnabled(enabledCherryPicker != null); + e.getPresentation() + .setText(enabledCherryPicker == null ? concatActionNamesForAllAvailable(cherryPickers) : enabledCherryPicker.getActionTitle()); + } + + @Nullable + private static VcsCherryPicker getEnabledCherryPicker(@NotNull final VcsLog log, + @NotNull List cherryPickers, + @NotNull List commits) { + final Map> groupedByRoot = groupByRoot(commits); + return ContainerUtil.find(cherryPickers, new Condition() { @Override public boolean value(VcsCherryPicker picker) { //all commits should be from one vcs, if not then all pickers should return false return picker.isEnabled(log, groupedByRoot); } }); - e.getPresentation().setEnabled(enabledCherryPicker != null); - e.getPresentation().setText( - enabledCherryPicker == null ? concatActionNamesForAllAvailable(cherryPickers) : enabledCherryPicker.getActionTitle()); } @NotNull private static Map> groupByRoot(@NotNull List details) { Map> result = ContainerUtil.newHashMap(); - for (CommitId commit: details) { + for (CommitId commit : details) { List hashes = result.get(commit.getRoot()); if (hashes == null) { hashes = ContainerUtil.newArrayList(); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index c3d542f4fb07..7c7a8f8109a1 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -43,10 +43,12 @@ import java.util.*; public class VcsCherryPickManager { private static final Logger LOG = Logger.getInstance(VcsCherryPickManager.class); @NotNull private final Project myProject; + @NotNull private final ProjectLevelVcsManager myProjectLevelVcsManager; @NotNull private final Set myIdsInProgress = ContainerUtil.newConcurrentSet(); - public VcsCherryPickManager(@NotNull Project project) { + public VcsCherryPickManager(@NotNull Project project, @NotNull ProjectLevelVcsManager projectLevelVcsManager) { myProject = project; + myProjectLevelVcsManager = projectLevelVcsManager; } public void cherryPick(@NotNull VcsLog log) { @@ -59,9 +61,8 @@ public class VcsCherryPickManager { } @Nullable - private VcsCherryPicker getCherryPickerForCommit(@NotNull ProjectLevelVcsManager projectLevelVcsManager, - @NotNull VcsFullCommitDetails commitDetails) { - AbstractVcs vcs = projectLevelVcsManager.getVcsFor(commitDetails.getRoot()); + private VcsCherryPicker getCherryPickerForCommit(@NotNull VcsFullCommitDetails commitDetails) { + AbstractVcs vcs = myProjectLevelVcsManager.getVcsFor(commitDetails.getRoot()); if (vcs == null) return null; VcsKey key = vcs.getKeyInstanceMethod(); return getCherryPickerFor(key); @@ -78,16 +79,12 @@ public class VcsCherryPickManager { } private class CherryPickingTask extends Task.Backgroundable { - private final Project myProject; - private final ProjectLevelVcsManager myProjectLevelVcsManager; private final Map> myGroupedCommits = ContainerUtil.newHashMap(); private final Collection myAllCommits; private final ChangeListManagerEx myChangeListManagerEx; public CherryPickingTask(@NotNull Project project, @NotNull Set details) { super(project, "Cherry-Picking"); - myProject = project; - myProjectLevelVcsManager = ProjectLevelVcsManager.getInstance(myProject); myAllCommits = details; myChangeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); myChangeListManagerEx.blockModalNotifications(); @@ -96,7 +93,7 @@ public class VcsCherryPickManager { public boolean processDetails(@NotNull VcsFullCommitDetails details) { myIdsInProgress.add(new CommitId(details.getId(), details.getRoot())); - VcsCherryPicker cherryPicker = getCherryPickerForCommit(myProjectLevelVcsManager, details); + VcsCherryPicker cherryPicker = getCherryPickerForCommit(details); if (cherryPicker == null) { String message = "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName(); @@ -125,7 +122,9 @@ public class VcsCherryPickManager { if (isOk) { for (Map.Entry> entry : myGroupedCommits.entrySet()) { - entry.getKey().cherryPick(sortCommits(entry.getValue())); + List commits = entry.getValue(); + Collections.reverse(commits); + entry.getKey().cherryPick(commits); } } } @@ -142,12 +141,6 @@ public class VcsCherryPickManager { } } - @NotNull - private static List sortCommits(@NotNull List commits) { - Collections.reverse(commits); - return commits; - } - public static VcsCherryPickManager getInstance(@NotNull Project project) { return ServiceManager.getService(project, VcsCherryPickManager.class); } From 684cd8334dff9887d118843c007c491583a0e4e0 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 29 Dec 2015 20:48:42 +0300 Subject: [PATCH 120/825] [vcs-log] check that selected commits are not already being processed --- .../dvcs/cherrypick/VcsCherryPickAction.java | 3 ++- .../dvcs/cherrypick/VcsCherryPickManager.java | 27 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java index e0e5b2387b36..57aeedea65dd 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickAction.java @@ -64,6 +64,7 @@ public class VcsCherryPickAction extends DumbAwareAction { final VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG); Project project = e.getProject(); assert project != null; + VcsCherryPickManager cherryPickManager = VcsCherryPickManager.getInstance(project); List cherryPickers = getActiveCherryPickersForProject(project); if (log == null || cherryPickers.isEmpty()) { @@ -72,7 +73,7 @@ public class VcsCherryPickAction extends DumbAwareAction { } List commits = VcsLogUtil.collectFirstPack(log.getSelectedCommits(), VcsLogUtil.MAX_SELECTED_COMMITS); - if (commits.isEmpty()) { + if (commits.isEmpty() || cherryPickManager.isCherryPickAlreadyStartedFor(commits)) { e.getPresentation().setEnabled(false); return; } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index 7c7a8f8109a1..d2c7465ec84a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -60,6 +60,15 @@ public class VcsCherryPickManager { }, null); } + public boolean isCherryPickAlreadyStartedFor(@NotNull List commits) { + for (CommitId commit : commits) { + if (myIdsInProgress.contains(commit)) { + return true; + } + } + return false; + } + @Nullable private VcsCherryPicker getCherryPickerForCommit(@NotNull VcsFullCommitDetails commitDetails) { AbstractVcs vcs = myProjectLevelVcsManager.getVcsFor(commitDetails.getRoot()); @@ -91,14 +100,17 @@ public class VcsCherryPickManager { } public boolean processDetails(@NotNull VcsFullCommitDetails details) { - myIdsInProgress.add(new CommitId(details.getId(), details.getRoot())); + CommitId commitId = new CommitId(details.getId(), details.getRoot()); + if (myIdsInProgress.contains(commitId)) { + showError("Cherry pick process is already started for commit " + commitId.getHash().toShortString() + " from root " + commitId.getRoot().getName()); + return false; + } + myIdsInProgress.add(commitId); VcsCherryPicker cherryPicker = getCherryPickerForCommit(details); if (cherryPicker == null) { - String message = - "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName(); - VcsNotifier.getInstance(myProject).notifyWeakError(message); - LOG.warn(message); + showError( + "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); return false; } List list = myGroupedCommits.get(cherryPicker); @@ -109,6 +121,11 @@ public class VcsCherryPickManager { return true; } + public void showError(@NotNull String message) { + VcsNotifier.getInstance(myProject).notifyWeakError(message); + LOG.warn(message); + } + @Override public void run(@NotNull ProgressIndicator indicator) { try { From 93fc5bd11861258b487fe0e0f10eb8310f9ae637 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 30 Dec 2015 18:12:53 +0300 Subject: [PATCH 121/825] [vcs-log] rename change list manager field, add not nulls --- .../dvcs/cherrypick/VcsCherryPickManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index d2c7465ec84a..af2570c8c45b 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -88,15 +88,15 @@ public class VcsCherryPickManager { } private class CherryPickingTask extends Task.Backgroundable { - private final Map> myGroupedCommits = ContainerUtil.newHashMap(); - private final Collection myAllCommits; - private final ChangeListManagerEx myChangeListManagerEx; + @NotNull private final Map> myGroupedCommits = ContainerUtil.newHashMap(); + @NotNull private final Collection myAllCommits; + @NotNull private final ChangeListManagerEx myChangeListManager; public CherryPickingTask(@NotNull Project project, @NotNull Set details) { super(project, "Cherry-Picking"); myAllCommits = details; - myChangeListManagerEx = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); - myChangeListManagerEx.blockModalNotifications(); + myChangeListManager = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); + myChangeListManager.blockModalNotifications(); } public boolean processDetails(@NotNull VcsFullCommitDetails details) { @@ -148,7 +148,7 @@ public class VcsCherryPickManager { finally { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { - myChangeListManagerEx.unblockModalNotifications(); + myChangeListManager.unblockModalNotifications(); for (VcsFullCommitDetails details : myAllCommits) { myIdsInProgress.remove(new CommitId(details.getId(), details.getRoot())); } From 2bf523c9750c1ff1636cc92145e8ec915da3df33 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 30 Dec 2015 18:24:27 +0300 Subject: [PATCH 122/825] [vcs-log] MultiMap instead of Map for cherry pickers --- .../dvcs/cherrypick/VcsCherryPickManager.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index af2570c8c45b..0af467ca0f5a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -15,6 +15,7 @@ */ package com.intellij.dvcs.cherrypick; +import com.google.common.collect.Lists; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -32,6 +33,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerEx; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.CommitId; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLog; @@ -88,7 +90,14 @@ public class VcsCherryPickManager { } private class CherryPickingTask extends Task.Backgroundable { - @NotNull private final Map> myGroupedCommits = ContainerUtil.newHashMap(); + @NotNull private final MultiMap myGroupedCommits = + new MultiMap() { + @NotNull + @Override + protected Collection createCollection() { + return new ArrayList(); + } + }; @NotNull private final Collection myAllCommits; @NotNull private final ChangeListManagerEx myChangeListManager; @@ -113,11 +122,7 @@ public class VcsCherryPickManager { "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); return false; } - List list = myGroupedCommits.get(cherryPicker); - if (list == null) { - myGroupedCommits.put(cherryPicker, list = new ArrayList()); // ordered set!! - } - list.add(details); + myGroupedCommits.putValue(cherryPicker, details); return true; } @@ -138,9 +143,8 @@ public class VcsCherryPickManager { } if (isOk) { - for (Map.Entry> entry : myGroupedCommits.entrySet()) { - List commits = entry.getValue(); - Collections.reverse(commits); + for (Map.Entry> entry : myGroupedCommits.entrySet()) { + List commits = Lists.reverse(Lists.newArrayList(entry.getValue())); entry.getKey().cherryPick(commits); } } From ff8ac4b968d019259433722b3cf54d45410ede82 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 30 Dec 2015 18:29:31 +0300 Subject: [PATCH 123/825] [vcs-log] turn myGroupedCommits into a parameter --- .../dvcs/cherrypick/VcsCherryPickManager.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index 0af467ca0f5a..86716fb7d5b5 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -90,14 +90,6 @@ public class VcsCherryPickManager { } private class CherryPickingTask extends Task.Backgroundable { - @NotNull private final MultiMap myGroupedCommits = - new MultiMap() { - @NotNull - @Override - protected Collection createCollection() { - return new ArrayList(); - } - }; @NotNull private final Collection myAllCommits; @NotNull private final ChangeListManagerEx myChangeListManager; @@ -108,7 +100,8 @@ public class VcsCherryPickManager { myChangeListManager.blockModalNotifications(); } - public boolean processDetails(@NotNull VcsFullCommitDetails details) { + public boolean processDetails(@NotNull VcsFullCommitDetails details, + @NotNull MultiMap groupedDetails) { CommitId commitId = new CommitId(details.getId(), details.getRoot()); if (myIdsInProgress.contains(commitId)) { showError("Cherry pick process is already started for commit " + commitId.getHash().toShortString() + " from root " + commitId.getRoot().getName()); @@ -122,7 +115,7 @@ public class VcsCherryPickManager { "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); return false; } - myGroupedCommits.putValue(cherryPicker, details); + groupedDetails.putValue(cherryPicker, details); return true; } @@ -135,15 +128,16 @@ public class VcsCherryPickManager { public void run(@NotNull ProgressIndicator indicator) { try { boolean isOk = true; + MultiMap groupedCommits = createArrayMultiMap(); for (VcsFullCommitDetails details : myAllCommits) { - if (!processDetails(details)) { + if (!processDetails(details, groupedCommits)) { isOk = false; break; } } if (isOk) { - for (Map.Entry> entry : myGroupedCommits.entrySet()) { + for (Map.Entry> entry : groupedCommits.entrySet()) { List commits = Lists.reverse(Lists.newArrayList(entry.getValue())); entry.getKey().cherryPick(commits); } @@ -160,6 +154,17 @@ public class VcsCherryPickManager { }); } } + + @NotNull + public MultiMap createArrayMultiMap() { + return new MultiMap() { + @NotNull + @Override + protected Collection createCollection() { + return new ArrayList(); + } + }; + } } public static VcsCherryPickManager getInstance(@NotNull Project project) { From 8d1158dba4a8c0ffcfa262f759a3ad6fe06e8d47 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 12 Jan 2016 18:14:27 +0300 Subject: [PATCH 124/825] [vcs-log] rename processDetails -> getCherryPickerOrReportError, make it return VcsCherryPicker or null instead of modifying groupedDetails in it --- .../dvcs/cherrypick/VcsCherryPickManager.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index 86716fb7d5b5..0600f8d726c0 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -100,12 +100,15 @@ public class VcsCherryPickManager { myChangeListManager.blockModalNotifications(); } - public boolean processDetails(@NotNull VcsFullCommitDetails details, - @NotNull MultiMap groupedDetails) { + @Nullable + private VcsCherryPicker getCherryPickerOrReportError(@NotNull VcsFullCommitDetails details) { CommitId commitId = new CommitId(details.getId(), details.getRoot()); if (myIdsInProgress.contains(commitId)) { - showError("Cherry pick process is already started for commit " + commitId.getHash().toShortString() + " from root " + commitId.getRoot().getName()); - return false; + showError("Cherry pick process is already started for commit " + + commitId.getHash().toShortString() + + " from root " + + commitId.getRoot().getName()); + return null; } myIdsInProgress.add(commitId); @@ -113,10 +116,9 @@ public class VcsCherryPickManager { if (cherryPicker == null) { showError( "Cherry pick is not supported for commit " + details.getId().toShortString() + " from root " + details.getRoot().getName()); - return false; + return null; } - groupedDetails.putValue(cherryPicker, details); - return true; + return cherryPicker; } public void showError(@NotNull String message) { @@ -130,10 +132,12 @@ public class VcsCherryPickManager { boolean isOk = true; MultiMap groupedCommits = createArrayMultiMap(); for (VcsFullCommitDetails details : myAllCommits) { - if (!processDetails(details, groupedCommits)) { + VcsCherryPicker cherryPicker = getCherryPickerOrReportError(details); + if (cherryPicker == null) { isOk = false; break; } + groupedCommits.putValue(cherryPicker, details); } if (isOk) { From 34673752f002fcf1a493dcf7566f85d7fe6dfe28 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 13 Jan 2016 17:24:26 +0300 Subject: [PATCH 125/825] [vcs-log] preserve order of loaded details --- .../dvcs/cherrypick/VcsCherryPickManager.java | 6 +- .../com/intellij/dvcs/ui/VcsLogAction.java | 6 +- .../api/src/com/intellij/vcs/log/VcsLog.java | 2 +- .../vcs/log/data/AbstractDataGetter.java | 68 ++++++++++++------- .../com/intellij/vcs/log/data/DataGetter.java | 3 +- .../com/intellij/vcs/log/impl/VcsLogImpl.java | 2 +- .../intellij/vcs/log/ui/frame/MainFrame.java | 4 +- .../vcs/log/data/VisiblePackBuilderTest.kt | 2 +- .../action/mq/HgQGotoFromLogAction.java | 4 +- 9 files changed, 56 insertions(+), 41 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index 0600f8d726c0..8b9e3337b4f8 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -54,9 +54,9 @@ public class VcsCherryPickManager { } public void cherryPick(@NotNull VcsLog log) { - log.requestSelectedDetails(new Consumer>() { + log.requestSelectedDetails(new Consumer>() { @Override - public void consume(Set details) { + public void consume(List details) { ProgressManager.getInstance().run(new CherryPickingTask(myProject, details)); } }, null); @@ -93,7 +93,7 @@ public class VcsCherryPickManager { @NotNull private final Collection myAllCommits; @NotNull private final ChangeListManagerEx myChangeListManager; - public CherryPickingTask(@NotNull Project project, @NotNull Set details) { + public CherryPickingTask(@NotNull Project project, @NotNull List details) { super(project, "Cherry-Picking"); myAllCommits = details; myChangeListManager = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java index 34ab175599cb..93baa14eca15 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java @@ -34,8 +34,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.List; import java.util.Map; -import java.util.Set; public abstract class VcsLogAction extends DumbAwareAction { @@ -44,9 +44,9 @@ public abstract class VcsLogAction extends DumbAwareAct final Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - log.requestSelectedDetails(new Consumer>() { + log.requestSelectedDetails(new Consumer>() { @Override - public void consume(Set details) { + public void consume(List details) { MultiMap grouped = groupCommits(project, details, new Function() { @Override public VirtualFile fun(VcsFullCommitDetails vcsFullCommitDetails) { diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java index 2813efbf647d..7c0f9f24ca19 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLog.java @@ -52,7 +52,7 @@ public interface VcsLog { * @param consumer called in EDT after all details are loaded. * @param indicator progress indicator to use in loading process, can be null. */ - void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator); + void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator); /** * Returns names of branches which contain the given commit, or null if this information is unavailable. diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java index 2e7c59c23441..2970cab0c0f8 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/AbstractDataGetter.java @@ -6,8 +6,10 @@ import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; @@ -142,35 +144,35 @@ abstract class AbstractDataGetter implements Di @Override public void loadCommitsData(@NotNull List rows, @NotNull GraphTableModel tableModel, - @NotNull Consumer> consumer, + @NotNull Consumer> consumer, @Nullable ProgressIndicator indicator) { assert EventQueue.isDispatchThread(); loadCommitsData(getCommitsForRows(rows, tableModel), consumer, indicator); } - private void loadCommitsData(@NotNull final MultiMap commits, - @NotNull final Consumer> consumer, + private void loadCommitsData(@NotNull final Map, Integer> commits, + @NotNull final Consumer> consumer, @Nullable ProgressIndicator indicator) { - final Set result = ContainerUtil.newHashSet(); + final List result = ContainerUtil.newArrayList(); final MultiMap toLoad = MultiMap.create(); long taskNumber = myCurrentTaskIndex++; - for (VirtualFile root : commits.keySet()) { - Collection hashesForRoot = commits.get(root); - for (final Integer commitId : hashesForRoot) { - T details = getFromCache(commitId); - if (details == null || details instanceof LoadingDetails) { - toLoad.putValue(root, commitId); - cacheCommit(commitId, root, taskNumber); - } - else { - result.add(details); - } + for (Pair rootAndCommit : commits.keySet()) { + VirtualFile root = rootAndCommit.getFirst(); + Integer commitId = rootAndCommit.getSecond(); + T details = getFromCache(commitId); + if (details == null || details instanceof LoadingDetails) { + toLoad.putValue(root, commitId); + cacheCommit(commitId, root, taskNumber); + } + else { + result.add(details); } } if (toLoad.isEmpty()) { + sortCommitsByRow(result, commits); consumer.consume(result); } else { @@ -181,6 +183,7 @@ abstract class AbstractDataGetter implements Di indicator.checkCanceled(); try { result.addAll(preLoadCommitData(toLoad)); + sortCommitsByRow(result, commits); notifyLoaded(); } catch (VcsException e) { @@ -202,6 +205,17 @@ abstract class AbstractDataGetter implements Di } } + private void sortCommitsByRow(@NotNull List result, @NotNull final Map, Integer> rowsForCommits) { + ContainerUtil.sort(result, new Comparator() { + @Override + public int compare(T details1, T details2) { + Integer row1 = rowsForCommits.get(Pair.create(details1.getRoot(), myHashMap.getCommitIndex(details1.getId(), details1.getRoot()))); + Integer row2 = rowsForCommits.get(Pair.create(details2.getRoot(), myHashMap.getCommitIndex(details2.getId(), details2.getRoot()))); + return Comparing.compare(row1, row2); + } + }); + } + @Override @Nullable public T getCommitDataIfAvailable(int hash) { @@ -232,17 +246,18 @@ abstract class AbstractDataGetter implements Di private void runLoadCommitsData(@NotNull GraphTableModel tableModel, @NotNull Iterable rows) { long taskNumber = myCurrentTaskIndex++; - MultiMap commits = getCommitsForRows(rows, tableModel); - for (Map.Entry> hashesByRoots : commits.entrySet()) { - VirtualFile root = hashesByRoots.getKey(); - Collection hashes = hashesByRoots.getValue(); + Map, Integer> commits = getCommitsForRows(rows, tableModel); + MultiMap toLoad = MultiMap.create(); - for (final int commitId : hashes) { - cacheCommit(commitId, root, taskNumber); - } + for (Pair rootAndCommit : commits.keySet()) { + VirtualFile root = rootAndCommit.getFirst(); + Integer commitId = rootAndCommit.getSecond(); + + cacheCommit(commitId, root, taskNumber); + toLoad.putValue(root, commitId); } - myLoader.queue(new TaskDescriptor(commits)); + myLoader.queue(new TaskDescriptor(toLoad)); } private void cacheCommit(final int commitId, VirtualFile root, long taskNumber) { @@ -260,12 +275,13 @@ abstract class AbstractDataGetter implements Di } @NotNull - private static MultiMap getCommitsForRows(@NotNull Iterable rows, @NotNull GraphTableModel model) { - MultiMap commits = MultiMap.create(); + private static Map, Integer> getCommitsForRows(@NotNull Iterable rows, + @NotNull GraphTableModel model) { + Map, Integer> commits = ContainerUtil.newHashMap(); for (int row : rows) { Integer commitId = model.getIdAtRow(row); VirtualFile root = model.getRoot(row); - commits.putValue(root, commitId); + commits.put(Pair.create(root, commitId), row); } return commits; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java index 1e4b485c102c..91e19c0f813b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java @@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.Set; public interface DataGetter { @Nullable @@ -31,7 +30,7 @@ public interface DataGetter { void loadCommitsData(@NotNull List rows, @NotNull GraphTableModel tableModel, - @NotNull Consumer> consumer, + @NotNull Consumer> consumer, @Nullable ProgressIndicator indicator); @Nullable diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index a3be80855d75..829d71d0e0f9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -83,7 +83,7 @@ public class VcsLogImpl implements VcsLog { } @Override - public void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator) { + public void requestSelectedDetails(@NotNull Consumer> consumer, @Nullable ProgressIndicator indicator) { List rowsList = Ints.asList(myUi.getTable().getSelectedRows()); myDataHolder.getCommitDetailsGetter().loadCommitsData(rowsList, (GraphTableModel)myUi.getTable().getModel(), consumer, indicator); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 5f5207a4f01b..5dca33647da2 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -398,9 +398,9 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { final EmptyProgressIndicator indicator = new EmptyProgressIndicator(); myLastRequest = indicator; - myLog.requestSelectedDetails(new Consumer>() { + myLog.requestSelectedDetails(new Consumer>() { @Override - public void consume(Set detailsList) { + public void consume(List detailsList) { if (myLastRequest == indicator && !(indicator.isCanceled())) { myLastRequest = null; List changes = ContainerUtil.newArrayList(); diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt index cae52f9b911f..150dc97df02f 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VisiblePackBuilderTest.kt @@ -154,7 +154,7 @@ class VisiblePackBuilderTest { return null } - override fun loadCommitsData(rows: MutableList, tableModel: GraphTableModel, consumer: Consumer>, indicator: ProgressIndicator?) { + override fun loadCommitsData(rows: MutableList, tableModel: GraphTableModel, consumer: Consumer>, indicator: ProgressIndicator?) { } override fun getCommitDataIfAvailable(hash: Int): VcsFullCommitDetails? { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java index d3169bcc2d09..8b34927ee579 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/mq/HgQGotoFromLogAction.java @@ -81,9 +81,9 @@ public class HgQGotoFromLogAction extends HgMqAppliedPatchAction { final Project project = e.getRequiredData(CommonDataKeys.PROJECT); VcsLog log = e.getRequiredData(VcsLogDataKeys.VCS_LOG); - log.requestSelectedDetails(new Consumer>() { + log.requestSelectedDetails(new Consumer>() { @Override - public void consume(Set selectedDetails) { + public void consume(List selectedDetails) { VcsFullCommitDetails fullCommitDetails = ContainerUtil.getFirstItem(selectedDetails); assert fullCommitDetails != null; From 0f53670d06f35be81ae52621095cb5e00e133709 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 13 Jan 2016 17:27:52 +0300 Subject: [PATCH 126/825] [vcs-log] try to move reversing commits list to a more visible place --- .../dvcs/cherrypick/VcsCherryPickManager.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java index 8b9e3337b4f8..5ca52904f1fe 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/cherrypick/VcsCherryPickManager.java @@ -57,7 +57,7 @@ public class VcsCherryPickManager { log.requestSelectedDetails(new Consumer>() { @Override public void consume(List details) { - ProgressManager.getInstance().run(new CherryPickingTask(myProject, details)); + ProgressManager.getInstance().run(new CherryPickingTask(myProject, ContainerUtil.reverse(details))); } }, null); } @@ -90,12 +90,12 @@ public class VcsCherryPickManager { } private class CherryPickingTask extends Task.Backgroundable { - @NotNull private final Collection myAllCommits; + @NotNull private final List myAllDetailsInReverseOrder; @NotNull private final ChangeListManagerEx myChangeListManager; - public CherryPickingTask(@NotNull Project project, @NotNull List details) { + public CherryPickingTask(@NotNull Project project, @NotNull List detailsInReverseOrder) { super(project, "Cherry-Picking"); - myAllCommits = details; + myAllDetailsInReverseOrder = detailsInReverseOrder; myChangeListManager = (ChangeListManagerEx)ChangeListManager.getInstance(myProject); myChangeListManager.blockModalNotifications(); } @@ -131,7 +131,7 @@ public class VcsCherryPickManager { try { boolean isOk = true; MultiMap groupedCommits = createArrayMultiMap(); - for (VcsFullCommitDetails details : myAllCommits) { + for (VcsFullCommitDetails details : myAllDetailsInReverseOrder) { VcsCherryPicker cherryPicker = getCherryPickerOrReportError(details); if (cherryPicker == null) { isOk = false; @@ -142,8 +142,7 @@ public class VcsCherryPickManager { if (isOk) { for (Map.Entry> entry : groupedCommits.entrySet()) { - List commits = Lists.reverse(Lists.newArrayList(entry.getValue())); - entry.getKey().cherryPick(commits); + entry.getKey().cherryPick(Lists.newArrayList(entry.getValue())); } } } @@ -151,7 +150,7 @@ public class VcsCherryPickManager { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { myChangeListManager.unblockModalNotifications(); - for (VcsFullCommitDetails details : myAllCommits) { + for (VcsFullCommitDetails details : myAllDetailsInReverseOrder) { myIdsInProgress.remove(new CommitId(details.getId(), details.getRoot())); } } From 20fadd17f0eaaabf722faaff4e882169fbc3176e Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 14 Jan 2016 17:49:02 +0100 Subject: [PATCH 127/825] dpi aware insets --- .../src/build/PluginModuleBuildConfEditor.java | 5 +++-- .../src/projectRoots/IdeaJdkConfigurable.java | 13 +++++++------ .../src/run/PluginRunConfigurationEditor.java | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/plugins/devkit/src/build/PluginModuleBuildConfEditor.java b/plugins/devkit/src/build/PluginModuleBuildConfEditor.java index 8ac3b4c64663..be4c0df8d423 100644 --- a/plugins/devkit/src/build/PluginModuleBuildConfEditor.java +++ b/plugins/devkit/src/build/PluginModuleBuildConfEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -26,6 +26,7 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.ui.IdeBorderFactory; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NonNls; import org.jetbrains.idea.devkit.DevKitBundle; @@ -71,7 +72,7 @@ public class PluginModuleBuildConfEditor implements ModuleConfigurationEditor { } }); final GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0); + GridBagConstraints.HORIZONTAL, JBUI.insets(2), 0, 0); myWholePanel.add(myPluginXMLLabel, gc); myWholePanel.add(myPluginXML, gc); JPanel manifestPanel = new JPanel(new GridBagLayout()); diff --git a/plugins/devkit/src/projectRoots/IdeaJdkConfigurable.java b/plugins/devkit/src/projectRoots/IdeaJdkConfigurable.java index 3eb4c5f97431..4dc93bb25eda 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdkConfigurable.java +++ b/plugins/devkit/src/projectRoots/IdeaJdkConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -15,7 +15,6 @@ */ package org.jetbrains.idea.devkit.projectRoots; -import com.intellij.ui.ListCellRendererWrapper; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -29,8 +28,10 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.GuiUtils; +import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.util.ArrayUtil; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NonNls; import org.jetbrains.idea.devkit.DevKitBundle; @@ -112,7 +113,7 @@ public class IdeaJdkConfigurable implements AdditionalDataConfigurable { mySandboxHome.setHistorySize(5); JPanel wholePanel = new JPanel(new GridBagLayout()); wholePanel.add(mySandboxHomeLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, - GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + GridBagConstraints.NONE, JBUI.emptyInsets(), 0, 0)); wholePanel.add(GuiUtils.constructFieldWithBrowseButton(mySandboxHome, new ActionListener() { public void actionPerformed(ActionEvent e) { FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); @@ -125,12 +126,12 @@ public class IdeaJdkConfigurable implements AdditionalDataConfigurable { myModified = true; } }), new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.EAST, - GridBagConstraints.HORIZONTAL, new Insets(0, 30, 0, 0), 0, 0)); + GridBagConstraints.HORIZONTAL, JBUI.insets(0, 30, 0, 0), 0, 0)); wholePanel.add(myInternalJreLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0, 1, GridBagConstraints.WEST, - GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + GridBagConstraints.NONE, JBUI.emptyInsets(), 0, 0)); wholePanel.add(myInternalJres, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.EAST, - GridBagConstraints.HORIZONTAL, new Insets(0, 30, 0, 0), 0, 0)); + GridBagConstraints.HORIZONTAL, JBUI.insets(0, 30, 0, 0), 0, 0)); myInternalJres.setRenderer(new ListCellRendererWrapper() { @Override public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { diff --git a/plugins/devkit/src/run/PluginRunConfigurationEditor.java b/plugins/devkit/src/run/PluginRunConfigurationEditor.java index bb2701c37633..170fde656860 100644 --- a/plugins/devkit/src/run/PluginRunConfigurationEditor.java +++ b/plugins/devkit/src/run/PluginRunConfigurationEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -30,6 +30,7 @@ import com.intellij.openapi.ui.LabeledComponent; import com.intellij.ui.PanelWithAnchor; import com.intellij.ui.RawCommandLineEditor; import com.intellij.ui.components.JBLabel; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -161,7 +162,8 @@ public class PluginRunConfigurationEditor extends SettingsEditor Date: Thu, 14 Jan 2016 18:19:11 +0100 Subject: [PATCH 128/825] dpi aware insets --- .../com/intellij/facet/impl/ui/FacetEditorImpl.java | 7 ++++--- .../AddSupportForFrameworksPanel.java | 5 ++--- .../ide/util/projectWizard/NamePathComponent.java | 11 ++++++----- .../ide/util/projectWizard/ProjectNameStep.java | 8 ++++---- .../roots/ui/configuration/ClasspathEditor.java | 5 +++-- .../openapi/roots/ui/configuration/OutputEditor.java | 5 +++-- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java index 41868ba87529..d7a7baab0f51 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -27,6 +27,7 @@ import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.openapi.options.UnnamedConfigurableGroup; import com.intellij.openapi.util.Disposer; import com.intellij.ui.TabbedPaneWrapper; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -96,14 +97,14 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed } else if (myEditorTabs.length == 1) { editorComponent = myEditorTabs[0].createComponent(); - UIUtil.addInsets(editorComponent, new Insets(0, 5, 0, 0)); + UIUtil.addInsets(editorComponent, JBUI.insets(0, 5, 0, 0)); } else { editorComponent = new JPanel(); } final JComponent errorComponent = myErrorPanel.getComponent(); - UIUtil.addInsets(errorComponent, new Insets(0, 5, 5, 0)); + UIUtil.addInsets(errorComponent, JBUI.insets(0, 5, 5, 0)); final JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, editorComponent); diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java index ea88dcd3698e..b3d3d05a1fbc 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -34,7 +34,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.DumbModePermission; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.IdeaModifiableModelsProvider; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.Library; @@ -176,7 +175,7 @@ public class AddSupportForFrameworksPanel implements Disposable { private static void addAssociatedFrameworkComponent(JPanel component, JPanel panel) { panel.add(component, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0, GridBagConstraints.NORTHWEST, - GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + GridBagConstraints.HORIZONTAL, JBUI.emptyInsets(), 0, 0)); } protected void onFrameworkStateChanged() {} diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java index 4541ba7b8693..a7d433a5fc87 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -28,6 +28,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.FieldPanel; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -91,11 +92,11 @@ public class NamePathComponent extends JPanel{ myNameLabel = new JLabel(nameLabelText); if (bold) myNameLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)); myNameLabel.setLabelFor(myTfName); - Insets insets = new Insets(0, 0, 5, 4); + Insets insets = JBUI.insets(0, 0, 5, 4); this.add(myNameLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0)); - insets = new Insets(0, 0, 5, 0); + insets = JBUI.insets(0, 0, 5, 0); this.add(myTfName, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, insets, 0, 0)); // todo: review texts @@ -111,10 +112,10 @@ public class NamePathComponent extends JPanel{ myPathLabel = new JLabel(pathLabelText); myPathLabel.setLabelFor(myTfPath); if (bold) myPathLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)); - insets = new Insets(0, 0, 5, 4); + insets = JBUI.insets(0, 0, 5, 4); this.add(myPathLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0)); - insets = new Insets(0, 0, 5, 0); + insets = JBUI.insets(0, 0, 5, 0); this.add(myPathPanel, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, insets, 0, 0)); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java index 398515f72b62..fea2114fc386 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -19,12 +19,12 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.openapi.application.ApplicationInfo; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NonNls; import javax.swing.*; @@ -55,9 +55,9 @@ public class ProjectNameStep extends ModuleWizardStep { ApplicationInfo info = ApplicationInfo.getInstance(); String appName = info.getVersionName(); myPanel.add(new JLabel(IdeBundle.message("label.please.enter.project.name", appName, wizardContext.getPresentationName())), - new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(8, 10, 8, 10), 0, 0)); + new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, JBUI.insets(8, 10), 0, 0)); - myPanel.add(myNamePathComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(8, 10, 8, 10), 0, 0)); + myPanel.add(myNamePathComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, JBUI.insets(8, 10), 0, 0)); } public JComponent getPreferredFocusedComponent() { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java index 44ddcce6ff65..9337892a9ba9 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.impl.storage.ClasspathStorageProvider; import com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanelImpl; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Disposer; +import com.intellij.util.ui.JBUI; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; @@ -163,7 +164,7 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL super(new GridBagLayout()); add(new JLabel(ProjectBundle.message("project.roots.classpath.format.label")), - new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 6, 6, 0), 0, 0)); + new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, JBUI.insets(10, 6, 6, 0), 0, 0)); formatIdToDescription.put(ClassPathStorageUtil.DEFAULT_STORAGE, ProjectBundle.message("project.roots.classpath.format.default.descr")); for (ClasspathStorageProvider provider : providers) { @@ -173,7 +174,7 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL comboBoxClasspathFormat = new ComboBox(formatIdToDescription.values().toArray()); updateClasspathFormat(); add(comboBoxClasspathFormat, - new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(6, 6, 6, 0), 0, 0)); + new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, JBUI.insets(6, 6, 6, 0), 0, 0)); } private void updateClasspathFormat() { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/OutputEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/OutputEditor.java index fe3ce1a82f7c..44d3fed6eb78 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/OutputEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/OutputEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -24,6 +24,7 @@ package com.intellij.openapi.roots.ui.configuration; import com.intellij.openapi.project.ProjectBundle; import com.intellij.ui.IdeBorderFactory; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -49,7 +50,7 @@ public class OutputEditor extends ModuleElementsEditor { final JPanel panel = new JPanel(new GridBagLayout()); panel.setBorder(new EmptyBorder(UIUtil.PANEL_SMALL_INSETS)); final GridBagConstraints gc = - new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0); + new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0); panel.add(myCompilerOutputEditor.createComponentImpl(), gc); final JPanel javadocPanel = (JPanel)myJavadocEditor.createComponentImpl(); javadocPanel.setBorder(IdeBorderFactory.createTitledBorder(myJavadocEditor.getDisplayName(), false)); From 31ab9592372ef02fd086cddcc1e38ac79ac71408 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 16:41:20 +0100 Subject: [PATCH 129/825] accept secondary setup methods (IDEA-150310) --- .../src/com/intellij/execution/junit/JUnitUtil.java | 4 ++-- .../com/intellij/execution/junit/JUnit4Framework.java | 1 + .../com/theoryinpractice/testng/TestNGFramework.java | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 9e088f81785b..74bf67d2c428 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -55,8 +55,8 @@ public class JUnitUtil { public static final String BEFORE_ANNOTATION_NAME = "org.junit.Before"; public static final String AFTER_ANNOTATION_NAME = "org.junit.After"; public static final String PARAMETRIZED_PARAMETERS_ANNOTATION_NAME = "org.junit.runners.Parameterized.Parameters"; - private static final String AFTER_CLASS_ANNOTATION_NAME = "org.junit.AfterClass"; - private static final String BEFORE_CLASS_ANNOTATION_NAME = "org.junit.BeforeClass"; + public static final String AFTER_CLASS_ANNOTATION_NAME = "org.junit.AfterClass"; + public static final String BEFORE_CLASS_ANNOTATION_NAME = "org.junit.BeforeClass"; private static final Collection CONFIGURATIONS_ANNOTATION_NAME = Collections.unmodifiableList( Arrays.asList(DATA_POINT, AFTER_ANNOTATION_NAME, BEFORE_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME, BEFORE_CLASS_ANNOTATION_NAME)); diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java index aa8af2fc46ff..30c271ebe6ed 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java @@ -96,6 +96,7 @@ public class JUnit4Framework extends JavaTestFramework { method = createSetUpPatternMethod(factory); PsiMethod existingMethod = clazz.findMethodBySignature(method, false); if (existingMethod != null) { + if (AnnotationUtil.isAnnotated(existingMethod, JUnitUtil.BEFORE_CLASS_ANNOTATION_NAME, false)) return existingMethod; int exit = ApplicationManager.getApplication().isUnitTestMode() ? Messages.OK : Messages.showOkCancelDialog("Method setUp already exist but is not annotated as @Before. Annotate?", diff --git a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java index d67a45c20a5f..9ac273ad70ea 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java +++ b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java @@ -36,8 +36,16 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import javax.swing.*; +import java.util.Arrays; +import java.util.List; public class TestNGFramework extends JavaTestFramework { + private final static List SECONDARY_BEFORE_ANNOTATIONS = Arrays.asList("org.testng.annotations.BeforeTest", + "org.testng.annotations.BeforeClass", + "org.testng.annotations.BeforeSuite", + "org.testng.annotations.BeforeGroups" + ); + @NotNull public String getName() { return "TestNG"; @@ -97,6 +105,9 @@ public class TestNGFramework extends JavaTestFramework { PsiMethod patternMethod = createSetUpPatternMethod(factory); PsiMethod inClass = clazz.findMethodBySignature(patternMethod, false); if (inClass != null) { + if (AnnotationUtil.isAnnotated(inClass, SECONDARY_BEFORE_ANNOTATIONS, false)) { + return inClass; + } int exit = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoDialog(manager.getProject(), "Method \'" + setUpName + "\' already exist but is not annotated as @BeforeMethod.", From 59f416b7d45489806bdf77b308ede6581b79f1e8 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 17:05:55 +0100 Subject: [PATCH 130/825] replace hardcoded clone with protected methods of Object (IDEA-150196) --- .../daemon/impl/analysis/HighlightMethodUtil.java | 8 +++++--- ...tectedMethodsAndInterfaceMethodsWithSameSignature.java | 4 ++++ .../codeInsight/daemon/GenericsHighlightingTest.java | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IgnoreReturnTypeClashForObjectProtectedMethodsAndInterfaceMethodsWithSameSignature.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index c36dcd195ac9..0ea7cb4839b1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -168,10 +168,12 @@ public class HighlightMethodUtil { @NotNull TextRange range, @NotNull LanguageLevel languageLevel) { if (superReturnType == null) return null; - if ("clone".equals(method.getName())) { + final PsiClass superContainingClass = superMethod.getContainingClass(); + if (superContainingClass != null && + CommonClassNames.JAVA_LANG_OBJECT.equals(superContainingClass.getQualifiedName()) && + !superMethod.hasModifierProperty(PsiModifier.PUBLIC)) { final PsiClass containingClass = method.getContainingClass(); - final PsiClass superContainingClass = superMethod.getContainingClass(); - if (containingClass != null && superContainingClass != null && containingClass.isInterface() && !superContainingClass.isInterface()) { + if (containingClass != null && containingClass.isInterface() && !superContainingClass.isInterface()) { return null; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IgnoreReturnTypeClashForObjectProtectedMethodsAndInterfaceMethodsWithSameSignature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IgnoreReturnTypeClashForObjectProtectedMethodsAndInterfaceMethodsWithSameSignature.java new file mode 100644 index 000000000000..ac9ae37c244e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IgnoreReturnTypeClashForObjectProtectedMethodsAndInterfaceMethodsWithSameSignature.java @@ -0,0 +1,4 @@ + +interface I { + String finalize(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index d7a6f39eb842..b8944b7ded5a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -559,6 +559,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testIgnoreReturnTypeClashForObjectProtectedMethodsAndInterfaceMethodsWithSameSignature() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testLeastUpperBoundWithRecursiveTypes() throws Exception { final PsiManager manager = getPsiManager(); final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); From 1976c64367693277d820d5d1be884443a6beb8b1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 18:02:40 +0100 Subject: [PATCH 131/825] move trivial method ref/trivial functional expression usage to redundancy group --- resources/src/META-INF/IdeaPlugin.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 19912187a3a9..49a45d78227c 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -727,10 +727,10 @@ groupKey="group.names.language.level.specific.issues.and.migration.aids" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection" /> Date: Thu, 14 Jan 2016 18:29:49 +0100 Subject: [PATCH 132/825] TypeName.super checks for classes fixed (IDEA-150141) --- .../daemon/impl/analysis/HighlightUtil.java | 28 +++++++++++++++---- .../src/messages/JavaErrorMessages.properties | 2 +- ...faceSuperMethodReferenceApplicability.java | 18 ++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index fb3b83379666..fdcd49003c0b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -60,7 +60,10 @@ import com.intellij.util.ui.UIUtil; import com.intellij.xml.util.XmlStringUtil; import gnu.trove.THashMap; import org.intellij.lang.annotations.Language; -import org.jetbrains.annotations.*; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.PropertyKey; import java.util.*; import java.util.regex.Matcher; @@ -1548,12 +1551,25 @@ public class HighlightUtil extends HighlightUtilBase { //or if there exists some other direct superclass or direct superinterface of T, J, such that J is a subtype of I. final PsiClass classT = PsiTreeUtil.getParentOfType(expr, PsiClass.class); if (classT != null) { + final PsiElement parent = expr.getParent(); + final PsiElement resolved = parent instanceof PsiReferenceExpression ? ((PsiReferenceExpression)parent).resolve() : null; + for (PsiClass superClass : classT.getSupers()) { - if (superClass.isInterface() && //check spec-javac relations - superClass.isInheritor(aClass, true)) { - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) - .range(qualifier) - .descriptionAndTooltip(JavaErrorMessages.message("bad.qualifier.in.super.method.reference", format(aClass), formatClass(superClass))).create(); + if (superClass.isInheritor(aClass, true)) { + String cause = null; + if (superClass.isInterface()) { + cause = "redundant interface " + format(aClass) + " is extended by "; + } + else if (resolved instanceof PsiMethod && + MethodSignatureUtil.findMethodBySuperMethod(superClass, (PsiMethod)resolved, true) != resolved) { + cause = "method " + ((PsiMethod)resolved).getName() + " is overridden in "; + } + + if (cause != null) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(qualifier) + .descriptionAndTooltip(JavaErrorMessages.message("bad.qualifier.in.super.method.reference", cause + formatClass(superClass))).create(); + } } } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 81b2c5ed8009..d03c02b68c72 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -99,7 +99,7 @@ illegal.generic.type.for.instanceof=Illegal generic type for instanceof cannot.select.dot.class.from.type.variable=Cannot select from a type variable method.does.not.override.super=Method does not override method from its superclass call.to.super.is.not.allowed.in.enum.constructor=Call to super is not allowed in enum constructor -bad.qualifier.in.super.method.reference=Bad type qualifier in default super call: redundant interface {0} is extended by {1} +bad.qualifier.in.super.method.reference=Bad type qualifier in default super call: {0} vararg.not.last.parameter=Vararg parameter must be the last in the list modifiers.for.enum.constants=No modifiers allowed for enum constants generics.type.arguments.on.raw.type=Type arguments given on a raw type diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/TypeNameInterfaceSuperMethodReferenceApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/TypeNameInterfaceSuperMethodReferenceApplicability.java index 23bdff178cca..b570019d8846 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/TypeNameInterfaceSuperMethodReferenceApplicability.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/TypeNameInterfaceSuperMethodReferenceApplicability.java @@ -45,5 +45,23 @@ class Test { J.super.toString(); } } + + class E implements I { + public void a() {} + } + + class F extends E implements I { + void bar() { + I.super.a(); + Runnable r = I.super::a; + } + } + + class G extends A implements I { + void bar() { + I.super.a(); + Runnable r = I.super::a; + } + } } From 13ff33e8d1cd2557e9e2fb40d6cc5e3b3c451e2a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 18:32:03 +0100 Subject: [PATCH 133/825] wording following IDEA-CR-7808 --- .../src/inspectionDescriptions/TrivialMethodReference.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-en/src/inspectionDescriptions/TrivialMethodReference.html b/resources-en/src/inspectionDescriptions/TrivialMethodReference.html index b4674967606f..7ab01df1db23 100644 --- a/resources-en/src/inspectionDescriptions/TrivialMethodReference.html +++ b/resources-en/src/inspectionDescriptions/TrivialMethodReference.html @@ -1,5 +1,5 @@ -This inspection reports method references which point to the abstract methods of the same functional interface types and hence can be replaced with their qualifiers +This inspection reports method references which point to a method of their own functional interface type and hence can be replaced with their qualifiers. \ No newline at end of file From a73e5d60d89552e724a3180937c499a311e81cf5 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Thu, 14 Jan 2016 18:34:29 +0300 Subject: [PATCH 134/825] Fix exception in console with python 3 (PY-18189) --- python/helpers/pydev/pydevconsole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index ad6443df81e7..bd2bfcaf5ad2 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -201,7 +201,7 @@ def process_exec_queue(interpreter): except _queue.Empty: continue - if callable(code_fragment): + if hasattr(code_fragment, '__call__'): # It can be a callable (i.e.: something that must run in the main # thread can be put in the queue for later execution). code_fragment() From 809412934f64dfe21f9286839045b3b43131b25e Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Thu, 14 Jan 2016 20:31:00 +0300 Subject: [PATCH 135/825] Remote debugging: Warning about wrong debugger version (PY-17929) --- python/src/com/jetbrains/python/debugger/PyDebugProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index 6e5d70c507ca..c43465ba6ef7 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -353,7 +353,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr printToConsole("Connected to pydev debugger (build " + remoteVersion + ")\n", ConsoleViewContentType.SYSTEM_OUTPUT); if (remoteVersion != null) { - if (!remoteVersion.equals(currentBuild)) { + if (!(remoteVersion.equals(currentBuild) || remoteVersion.startsWith(currentBuild))) { LOG.warn(String.format("Wrong debugger version. Remote version: %s Current build: %s", remoteVersion, currentBuild)); printToConsole("Warning: wrong debugger version. Use pycharm-debugger.egg from PyCharm installation folder.\n", ConsoleViewContentType.ERROR_OUTPUT); From 4e0e643896a096624198d909ba05c2a5cfbce8e7 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 14 Jan 2016 20:58:29 +0300 Subject: [PATCH 136/825] IDEA-149395 Fix viewport position for flipped translucent scroll bars --- .../intellij/ui/components/JBViewport.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/JBViewport.java b/platform/platform-api/src/com/intellij/ui/components/JBViewport.java index 4acfe5f38cd2..b5a89627c745 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBViewport.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBViewport.java @@ -201,6 +201,33 @@ public class JBViewport extends JViewport implements ZoomableViewport { return size; } + @Override + public Point getViewPosition() { + return updateViewPosition(super.getViewPosition(), false); + } + + @Override + public void setViewPosition(Point p) { + super.setViewPosition(updateViewPosition(p, true)); + } + + private Point updateViewPosition(Point p, boolean minus) { + JScrollPane pane = getScrollPane(this); + if (pane != null) { + JScrollBar vsb = pane.getVerticalScrollBar(); + if (Alignment.LEFT == getAlignment(vsb)) { + int width = vsb.getWidth(); + p.x += minus ? -width : width; + } + JScrollBar hsb = pane.getHorizontalScrollBar(); + if (Alignment.TOP == getAlignment(hsb)) { + int height = hsb.getHeight(); + p.y += minus ? -height : height; + } + } + return p; + } + /** * Returns the alignment of the specified scroll bar * if and only if the specified scroll bar @@ -256,7 +283,6 @@ public class JBViewport extends JViewport implements ZoomableViewport { } } else { - // NOT SUPPORTED YET viewPosition.x = maxX < 0 ? maxX : Math.max(0, Math.min(maxX, viewPosition.x)); } // If the new viewport size would leave empty space below the view, @@ -278,11 +304,11 @@ public class JBViewport extends JViewport implements ZoomableViewport { if (!(view instanceof TypingTarget)) { if (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER == pane.getHorizontalScrollBarPolicy()) { viewPosition.x = 0; - viewSize.width = actualSize.width; + viewSize.width = extentSize.width; } if (ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER == pane.getVerticalScrollBarPolicy()) { viewPosition.y = 0; - viewSize.height = actualSize.height; + viewSize.height = extentSize.height; } } viewport.setViewPosition(viewPosition); From 87ee55555a9d0ba8d7ab66800803cff5c1951c77 Mon Sep 17 00:00:00 2001 From: Ivan Chirkov Date: Thu, 14 Jan 2016 20:03:07 +0100 Subject: [PATCH 137/825] Per-project custom repositories through required plugins --- .../testSrc/DefaultProjectStoreTest.kt | 2 +- .../DependencyOnPlugin.java | 13 +++++++-- .../impl/CheckRequiredPluginsActivity.java | 29 +++++++++++++++++-- .../impl/DependencyOnPluginState.java | 3 ++ .../ExternalDependenciesConfigurable.java | 8 +++-- .../impl/ExternalDependenciesManagerImpl.java | 2 +- 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt index d259d5f1ac69..a073215dc5a7 100644 --- a/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/DefaultProjectStoreTest.kt @@ -40,7 +40,7 @@ internal class DefaultProjectStoreTest { private val tempDirManager = TemporaryDirectory() - private val requiredPlugins = listOf(DependencyOnPlugin("fake", "0", "1")) + private val requiredPlugins = listOf(DependencyOnPlugin("fake", "0", "1", "alpha")) private val ruleChain = RuleChain( tempDirManager, diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/DependencyOnPlugin.java b/platform/platform-impl/src/com/intellij/externalDependencies/DependencyOnPlugin.java index 037e3477ed05..cf0d475510c5 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/DependencyOnPlugin.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/DependencyOnPlugin.java @@ -31,11 +31,13 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable private final String myPluginId; private final String myMinVersion; private final String myMaxVersion; + private final String myChannel; - public DependencyOnPlugin(@NotNull String pluginId, @Nullable String minVersion, @Nullable String maxVersion) { + public DependencyOnPlugin(@NotNull String pluginId, @Nullable String minVersion, @Nullable String maxVersion, @Nullable String channel) { myPluginId = pluginId; myMinVersion = minVersion; myMaxVersion = maxVersion; + myChannel = channel; } public String getPluginId() { @@ -50,6 +52,10 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable return myMaxVersion; } + public String getChannel() { + return myChannel; + } + @Override public boolean equals(Object o) { @@ -60,12 +66,13 @@ public class DependencyOnPlugin implements ProjectExternalDependency, Comparable return myPluginId.equals(plugin.myPluginId) && Comparing.equal(myMinVersion, plugin.myMinVersion) - && Comparing.equal(myMaxVersion, plugin.myMaxVersion); + && Comparing.equal(myMaxVersion, plugin.myMaxVersion) + && Comparing.equal(myChannel, plugin.myChannel); } @Override public int hashCode() { - return 31 * (31 * myPluginId.hashCode() + Comparing.hashcode(myMinVersion)) + Comparing.hashcode(myMaxVersion); + return 31 * (31 * (31 * myPluginId.hashCode() + Comparing.hashcode(myMinVersion)) + Comparing.hashcode(myMaxVersion)) + Comparing.hashcode(myChannel); } @Override diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java b/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java index 782ec7a2ebef..aa1723fdb94c 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java @@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; +import com.intellij.openapi.updateSettings.impl.UpdateSettings; import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.text.VersionComparatorUtil; @@ -42,6 +43,7 @@ import java.util.Set; */ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware { private static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup("Required Plugins", NotificationDisplayType.BALLOON, true); + public static final String PLUGINS_HOST = "https://plugins.jetbrains.com"; @Override public void runActivity(@NotNull final Project project) { @@ -53,11 +55,20 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware List dependencies = ExternalDependenciesManager.getInstance(project).getDependencies(DependencyOnPlugin.class); if (dependencies.isEmpty()) return; + List customRepositories = UpdateSettings.getInstance().getStoredPluginHosts(); + final List errorMessages = new ArrayList(); + final List missingCustomRepositories = new ArrayList(); final List disabled = new ArrayList(); final List notInstalled = new ArrayList(); for (DependencyOnPlugin dependency : dependencies) { PluginId pluginId = PluginId.getId(dependency.getPluginId()); + String channel = dependency.getChannel(); + String customRepository = getCustomRepository(pluginId, channel); + if (!StringUtil.isEmpty(channel) && customRepositoryNotSpecified(customRepositories, customRepository)) { + errorMessages.add("Custom repository '" + customRepository + "' required for '" + project.getName() + "' project isn't installed."); + missingCustomRepositories.add(customRepository); + } IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId); if (plugin == null) { errorMessages.add("Plugin '" + dependency.getPluginId() + "' required for '" + project.getName() + "' project isn't installed."); @@ -80,7 +91,10 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware } if (!errorMessages.isEmpty()) { - if (!disabled.isEmpty() && notInstalled.isEmpty()) { + if (!missingCustomRepositories.isEmpty()) { + errorMessages.add("
    Add custom repositories and install required plugins"); + } + else if (!disabled.isEmpty() && notInstalled.isEmpty()) { String plugins = disabled.size() == 1 ? disabled.get(0).getName() : "required plugins"; errorMessages.add("Enable " + plugins + ""); } @@ -94,6 +108,9 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware public void hyperlinkUpdate(@NotNull final Notification notification, @NotNull HyperlinkEvent event) { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + if ("addRepositories".equals(event.getDescription())) { + UpdateSettings.getInstance().getStoredPluginHosts().addAll(missingCustomRepositories); + } if ("enable".equals(event.getDescription())) { notification.expire(); for (IdeaPluginDescriptor descriptor : disabled) { @@ -101,7 +118,7 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware } PluginManagerMain.notifyPluginsUpdated(project); } - else { + else if ("install".equals(event.getDescription()) || "addRepositories".equals(event.getDescription())) { Set pluginIds = new HashSet(); for (IdeaPluginDescriptor descriptor : disabled) { pluginIds.add(descriptor.getPluginId().getIdString()); @@ -121,4 +138,12 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware }).notify(project); } } + + private static boolean customRepositoryNotSpecified(List repositories, String customRepository) { + return !repositories.contains(customRepository); + } + + private static String getCustomRepository(PluginId id, String channel) { + return String.format(PLUGINS_HOST + "/plugins/%s/%s", channel, id); + } } diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/impl/DependencyOnPluginState.java b/platform/platform-impl/src/com/intellij/externalDependencies/impl/DependencyOnPluginState.java index aa8b925f8f9e..e15223d6e425 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/impl/DependencyOnPluginState.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/impl/DependencyOnPluginState.java @@ -31,6 +31,7 @@ class DependencyOnPluginState { myId = dependency.getPluginId(); myMinVersion = dependency.getMinVersion(); myMaxVersion = dependency.getMaxVersion(); + myChannel = dependency.getChannel(); } @Attribute("id") @@ -39,4 +40,6 @@ class DependencyOnPluginState { public String myMinVersion; @Attribute("max-version") public String myMaxVersion; + @Attribute("channel") + public String myChannel; } diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesConfigurable.java b/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesConfigurable.java index f16e268a4f4f..64923f7ff141 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesConfigurable.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesConfigurable.java @@ -117,7 +117,7 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable, .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - replaceDependency(new DependencyOnPlugin("", null, null), dependenciesList); + replaceDependency(new DependencyOnPlugin("", null, null, null), dependenciesList); } }) .setEditAction(new AnActionButtonRunnable() { @@ -198,14 +198,17 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable, final JBTextField minVersionField = new JBTextField(StringUtil.notNullize(original.getMinVersion())); final JBTextField maxVersionField = new JBTextField(StringUtil.notNullize(original.getMaxVersion())); + final JBTextField channelField = new JBTextField(StringUtil.notNullize(original.getChannel())); minVersionField.getEmptyText().setText(""); minVersionField.setColumns(10); maxVersionField.getEmptyText().setText(""); maxVersionField.setColumns(10); + channelField.setColumns(10); JPanel panel = FormBuilder.createFormBuilder() .addLabeledComponent("Plugin:", pluginChooser) .addLabeledComponent("Minimum version:", minVersionField) .addLabeledComponent("Maximum version:", maxVersionField) + .addLabeledComponent("Channel:", channelField) .getPanel(); final DialogBuilder dialogBuilder = new DialogBuilder(parent).title("Required Plugin").centerPanel(panel); dialogBuilder.setPreferredFocusComponent(pluginChooser); @@ -218,7 +221,8 @@ public class ExternalDependenciesConfigurable implements SearchableConfigurable, if (dialogBuilder.show() == DialogWrapper.OK_EXIT_CODE) { return new DependencyOnPlugin(((String)pluginChooser.getSelectedItem()), StringUtil.nullize(minVersionField.getText().trim()), - StringUtil.nullize(maxVersionField.getText().trim())); + StringUtil.nullize(maxVersionField.getText().trim()), + StringUtil.nullize(channelField.getText().trim())); } return null; } diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesManagerImpl.java b/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesManagerImpl.java index 38990458cf5c..442cea5fb52e 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/impl/ExternalDependenciesManagerImpl.java @@ -96,7 +96,7 @@ public class ExternalDependenciesManagerImpl extends ExternalDependenciesManager ArrayList oldDependencies = new ArrayList(myDependencies); myDependencies.clear(); for (DependencyOnPluginState dependency : state.myDependencies) { - myDependencies.add(new DependencyOnPlugin(dependency.myId, dependency.myMinVersion, dependency.myMaxVersion)); + myDependencies.add(new DependencyOnPlugin(dependency.myId, dependency.myMinVersion, dependency.myMaxVersion, dependency.myChannel)); } if (!oldDependencies.equals(myDependencies) && !myDependencies.isEmpty()) { StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() { From 9aaca740ee87d5ccb59cb830baf75732353552ba Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 19:47:57 +0100 Subject: [PATCH 138/825] rename to Guice completed --- .../src/com/intellij/ide/customize/PluginGroups.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java index 933290e37af2..d6377526081b 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java @@ -135,7 +135,7 @@ public class PluginGroups { "com.intellij.freemarker", "com.intellij.tapestry", "com.intellij.velocity", - "GuiceyIDEA", + "Guice", "com.intellij.aspectj", "Osmorc" ))); From c79c49396bb3b6dd06eb3c11cc92e2fa6b71465c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 21:12:18 +0100 Subject: [PATCH 139/825] optimization: don't map to get the parameter numbers --- .../src/com/intellij/psi/impl/TypeCorrector.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java index ede55b6f2660..f1cde7acd2ce 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java @@ -204,6 +204,11 @@ class TypeCorrector extends PsiTypeMapper { }); } + @Override + public int getParameterCount() { + return myDelegate.getParameters().length; + } + @NotNull @Override public ClassResolveResult resolveGenerics() { From 6aac85f2f1fd785853fa6ffb9f8491be88156c32 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 14 Jan 2016 21:13:45 +0100 Subject: [PATCH 140/825] optimization: don't try to capture if type was not wildcard parameterized --- .../src/com/intellij/psi/util/PsiUtil.java | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index 5da8840fc108..ebffc3e97842 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -770,25 +770,27 @@ public final class PsiUtil extends PsiUtilCore { } } - Map substitutionMap = null; - for (PsiTypeParameter typeParameter : typeParametersIterable(aClass)) { - final PsiType substituted = substitutor.substitute(typeParameter); - if (substituted instanceof PsiWildcardType) { - if (substitutionMap == null) substitutionMap = new HashMap(substitutor.getSubstitutionMap()); - final PsiCapturedWildcardType capturedWildcard = (PsiCapturedWildcardType)captureSubstitutor.substitute(typeParameter); - LOG.assertTrue(capturedWildcard != null); - final PsiType upperBound = PsiCapturedWildcardType.captureUpperBound(typeParameter, (PsiWildcardType)substituted, captureSubstitutor); - if (upperBound != null) { - capturedWildcard.setUpperBound(upperBound); + if (captureSubstitutor != substitutor) { + Map substitutionMap = null; + for (PsiTypeParameter typeParameter : typeParametersIterable(aClass)) { + final PsiType substituted = substitutor.substitute(typeParameter); + if (substituted instanceof PsiWildcardType) { + if (substitutionMap == null) substitutionMap = new HashMap(substitutor.getSubstitutionMap()); + final PsiCapturedWildcardType capturedWildcard = (PsiCapturedWildcardType)captureSubstitutor.substitute(typeParameter); + LOG.assertTrue(capturedWildcard != null); + final PsiType upperBound = PsiCapturedWildcardType.captureUpperBound(typeParameter, (PsiWildcardType)substituted, captureSubstitutor); + if (upperBound != null) { + capturedWildcard.setUpperBound(upperBound); + } + substitutionMap.put(typeParameter, capturedWildcard); } - substitutionMap.put(typeParameter, capturedWildcard); } - } - if (substitutionMap != null) { - final PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); - final PsiSubstitutor newSubstitutor = factory.createSubstitutor(substitutionMap); - return factory.createType(aClass, newSubstitutor); + if (substitutionMap != null) { + final PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); + final PsiSubstitutor newSubstitutor = factory.createSubstitutor(substitutionMap); + return factory.createType(aClass, newSubstitutor); + } } } } From 6429d76a87bdf34507b82214f6dda6a7296865bb Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Fri, 15 Jan 2016 00:18:21 +0300 Subject: [PATCH 141/825] Tox fix: interpreter should be provided --- python/helpers/pycharm/_jb_tox_runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/helpers/pycharm/_jb_tox_runner.py b/python/helpers/pycharm/_jb_tox_runner.py index 15552622a4f9..26535fbb7094 100644 --- a/python/helpers/pycharm/_jb_tox_runner.py +++ b/python/helpers/pycharm/_jb_tox_runner.py @@ -18,9 +18,9 @@ helpers_dir = str(os.path.split(__file__)[0]) class _Unit2(object): def fix(self, command, dir_to_run): if command[0] == "unit2": - return [os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"] + return ["python", os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"] elif command == ["python", "-m", "unittest", "discover"]: - return [os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + ["true"] + return ["python", os.path.join(helpers_dir, "utrunner.py"), dir_to_run, "true"] return None From bafd756a9e2cd95835e525f253c5c9b092841019 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 14 Jan 2016 23:26:16 +0100 Subject: [PATCH 142/825] IDEA-68160 Find & Replace: preserve case bug --- .../com/intellij/find/FindManagerTest.java | 8 ++++++++ .../intellij/find/impl/FindManagerImpl.java | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 4b0ee7222143..c991b1bd3709 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -633,6 +633,14 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { FindUtil.replace(myProject, myEditor, 0, model); assertEquals("FooBar fooBar", myEditor.getDocument().getText()); + + configureByText(FileTypes.PLAIN_TEXT, "abc1 Abc1 ABC1"); + + model.setStringToFind("ABC1"); + model.setStringToReplace("DEF1"); + + FindUtil.replace(myProject, myEditor, 0, model); + assertEquals("def1 Def1 DEF1", myEditor.getDocument().getText()); } public void testFindWholeWords() { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java index 358af739878d..4904eea45943 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java @@ -864,23 +864,29 @@ public class FindManagerImpl extends FindManager { } boolean isReplacementLowercase = true; + boolean isReplacementUppercase = true; for (int i = 1; i < toReplace.length(); i++) { - isReplacementLowercase = Character.isLowerCase(toReplace.charAt(i)); - if (!isReplacementLowercase) break; + char replacementChar = toReplace.charAt(i); + if (!Character.isLetter(replacementChar)) continue; + isReplacementLowercase &= Character.isLowerCase(replacementChar); + isReplacementUppercase &= Character.isUpperCase(replacementChar); + if (!isReplacementLowercase && !isReplacementUppercase) break; } boolean isTailUpper = true; boolean isTailLower = true; for (int i = 1; i < foundString.length(); i++) { - isTailUpper &= Character.isUpperCase(foundString.charAt(i)); - isTailLower &= Character.isLowerCase(foundString.charAt(i)); + char foundChar = foundString.charAt(i); + if (!Character.isLetter(foundChar)) continue; + isTailUpper &= Character.isUpperCase(foundChar); + isTailLower &= Character.isLowerCase(foundChar); if (!isTailUpper && !isTailLower) break; } - if (isTailUpper && isReplacementLowercase) { + if (isTailUpper && (isReplacementLowercase || isReplacementUppercase)) { buffer.append(StringUtil.toUpperCase(toReplace.substring(1))); } - else if (isTailLower && isReplacementLowercase) { + else if (isTailLower && (isReplacementLowercase || isReplacementUppercase)) { buffer.append(toReplace.substring(1).toLowerCase()); } else { From 8271de805677cce80afc0ebced6b9f872d2437c3 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 15 Jan 2016 09:52:35 +0300 Subject: [PATCH 143/825] OC-13005 script for building of Appcode module cache --- platform/bootstrap/src/com/intellij/idea/Main.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java index b735053bdbd6..0c01ce578785 100644 --- a/platform/bootstrap/src/com/intellij/idea/Main.java +++ b/platform/bootstrap/src/com/intellij/idea/Main.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -134,6 +134,7 @@ public class Main { return Comparing.strEqual(firstArg, "ant") || Comparing.strEqual(firstArg, "duplocate") || Comparing.strEqual(firstArg, "traverseUI") || + Comparing.strEqual(firstArg, "buildAppcodeCache") || (firstArg.length() < 20 && firstArg.endsWith("inspect")); } From 004bdf384bc5e58baa05a3ea43578c28441d55ac Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 15 Jan 2016 12:10:31 +0300 Subject: [PATCH 144/825] replace EditorGutterComponentImpl.START_ICON_AREA_WIDTH w/ Editor's line height --- .../openapi/editor/impl/EditorGutterComponentImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index aaf8db2e7fd3..6b1cc18eddf5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -112,11 +112,11 @@ import java.util.List; */ class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener, DataProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl"); - private static final int START_ICON_AREA_WIDTH = JBUI.scale(15); private static final int FREE_PAINTERS_LEFT_AREA_WIDTH = JBUI.scale(8); private static final int FREE_PAINTERS_RIGHT_AREA_WIDTH = JBUI.scale(5); private static final int GAP_BETWEEN_ICONS = JBUI.scale(3); private static final int GAP_BETWEEN_AREAS = JBUI.scale(5); + private static final int GAP_BETWEEN_ANNOTATIONS = JBUI.scale(5); private static final TooltipGroup GUTTER_TOOLTIP_GROUP = new TooltipGroup("GUTTER_TOOLTIP_GROUP", 0); public static final TIntFunction ID = new TIntFunction() { @Override @@ -127,7 +127,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private final EditorImpl myEditor; private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy; - private int myIconsAreaWidth = START_ICON_AREA_WIDTH; + private int myIconsAreaWidth = 0; private int myLineNumberAreaWidth = 0; private int myAdditionalLineNumberAreaWidth = 0; private FoldRegion myActiveFoldRegion; @@ -136,7 +136,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private TIntArrayList myTextAnnotationGutterSizes = new TIntArrayList(); private ArrayList myTextAnnotationGutters = new ArrayList(); private final Map myProviderToListener = new HashMap(); - private static final int GAP_BETWEEN_ANNOTATIONS = 5; private String myLastGutterToolTip = null; @NotNull private TIntFunction myLineNumberConvertor; @Nullable private TIntFunction myAdditionalLineNumberConvertor; @@ -759,7 +758,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } }); - myIconsAreaWidth = START_ICON_AREA_WIDTH; + myIconsAreaWidth = myEditor.getLineHeight(); myLineToGutterRenderers.forEachValue(new TObjectProcedure>() { @Override From 8ad0c1bc725baa42279347409063316f62c23c00 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Fri, 15 Jan 2016 13:37:36 +0300 Subject: [PATCH 145/825] IDEA-149907 Get rid of duplication between python\edu\build\idea.nsi and build\conf\nsis\idea.nsi --- build/conf/nsis/customInstallActions.nsi | 38 + build/conf/nsis/idea.nsi | 61 +- python/edu/build/customInstallActions.nsi | 188 +++ python/edu/build/idea.nsi | 1328 --------------------- python/edu/build/pycharm_edu_build.gant | 6 +- 5 files changed, 241 insertions(+), 1380 deletions(-) create mode 100644 build/conf/nsis/customInstallActions.nsi create mode 100644 python/edu/build/customInstallActions.nsi delete mode 100644 python/edu/build/idea.nsi diff --git a/build/conf/nsis/customInstallActions.nsi b/build/conf/nsis/customInstallActions.nsi new file mode 100644 index 000000000000..a208f5c07b82 --- /dev/null +++ b/build/conf/nsis/customInstallActions.nsi @@ -0,0 +1,38 @@ +!define INSTALL_OPTION_ELEMENTS 4 + + +Function customInstallActions + DetailPrint "There are no custom install actions." +FunctionEnd + + +Function ConfirmDesktopShortcut + !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 1" "Text" "$(create_desktop_shortcut)" + call winVersion + ${If} $0 == "1" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Type" "Label" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "" + ${Else} + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "$(create_quick_launch_shortcut)" + ${EndIf} + StrCmp "${ASSOCIATION}" "NoAssociation" skip_association + StrCpy $R0 3 + push "${ASSOCIATION}" +loop: + call SplitStr + Pop $0 + StrCmp $0 "" done + IntOp $R0 $R0 + 1 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" + goto loop +skip_association: + StrCpy $R0 2 + call winVersion + ${If} $0 == "1" + IntOp $R0 $R0 - 1 + ${EndIf} +done: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" + !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini" +FunctionEnd diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi index 16cc8904799b..04e2f16f7088 100644 --- a/build/conf/nsis/idea.nsi +++ b/build/conf/nsis/idea.nsi @@ -12,7 +12,6 @@ ; thus ${PRODUCT_WITH_VER} is used for uninstall registry information !define PRODUCT_REG_VER "${MUI_PRODUCT}\${VER_BUILD}" -!define INSTALL_OPTION_ELEMENTS 4 Name "${MUI_PRODUCT}" SetCompressor lzma ; http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista @@ -28,6 +27,8 @@ RequestExecutionLevel user !include StrFunc.nsh !include LogicLib.nsh +!include "customInstallActions.nsi" + ${UnStrStr} ${UnStrLoc} ${UnStrRep} @@ -686,9 +687,9 @@ FunctionEnd Function ProductRegistration StrCmp "${PRODUCT_WITH_VER}" "${MUI_PRODUCT} ${VER_BUILD}" eapInfo releaseInfo -eapInfo: +eapInfo: StrCpy $3 "${PRODUCT_WITH_VER}(EAP)" - goto createRegistration + goto createRegistration releaseInfo: StrCpy $3 "${PRODUCT_WITH_VER}" createRegistration: @@ -742,31 +743,34 @@ Section "IDEA Files" CopyIdeaFiles skip_desktop_shortcut: ; OS is not win7 Call winVersion - ${If} $0 == "0" + ${If} $0 == "0" !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 2" "State" StrCmp $R2 1 "" skip_quicklaunch_shortcut CreateShortCut "$QUICKLAUNCH\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL - ${EndIf} + ${EndIf} skip_quicklaunch_shortcut: !insertmacro INSTALLOPTIONS_READ $R1 "Desktop.ini" "Settings" "NumFields" IntCmp $R1 ${INSTALL_OPTION_ELEMENTS} do_association done do_association do_association: - StrCpy $R2 ${INSTALL_OPTION_ELEMENTS} + StrCpy $R2 ${INSTALL_OPTION_ELEMENTS} get_user_choice: !insertmacro INSTALLOPTIONS_READ $R3 "Desktop.ini" "Field $R2" "State" StrCmp $R3 1 "" next_association !insertmacro INSTALLOPTIONS_READ $R4 "Desktop.ini" "Field $R2" "Text" call ProductAssociation -next_association: +next_association: IntOp $R2 $R2 + 1 IntCmp $R1 $R2 get_user_choice done get_user_choice done: + + Call customInstallActions + ;registration application to be presented in Open With list call ProductRegistration ;reset icon cache - System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' + System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' !insertmacro MUI_STARTMENU_WRITE_BEGIN Application ; $STARTMENU_FOLDER stores name of IDEA folder in Start Menu, ; save it name in the "MenuFolder" RegValue @@ -864,47 +868,6 @@ skip_properties: ${EndIf} SectionEnd -;------------------------------------------------------------------------------ -; Descriptions of sections -;------------------------------------------------------------------------------ -; LangString DESC_CopyRuntime ${LANG_ENGLISH} "${MUI_PRODUCT} files" - -;------------------------------------------------------------------------------ -; custom install pages -;------------------------------------------------------------------------------ - -Function ConfirmDesktopShortcut - !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 1" "Text" "$(create_desktop_shortcut)" - call winVersion - ${If} $0 == "1" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Type" "Label" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "" - ${Else} - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "$(create_quick_launch_shortcut)" - ${EndIf} - StrCmp "${ASSOCIATION}" "NoAssociation" skip_association - StrCpy $R0 3 - push "${ASSOCIATION}" -loop: - call SplitStr - Pop $0 - StrCmp $0 "" done - IntOp $R0 $R0 + 1 - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" - goto loop -skip_association: - StrCpy $R0 2 - call winVersion - ${If} $0 == "1" - IntOp $R0 $R0 - 1 - ${EndIf} -done: - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" - !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini" -FunctionEnd - - ;------------------------------------------------------------------------------ ; custom uninstall functions ;------------------------------------------------------------------------------ diff --git a/python/edu/build/customInstallActions.nsi b/python/edu/build/customInstallActions.nsi new file mode 100644 index 000000000000..ed293098c921 --- /dev/null +++ b/python/edu/build/customInstallActions.nsi @@ -0,0 +1,188 @@ +!include "TextFunc.nsh" +!include x64.nsh + +!define INSTALL_OPTION_ELEMENTS 7 +!define PYTHON_VERSIONS 4 + +${StrTok} + +Function customInstallActions + ${LineSum} "$TEMP\python.txt" $R0 + IfErrors cantOpenFile + StrCmp $R0 ${PYTHON_VERSIONS} getPythonInfo ;info about 2 and 3 version of python +cantOpenFile: + MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is invalid. Python will not be downloaded." + goto skip_python_download +getPythonInfo: + Call getPythonInfo + StrCmp $0 "Error" skip_python_download + !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 4" "State" + StrCpy $R8 "$0.msi" + StrCpy $R9 "/quiet /qn /norestart" + StrCmp $R2 1 "" python3 + StrCpy $R2 $0 + StrCpy $R3 $1 + goto check_python +python3: + !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 5" "State" + StrCpy $R8 "$R0.exe" + StrCpy $R9 "InstallAllUsers=1 /quiet" + StrCmp $R2 1 "" skip_python_download + StrCpy $R2 $R0 + StrCpy $R3 $R1 +check_python: + ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2\InstallPath" "" + StrCmp $1 "" installation_for_all_users + goto verefy_python_launcher +installation_for_all_users: + ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2\InstallPath" "" + StrCmp $1 "" get_python +verefy_python_launcher: + IfFileExists $1python.exe python_exists get_python +get_python: + CreateDirectory "$INSTDIR\python" + inetc::get "$R3" "$INSTDIR\python\python_$R8" + Pop $0 + ${If} $0 == "OK" + ExecCmd::exec '"$INSTDIR\python\python_$R8" $R9' + ${Else} + MessageBox MB_OK|MB_ICONEXCLAMATION "The download is failed" + ${EndIf} +python_exists: +skip_python_download: +FunctionEnd + + +Function updatePythonControls + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Text" "Python $R2 (installed)" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Flags" "DISABLED" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "State" "0" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R5 "Type" "checkbox" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R5 "State" "0" +FunctionEnd + + +Function ConfirmDesktopShortcut + !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 1" "Text" "$(create_desktop_shortcut)" + call winVersion + ${If} $0 == "1" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Type" "Label" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "" + ${Else} + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "$(create_quick_launch_shortcut)" + ${EndIf} + IfFileExists "$TEMP\python.txt" deletePythonFileInfo getPythonFileInfo +deletePythonFileInfo: + Delete "$TEMP\python.txt" +getPythonFileInfo: + inetc::get "https://www.jetbrains.com/updates/python.txt" "$TEMP\python.txt" + ${LineSum} "$TEMP\python.txt" $R0 + IfErrors cantOpenFile + StrCmp $R0 ${PYTHON_VERSIONS} getPythonInfo +cantOpenFile: + MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is not exist. Python will not be downloaded." +removePythonChoice: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Flags" "DISABLED" + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 5" "Flags" "DISABLED" + goto association +getPythonInfo: + Call getPythonInfo + StrCmp $0 "Error" removePythonChoice + ;check if pythons are already installed + StrCpy $R2 $0 + Call searchPython + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Text" "Python $0" + StrCmp $R2 "Absent" checkPython3 + StrCpy $R2 $0 + StrCpy $R4 "Field 4" + StrCpy $R5 "Field 5" + Call updatePythonControls +checkPython3: + StrCpy $R2 $R0 + Call searchPython + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 5" "Text" "Python $R0" + StrCmp $R2 "Absent" association + StrCpy $R2 $R0 + StrCpy $R4 "Field 5" + StrCpy $R5 "Field 4" + Call updatePythonControls +association: + StrCpy $R0 6 + StrCmp "${ASSOCIATION}" "NoAssociation" skip_association + push "${ASSOCIATION}" +loop: + call SplitStr + Pop $0 + StrCmp $0 "" done + IntOp $R0 $R0 + 1 + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" + goto loop +skip_association: + call winVersion + ${If} $0 == "1" + IntOp $R0 $R0 - 1 + ${EndIf} +done: + !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" + !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini" +FunctionEnd + + +Function getPythonInfo + ClearErrors + FileOpen $3 $Temp\python.txt r + IfErrors cantOpenFile ;file can not be open. + ${If} ${RunningX64} + goto getPythonInfo + ${Else} + FileRead $3 $4 + FileRead $3 $4 + ${EndIf} + ;get python2 info +getPythonInfo: + FileRead $3 $4 + ${StrTok} $0 $4 " " "1" "1" + ${StrTok} $1 $4 " " "2" "1" + ;get python3 info + FileRead $3 $4 + ${StrTok} $R0 $4 " " "1" "1" + ${StrTok} $R1 $4 " " "2" "1" + goto done +cantOpenFile: + MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is not exist. Python will not be downloaded." + StrCpy $0 "Error" +done: +FunctionEnd + + +Function searchPython + ;$R2 - version of python + ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2\InstallPath" "" + StrCmp $1 "" CU_32bit verifyPythonLauncher +CU_32bit: + ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2-32\InstallPath" "" + StrCmp $1 "" CU_64bit verifyPythonLauncher +CU_64bit: + ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2-64\InstallPath" "" + StrCmp $1 "" installationForAllUsers verifyPythonLauncher + +installationForAllUsers: + ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2\InstallPath" "" + StrCmp $1 "" LM_32bit verifyPythonLauncher +LM_32bit: + ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2-32\InstallPath" "" + StrCmp $1 "" LM_64bit verifyPythonLauncher +LM_64bit: + ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2-64\InstallPath" "" + StrCmp $1 "" pythonAbsent +verifyPythonLauncher: + IfFileExists $1python.exe pythonExists pythonAbsent +pythonAbsent: + StrCpy $R2 "Absent" + goto done +pythonExists: + StrCpy $R2 "Exists" +done: +FunctionEnd diff --git a/python/edu/build/idea.nsi b/python/edu/build/idea.nsi deleted file mode 100644 index 0a3173611704..000000000000 --- a/python/edu/build/idea.nsi +++ /dev/null @@ -1,1328 +0,0 @@ -!verbose 2 - -!include "paths.nsi" -!include "strings.nsi" -!include "Registry.nsi" -!include "version.nsi" -!include x64.nsh - -; Product with version (IntelliJ IDEA #xxxx). - -; Used in registry to put each build info into the separate subkey -; Add&Remove programs doesn't understand subkeys in the Uninstall key, -; thus ${PRODUCT_WITH_VER} is used for uninstall registry information -!define PRODUCT_REG_VER "${MUI_PRODUCT}\${VER_BUILD}" - -!define INSTALL_OPTION_ELEMENTS 7 -!define PYTHON_VERSIONS 4 -Name "${MUI_PRODUCT}" -SetCompressor lzma -; http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista -RequestExecutionLevel user - -;------------------------------------------------------------------------------ -; include "Modern User Interface" -;------------------------------------------------------------------------------ -!include "MUI2.nsh" -!include "FileFunc.nsh" -!include "TextFunc.nsh" -!include UAC.nsh -!include "InstallOptions.nsh" -!include StrFunc.nsh -!include LogicLib.nsh - -${UnStrStr} -${UnStrLoc} -${UnStrRep} -${StrRep} -${StrTok} - -ReserveFile "desktop.ini" -ReserveFile "DeleteSettings.ini" -ReserveFile '${NSISDIR}\Plugins\InstallOptions.dll' -!insertmacro MUI_RESERVEFILE_LANGDLL - -!define MUI_ICON "${IMAGES_LOCATION}\${PRODUCT_ICON_FILE}" -!define MUI_UNICON "${IMAGES_LOCATION}\${PRODUCT_UNINST_ICON_FILE}" - -!define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_HEADER_FILE}" -!define MUI_WELCOMEFINISHPAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_LOGO_FILE}" - -;------------------------------------------------------------------------------ -; on GUI initialization installer checks whether IDEA is already installed -;------------------------------------------------------------------------------ - -!define MUI_CUSTOMFUNCTION_GUIINIT GUIInit - -Var baseRegKey -Var IS_UPGRADE_60 - -!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" -!define MUI_LANGDLL_REGISTRY_KEY "Software\JetBrains\${MUI_PRODUCT}\${VER_BUILD}\" -!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" - -;check if the window is win7 or newer -!macro INST_UNINST_SWITCH un - Function ${un}winVersion - ;The platform is returned into $0, minor version into $1. - ;Windows 7 is equals values of 6 as platform and 1 as minor version. - ;Windows 8 is equals values of 6 as platform and 2 as minor version. - nsisos::osversion - ${If} $0 == "6" - ${AndIf} $1 >= "1" - StrCpy $0 "1" - ${else} - StrCpy $0 "0" - ${EndIf} - FunctionEnd - - Function ${un}compareFileInstallationTime - StrCpy $9 "" - get_first_file: - Pop $7 - IfFileExists "$7" get_next_file 0 - StrCmp $7 "Complete" complete get_first_file - get_next_file: - Pop $8 - StrCmp $8 "Complete" 0 +2 - ; check if there is only one property file - StrCmp $9 "no changes" complete different - IfFileExists "$8" 0 get_next_file - ClearErrors - ${GetTime} "$7" "M" $0 $1 $2 $3 $4 $5 $6 - ${GetTime} "$8" "M" $R0 $R1 $R2 $R3 $R4 $R5 $R6 - StrCmp $0 $R0 0 different - StrCmp $1 $R1 0 different - StrCmp $2 $R2 0 different - StrCmp $4 $R4 0 different - StrCmp $5 $R5 0 different - StrCmp $6 $R6 0 different - StrCpy $9 "no changes" - Goto get_next_file - different: - StrCpy $9 "Modified" - complete: -FunctionEnd - -Function ${un}SplitStr -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 ! - ${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 - 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` - - !macro InstDirStateCall _PATH _RESULT - Push `${_PATH}` - Call InstDirState - Pop ${_RESULT} - !macroend - - 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 -FunctionEnd - -Function SplitFirstStrPart - Exch $R0 - Exch - Exch $R1 - Push $R2 - Push $R3 - 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: - StrCpy $R1 "" - Goto exit2 - 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: - Pop $R3 - Pop $R2 - Exch $R1 ;rest - Exch - Exch $R0 ;first -FunctionEnd - -Function VersionSplit - !define VersionSplit `!insertmacro VersionSplitCall` - - !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 -FunctionEnd - -Function OnDirectoryPageLeave - StrCpy $IS_UPGRADE_60 "0" - ${InstDirState} "$INSTDIR" $R0 - IntCmp $R0 1 check_build skip_abort skip_abort -check_build: - FileOpen $R1 "$INSTDIR\build.txt" "r" - IfErrors do_abort - FileRead $R1 $R2 - FileClose $R1 - IfErrors do_abort - ${VersionSplit} ${MIN_UPGRADE_BUILD} $R3 $R4 $R5 - ${VersionSplit} ${MAX_UPGRADE_BUILD} $R6 $R7 $R8 - ${VersionSplit} $R2 $R9 $R2 $R0 - StrCmp $R9 $R3 0 do_abort - IntCmp $R2 $R4 0 do_abort - IntCmp $R0 $R5 do_accept do_abort - - StrCmp $R9 $R6 0 do_abort - IntCmp $R2 $R7 0 0 do_abort - IntCmp $R0 $R8 do_abort do_accept do_abort - -do_accept: - StrCpy $IS_UPGRADE_60 "1" - FileClose $R1 - Goto skip_abort - -do_abort: - ;check - ; - if there are no files into $INSTDIR (recursively) just excepted property files - ; - if property files have the same installation time. - StrCpy $9 "$INSTDIR" - Call instDirEmpty - StrCmp $9 "not empty" abort 0 - Push "Complete" - Push "$INSTDIR\bin\${PRODUCT_EXE_FILE}.vmoptions" - Push "$INSTDIR\bin\idea.properties" - ${StrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions" - Push "$INSTDIR\bin\$0" - Call compareFileInstallationTime - StrCmp $9 "Modified" abort skip_abort -abort: - MessageBox MB_OK|MB_ICONEXCLAMATION "$(empty_or_upgrade_folder)" - Abort -skip_abort: -FunctionEnd - - -;check if there are no files into $INSTDIR recursively just except property files. -Function instDirEmpty - Push $0 - Push $1 - Push $2 - ClearErrors - FindFirst $1 $2 "$9\*.*" -nextElemement: - ;is the element a folder? - StrCmp $2 "." getNextElement - StrCmp $2 ".." getNextElement - IfFileExists "$9\$2\*.*" 0 nextFile - Push $9 - StrCpy "$9" "$9\$2" - Call instDirEmpty - StrCmp $9 "not empty" done 0 - Pop $9 - Goto getNextElement -nextFile: - ;is it the file property? - ${If} $2 != "idea.properties" - ${AndIf} $2 != "${PRODUCT_EXE_FILE}.vmoptions" - ${StrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions" - ${AndIf} $2 != $0 - StrCpy $9 "not empty" - Goto done - ${EndIf} -getNextElement: - FindNext $1 $2 - IfErrors 0 nextElemement -done: - FindClose $1 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - - -;------------------------------------------------------------------------------ -; Variables -;------------------------------------------------------------------------------ - Var STARTMENU_FOLDER - Var config_path - Var system_path - -;------------------------------------------------------------------------------ -; configuration -;------------------------------------------------------------------------------ - -!insertmacro MUI_PAGE_WELCOME - -Page custom uninstallOldVersionDialog -Var productDir -Var control_fields -Var max_fields - -!ifdef LICENSE_FILE -!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" -!endif - -!define MUI_PAGE_CUSTOMFUNCTION_LEAVE OnDirectoryPageLeave -!insertmacro MUI_PAGE_DIRECTORY - -Page custom ConfirmDesktopShortcut - !define MUI_STARTMENUPAGE_NODISABLE - !define MUI_STARTMENUPAGE_DEFAULTFOLDER "JetBrains" - -!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER -!define MUI_ABORTWARNING -!insertmacro MUI_PAGE_INSTFILES -!define MUI_FINISHPAGE_RUN_NOTCHECKED -!define MUI_FINISHPAGE_RUN -!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun -!insertmacro MUI_PAGE_FINISH - -!define MUI_UNINSTALLER -;!insertmacro MUI_UNPAGE_CONFIRM -UninstPage custom un.ConfirmDeleteSettings -!insertmacro MUI_UNPAGE_INSTFILES - -OutFile "${OUT_DIR}\${OUT_FILE}.exe" - -InstallDir "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}" -!define MUI_BRANDINGTEXT " " -BrandingText " " - -Function PageFinishRun -!insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" -FunctionEnd - -;------------------------------------------------------------------------------ -; languages -;------------------------------------------------------------------------------ -!insertmacro MUI_LANGUAGE "English" -;!insertmacro MUI_LANGUAGE "Japanese" -!include "idea_en.nsi" -;!include "idea_jp.nsi" - -!ifdef LICENSE_FILE -LicenseLangString myLicenseData ${LANG_ENGLISH} "${LICENSE_FILE}.txt" -LicenseLangString myLicenseData ${LANG_JAPANESE} "${LICENSE_FILE}.txt" -!endif - -Function .onInit - 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: - StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}" - SetShellVarContext all - StrCpy $baseRegKey "HKLM" -UAC_Done: -; !insertmacro MUI_LANGDLL_DISPLAY -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 -check_version: - StrCpy $2 "Build" - Call OMReadRegStr - StrCmp $3 "" Done - IntCmpU $3 ${VER_BUILD} ask_Install_Over Done ask_Install_Over -ask_Install_Over: - MessageBox MB_YESNO|MB_ICONQUESTION "$(current_version_already_installed)" IDYES continue IDNO exit_installer -exit_installer: - Abort -continue: - StrCpy $0 "complete" -Done: -FunctionEnd - - -Function searchCurrentVersion - ; search current version of IDEA - StrCpy $0 "HKCU" - Call checkVersion - StrCmp $0 "complete" Done - StrCpy $0 "HKLM" - Call checkVersion -Done: -FunctionEnd - - -Function uninstallOldVersion - ;check if the uninstalled application is running -remove_previous_installation: - ;prepare a copy of launcher - CopyFiles "$3\bin\${PRODUCT_EXE_FILE}" "$3\bin\${PRODUCT_EXE_FILE}_copy" - ClearErrors - ;copy launcher to itself - CopyFiles "$3\bin\${PRODUCT_EXE_FILE}_copy" "$3\bin\${PRODUCT_EXE_FILE}" - Delete "$3\bin\${PRODUCT_EXE_FILE}_copy" - IfErrors 0 +3 - MessageBox MB_OKCANCEL|MB_ICONQUESTION|MB_TOPMOST "$(application_running)" IDOK remove_previous_installation IDCANCEL complete - goto complete - ; uninstallation mode - !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 2" "State" - ${If} $9 == "1" - ExecWait '"$3\bin\Uninstall.exe" /S' - ${else} - ExecWait '"$3\bin\Uninstall.exe" _?=$3\bin' - ${EndIf} - IfFileExists $3\bin\${PRODUCT_EXE_FILE} 0 uninstall - goto complete -uninstall: - ;previous installation has been removed - ;customer decided to keep properties? - IfFileExists $3\bin\idea.properties saveProperties fullRemove -saveProperties: - Delete "$3\bin\Uninstall.exe" - Goto complete -fullRemove: - RmDir /r "$3" -complete: -FunctionEnd - - -Function checkProductVersion -;$8 - count of already added fields to the dialog -;$3 - an old version which will be checked if the one should be added too -StrCpy $7 $control_fields -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} - Goto loop - ${EndIf} -finish: -FunctionEnd - - -Function uninstallOldVersionDialog - StrCpy $control_fields 2 - StrCpy $max_fields 13 - StrCpy $0 "HKLM" - StrCpy $4 0 - ReserveFile "UninstallOldVersions.ini" - !insertmacro INSTALLOPTIONS_EXTRACT "UninstallOldVersions.ini" - StrCpy $8 $control_fields - -get_installation_info: - StrCpy $1 "Software\${MANUFACTURER}\${MUI_PRODUCT}" - StrCpy $5 "\bin\${PRODUCT_EXE_FILE}" - StrCpy $2 "" - Call getInstallationPath - StrCmp $3 "complete" next_registry_root - ;check if the old installation could be uninstalled - IfFileExists $3\bin\Uninstall.exe uninstall_dialog get_next_key -uninstall_dialog: - Call checkProductVersion - ${If} $6 != "duplicated" - IntOp $8 $8 + 1 - !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $8" "Text" "$3" - StrCmp $8 $max_fields complete - ${EndIf} -get_next_key: - IntOp $4 $4 + 1 ;to check next record from registry - goto get_installation_info - -next_registry_root: -${If} $0 == "HKLM" - StrCpy $0 "HKCU" - StrCpy $4 0 - Goto get_installation_info -${EndIf} -complete: -!insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Settings" "NumFields" "$8" -${If} $8 > $control_fields - ;$2 used in prompt text - StrCpy $2 "s" - StrCpy $7 $control_fields - IntOp $7 $7 + 1 - StrCmp $8 $7 0 +2 - StrCpy $2 "" - !insertmacro MUI_HEADER_TEXT "$(uninstall_previous_installations_title)" "$(uninstall_previous_installations)" - !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 1" "Text" "$(uninstall_previous_installations_prompt)" - !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 3" "Flags" "FOCUS" - !insertmacro INSTALLOPTIONS_DISPLAY "UninstallOldVersions.ini" - ;uninstall chosen installation(s) - - ;no disabled controls. StrCmp $2 "OK" loop finish -loop: - !insertmacro INSTALLOPTIONS_READ $0 "UninstallOldVersions.ini" "Field $8" "State" - !insertmacro INSTALLOPTIONS_READ $3 "UninstallOldVersions.ini" "Field $8" "Text" - ${If} $0 == "1" - Call uninstallOldVersion - ${EndIf} - IntOp $8 $8 - 1 - StrCmp $8 $control_fields finish loop - ${EndIf} -finish: -FunctionEnd - - -Function getInstallationPath - Push $1 - Push $2 - Push $5 -loop: - Call OMEnumRegKey - StrCmp $3 "" 0 getPath - StrCpy $3 "complete" - goto done -getPath: - Push $1 - StrCpy $1 "$1\$3" - Call OMReadRegStr - Pop $1 - IfFileExists $3$5 done 0 - IntOp $4 $4 + 1 - goto loop -done: - Pop $5 - Pop $2 - Pop $1 -FunctionEnd - - -Function GUIInit - Push $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - -; is the current version of IDEA installed? - Call searchCurrentVersion - -; search old versions of IDEA - StrCpy $4 0 - StrCpy $0 "HKCU" - StrCpy $1 "Software\${MANUFACTURER}\${MUI_PRODUCT}" - StrCpy $5 "\bin\${PRODUCT_EXE_FILE}" - StrCpy $2 "" - Call getInstallationPath - StrCmp $3 "complete" all_users - IfFileExists $3\bin\${PRODUCT_EXE_FILE} old_version_located all_users -all_users: - StrCpy $4 0 - StrCpy $0 "HKLM" - Call getInstallationPath - StrCmp $3 "complete" success - IfFileExists $3\bin\${PRODUCT_EXE_FILE} 0 success -old_version_located: -; MessageBox MB_YESNO|MB_ICONQUESTION "$(previous_installations)" IDYES uninstall IDNO success -;uninstall: -; Call uninstallOldVersions - -success: - IntCmp ${SHOULD_SET_DEFAULT_INSTDIR} 0 end_enum_versions_hklm - StrCpy $3 "0" # latest build number - StrCpy $0 "0" # registry key index - -enum_versions_hkcu: - EnumRegKey $1 "HKCU" "Software\${MANUFACTURER}\${MUI_PRODUCT}" $0 - StrCmp $1 "" end_enum_versions_hkcu - IntCmp $1 $3 continue_enum_versions_hkcu continue_enum_versions_hkcu - StrCpy $3 $1 - ReadRegStr $INSTDIR "HKCU" "Software\${MANUFACTURER}\${MUI_PRODUCT}\$3" "" - -continue_enum_versions_hkcu: - IntOp $0 $0 + 1 - Goto enum_versions_hkcu - -end_enum_versions_hkcu: - - StrCpy $0 "0" # registry key index - -enum_versions_hklm: - EnumRegKey $1 "HKLM" "Software\${MANUFACTURER}\${MUI_PRODUCT}" $0 - StrCmp $1 "" end_enum_versions_hklm - IntCmp $1 $3 continue_enum_versions_hklm continue_enum_versions_hklm - StrCpy $3 $1 - ReadRegStr $INSTDIR "HKLM" "Software\${MANUFACTURER}\${MUI_PRODUCT}\$3" "" - -continue_enum_versions_hklm: - IntOp $0 $0 + 1 - Goto enum_versions_hklm - -end_enum_versions_hklm: - - StrCmp $INSTDIR "" 0 skip_default_instdir - StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}" -skip_default_instdir: - - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 - !insertmacro INSTALLOPTIONS_EXTRACT "Desktop.ini" - -FunctionEnd - -Function ProductRegistration - StrCmp "${PRODUCT_WITH_VER}" "${MUI_PRODUCT} ${VER_BUILD}" eapInfo releaseInfo -eapInfo: - StrCpy $3 "${PRODUCT_WITH_VER}(EAP)" - goto createRegistration -releaseInfo: - StrCpy $3 "${PRODUCT_WITH_VER}" -createRegistration: - StrCpy $0 "HKCR" - StrCpy $1 "Applications\${PRODUCT_EXE_FILE}\shell\open" - StrCpy $2 "FriendlyAppName" - call OMWriteRegStr - StrCpy $1 "Applications\${PRODUCT_EXE_FILE}\shell\open\command" - StrCpy $2 "" - StrCpy $3 '$INSTDIR\bin\${PRODUCT_EXE_FILE} "%1"' - call OMWriteRegStr -FunctionEnd - -Function ProductAssociation - ; 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 -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" "" "$INSTDIR\bin\${PRODUCT_EXE_FILE},0" -command_exists: - WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell\open\command" "" \ - '$INSTDIR\bin\${PRODUCT_EXE_FILE} "%1"' -FunctionEnd - -Function getPythonInfo - ClearErrors - FileOpen $3 $Temp\python.txt r - IfErrors cantOpenFile ;file can not be open. - ${If} ${RunningX64} - goto getPythonInfo - ${Else} - FileRead $3 $4 - FileRead $3 $4 - ${EndIf} - ;get python2 info -getPythonInfo: - FileRead $3 $4 - ${StrTok} $0 $4 " " "1" "1" - ${StrTok} $1 $4 " " "2" "1" - ;get python3 info - FileRead $3 $4 - ${StrTok} $R0 $4 " " "1" "1" - ${StrTok} $R1 $4 " " "2" "1" - goto done -cantOpenFile: - MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is not exist. Python will not be downloaded." - StrCpy $0 "Error" -done: -FunctionEnd - -Function searchPython - ;$R2 - version of python - ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2\InstallPath" "" - StrCmp $1 "" CU_32bit verifyPythonLauncher -CU_32bit: - ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2-32\InstallPath" "" - StrCmp $1 "" CU_64bit verifyPythonLauncher -CU_64bit: - ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2-64\InstallPath" "" - StrCmp $1 "" installationForAllUsers verifyPythonLauncher - -installationForAllUsers: - ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2\InstallPath" "" - StrCmp $1 "" LM_32bit verifyPythonLauncher -LM_32bit: - ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2-32\InstallPath" "" - StrCmp $1 "" LM_64bit verifyPythonLauncher -LM_64bit: - ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2-64\InstallPath" "" - StrCmp $1 "" pythonAbsent -verifyPythonLauncher: - IfFileExists $1python.exe pythonExists pythonAbsent -pythonAbsent: - StrCpy $R2 "Absent" - goto done -pythonExists: - StrCpy $R2 "Exists" -done: -FunctionEnd - -;------------------------------------------------------------------------------ -; Installer sections -;------------------------------------------------------------------------------ -Section "IDEA Files" CopyIdeaFiles - ${LineSum} "$TEMP\python.txt" $R0 - IfErrors cantOpenFile - StrCmp $R0 ${PYTHON_VERSIONS} getPythonInfo ;info about 2 and 3 version of python -cantOpenFile: - MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is invalid. Python will not be downloaded." - goto skip_python_download -getPythonInfo: - Call getPythonInfo - StrCmp $0 "Error" skip_python_download - !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 4" "State" - StrCpy $R8 "$0.msi" - StrCpy $R9 "/quiet /qn /norestart" - StrCmp $R2 1 "" python3 - StrCpy $R2 $0 - StrCpy $R3 $1 - goto check_python -python3: - !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 5" "State" - StrCpy $R8 "$R0.exe" - StrCpy $R9 "InstallAllUsers=1 /quiet" - StrCmp $R2 1 "" skip_python_download - StrCpy $R2 $R0 - StrCpy $R3 $R1 -check_python: - ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2\InstallPath" "" - StrCmp $1 "" installation_for_all_users - goto verefy_python_launcher -installation_for_all_users: - ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2\InstallPath" "" - StrCmp $1 "" get_python -verefy_python_launcher: - IfFileExists $1python.exe python_exists get_python -get_python: - CreateDirectory "$INSTDIR\python" - inetc::get "$R3" "$INSTDIR\python\python_$R8" - Pop $0 - ${If} $0 == "OK" - ExecCmd::exec '"$INSTDIR\python\python_$R8" $R9' - ${Else} - MessageBox MB_OK|MB_ICONEXCLAMATION "The download is failed" - ${EndIf} -python_exists: -skip_python_download: -; create shortcuts - !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 1" "State" - StrCmp $R2 1 "" skip_desktop_shortcut - CreateShortCut "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ - "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL - -skip_desktop_shortcut: - ; OS is not win7 - Call winVersion - ${If} $0 == "0" - !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 2" "State" - StrCmp $R2 1 "" skip_quicklaunch_shortcut - CreateShortCut "$QUICKLAUNCH\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ - "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL - ${EndIf} -skip_quicklaunch_shortcut: - - !insertmacro INSTALLOPTIONS_READ $R1 "Desktop.ini" "Settings" "NumFields" - IntCmp $R1 ${INSTALL_OPTION_ELEMENTS} do_association done do_association -do_association: - StrCpy $R2 ${INSTALL_OPTION_ELEMENTS} -get_user_choice: - !insertmacro INSTALLOPTIONS_READ $R3 "Desktop.ini" "Field $R2" "State" - StrCmp $R3 1 "" next_association - !insertmacro INSTALLOPTIONS_READ $R4 "Desktop.ini" "Field $R2" "Text" - call ProductAssociation -next_association: - IntOp $R2 $R2 + 1 - IntCmp $R1 $R2 get_user_choice done get_user_choice - -done: - ;registration application to be presented in Open With list - call ProductRegistration - ;reset icon cache - System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' -!insertmacro MUI_STARTMENU_WRITE_BEGIN Application -; $STARTMENU_FOLDER stores name of IDEA folder in Start Menu, -; save it name in the "MenuFolder" RegValue - CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" - - CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ - "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL -; CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall ${PRODUCT_FULL_NAME_WITH_VER}.lnk" \ -; "$INSTDIR\bin\Uninstall.exe" - StrCpy $0 $baseRegKey - StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" - StrCpy $2 "MenuFolder" - StrCpy $3 "$STARTMENU_FOLDER" - Call OMWriteRegStr -!insertmacro MUI_STARTMENU_WRITE_END - - StrCmp ${IPR} "false" skip_ipr - - ; back up old value of .ipr -!define Index "Line${__LINE__}" - ReadRegStr $1 HKCR ".ipr" "" - StrCmp $1 "" "${Index}-NoBackup" - StrCmp $1 "IntelliJIdeaProjectFile" "${Index}-NoBackup" - WriteRegStr HKCR ".ipr" "backup_val" $1 -"${Index}-NoBackup:" - WriteRegStr HKCR ".ipr" "" "IntelliJIdeaProjectFile" - ReadRegStr $0 HKCR "IntelliJIdeaProjectFile" "" - StrCmp $0 "" 0 "${Index}-Skip" - WriteRegStr HKCR "IntelliJIdeaProjectFile" "" "IntelliJ IDEA Project File" - WriteRegStr HKCR "IntelliJIdeaProjectFile\shell" "" "open" -"${Index}-Skip:" - WriteRegStr HKCR "IntelliJIdeaProjectFile\DefaultIcon" "" "$INSTDIR\bin\${PRODUCT_EXE_FILE},0" - WriteRegStr HKCR "IntelliJIdeaProjectFile\shell\open\command" "" \ - '$INSTDIR\bin\${PRODUCT_EXE_FILE} "%1"' -!undef Index - -skip_ipr: - -; readonly section - SectionIn RO -!include "idea_win.nsh" - - IntCmp $IS_UPGRADE_60 1 skip_properties - SetOutPath $INSTDIR\bin - File "${PRODUCT_PROPERTIES_FILE}" - File "${PRODUCT_VM_OPTIONS_FILE}" -skip_properties: - - StrCpy $0 $baseRegKey - StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" - StrCpy $2 "" - StrCpy $3 "$INSTDIR" - Call OMWriteRegStr - StrCpy $2 "Build" - StrCpy $3 ${VER_BUILD} - Call OMWriteRegStr - -; write uninstaller & add it to add/remove programs in control panel - WriteUninstaller "$INSTDIR\bin\Uninstall.exe" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "DisplayName" "${PRODUCT_FULL_NAME_WITH_VER}" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "UninstallString" "$INSTDIR\bin\Uninstall.exe" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "InstallLocation" "$INSTDIR" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "DisplayIcon" "$INSTDIR\bin\${PRODUCT_EXE_FILE}" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "DisplayVersion" "${VER_BUILD}" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "Publisher" "JetBrains s.r.o." - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "URLInfoAbout" "https://www.jetbrains.com/products" - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "InstallType" "$baseRegKey" - WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "NoModify" 1 - WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \ - "NoRepair" 1 - - ExecWait "$INSTDIR\jre\jre\bin\javaw.exe -Xshare:dump" - SetOutPath $INSTDIR\bin - ; set the current time for installation files under $INSTDIR\bin - ExecCmd::exec 'copy "$INSTDIR\bin\*.*s" +,,' - call winVersion - ${If} $0 == "1" - ;ExecCmd::exec 'icacls "$INSTDIR" /grant %username%:F /T >"$INSTDIR"\installation_log.txt 2>"$INSTDIR"\installation_error.txt' - AccessControl::GrantOnFile \ - "$INSTDIR" "(S-1-5-32-545)" "GenericRead + GenericExecute" - AccessControl::GrantOnFile \ - "$INSTDIR\bin\${PRODUCT_EXE_FILE}.vmoptions" "(S-1-5-32-545)" "GenericRead + GenericWrite" - ${StrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions" - AccessControl::GrantOnFile \ - "$INSTDIR\bin\$0" "(S-1-5-32-545)" "GenericRead + GenericWrite" - ${EndIf} -SectionEnd - -;------------------------------------------------------------------------------ -; Descriptions of sections -;------------------------------------------------------------------------------ -; LangString DESC_CopyRuntime ${LANG_ENGLISH} "${MUI_PRODUCT} files" - -;------------------------------------------------------------------------------ -; custom install pages -;------------------------------------------------------------------------------ -Function updatePythonControls - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Text" "Python $R2 (installed)" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Flags" "DISABLED" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "Type" "checkbox" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R4 "State" "0" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R5 "Type" "checkbox" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" $R5 "State" "0" -FunctionEnd - -Function ConfirmDesktopShortcut - !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 1" "Text" "$(create_desktop_shortcut)" - call winVersion - ${If} $0 == "1" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Type" "Label" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "" - ${Else} - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "$(create_quick_launch_shortcut)" - ${EndIf} - IfFileExists "$TEMP\python.txt" deletePythonFileInfo getPythonFileInfo -deletePythonFileInfo: - Delete "$TEMP\python.txt" -getPythonFileInfo: - inetc::get "https://www.jetbrains.com/updates/python.txt" "$TEMP\python.txt" - ${LineSum} "$TEMP\python.txt" $R0 - IfErrors cantOpenFile - StrCmp $R0 ${PYTHON_VERSIONS} getPythonInfo -cantOpenFile: - MessageBox MB_OK|MB_ICONEXCLAMATION "python.txt is not exist. Python will not be downloaded." -removePythonChoice: - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Flags" "DISABLED" - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 5" "Flags" "DISABLED" - goto association -getPythonInfo: - Call getPythonInfo - StrCmp $0 "Error" removePythonChoice - ;check if pythons are already installed - StrCpy $R2 $0 - Call searchPython - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Text" "Python $0" - StrCmp $R2 "Absent" checkPython3 - StrCpy $R2 $0 - StrCpy $R4 "Field 4" - StrCpy $R5 "Field 5" - Call updatePythonControls -checkPython3: - StrCpy $R2 $R0 - Call searchPython - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 5" "Text" "Python $R0" - StrCmp $R2 "Absent" association - StrCpy $R2 $R0 - StrCpy $R4 "Field 5" - StrCpy $R5 "Field 4" - Call updatePythonControls -association: - StrCpy $R0 6 - StrCmp "${ASSOCIATION}" "NoAssociation" skip_association - push "${ASSOCIATION}" -loop: - call SplitStr - Pop $0 - StrCmp $0 "" done - IntOp $R0 $R0 + 1 - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0" - goto loop -skip_association: - call winVersion - ${If} $0 == "1" - IntOp $R0 $R0 - 1 - ${EndIf} -done: - !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0" - !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini" -FunctionEnd - - -;------------------------------------------------------------------------------ -; custom uninstall functions -;------------------------------------------------------------------------------ - -Function un.onInit - StrCpy $baseRegKey "HKCU" - ;admin perm. is required to uninstall? - ${UnStrStr} $R0 $INSTDIR $PROGRAMFILES - StrCmp $R0 $INSTDIR requred_admin_perm UAC_Done - -requred_admin_perm: - ;the user has admin rights? - UserInfo::GetAccountType - Pop $R2 - StrCmp $R2 "Admin" UAC_Admin uninstall_location - -uninstall_location: - ;check if the uninstallation is running from the product location - IfFileExists $APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe UAC_Elevate copy_uninstall - -copy_uninstall: - ;do copy for unistall.exe - CopyFiles "$OUTDIR\Uninstall.exe" "$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe" - ExecWait '"$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe" _?=$INSTDIR' - Delete "$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe" - Quit - -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_ElevationAborted: -UAC_Err: - Abort -UAC_Success: - StrCmp 1 $3 UAC_Admin ;Admin? - StrCmp 3 $1 0 UAC_ElevationAborted ;Try again? - goto UAC_Elevate -UAC_Admin: - SetShellVarContext all - StrCpy $baseRegKey "HKLM" -UAC_Done: - !insertmacro MUI_UNGETLANGUAGE - !insertmacro INSTALLOPTIONS_EXTRACT "DeleteSettings.ini" -FunctionEnd - -Function un.ReturnBackupRegValue - ;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: - Pop $0 -FunctionEnd - -;------------------------------------------------------------------------------ -; custom uninstall pages -;------------------------------------------------------------------------------ - -Function un.ConfirmDeleteSettings - !insertmacro MUI_HEADER_TEXT "$(uninstall_options)" "$(uninstall_options_prompt)" - !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 1" "Text" "$(prompt_delete_settings)" - !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" $INSTDIR - !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(text_delete_settings)" - !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 4" "Text" "$(confirm_delete_caches)" - !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 5" "Text" "$(confirm_delete_settings)" - !insertmacro INSTALLOPTIONS_DISPLAY "DeleteSettings.ini" -FunctionEnd - - -Function un.PrepareCustomPath - ;Input: - ;$0 - name of variable - ;$1 - value of the variable - ;$2 - line from the property file - push $3 - push $5 - ${UnStrLoc} $3 $2 $0 ">" - StrCmp $3 "" not_found - StrLen $5 $0 - IntOp $3 $3 + $5 - StrCpy $2 $2 "" $3 - IfFileExists "$1$2\\*.*" not_found - StrCpy $2 $1$2 - goto complete -not_found: - StrCpy $0 "" -complete: - pop $5 - pop $3 -FunctionEnd - - -Function un.getCustomPath - push $0 - push $1 - StrCpy $0 "${user.home}/" - StrCpy $1 "$PROFILE/" - Call un.PrepareCustomPath - StrCmp $0 "" check_idea_var - goto complete -check_idea_var: - StrCpy $0 "${idea.home}/" - StrCpy $1 "$INSTDIR/" - Call un.PrepareCustomPath - StrCmp $2 "" +1 +2 - StrCpy $2 "" -complete: - pop $1 - pop $0 -FunctionEnd - - -Function un.getPath -; The function read lines from idea.properties and search the substring and prepare the path to settings or caches. - ClearErrors - FileOpen $3 $INSTDIR\bin\idea.properties r - IfErrors complete ;file can not be open. not sure if a message should be displayed in this case. - StrLen $5 $1 -read_line: - FileRead $3 $4 - StrCmp $4 "" complete - ${UnStrLoc} $6 $4 $1 ">" - StrCmp $6 "" read_line ; there is no substring in a string from the file. go for next one. - IntOp $6 $6 + $5 - ${unStrStr} $7 $4 "#" ;check if the property has been customized - StrCmp $7 "" custom - StrCpy $2 "$PROFILE/${PRODUCT_SETTINGS_DIR}/$0" ;no. use the default value. - goto complete -custom: - StrCpy $2 $4 "" $6 - Call un.getCustomPath -complete: - FileClose $3 - ${UnStrRep} $2 $2 "/" "\" -FunctionEnd - - -Section "Uninstall" - StrCpy $productDir $INSTDIR - StrCpy $baseRegKey "HKCU" - ; Uninstaller is in the \bin directory, we need upper level dir - StrCpy $INSTDIR $INSTDIR\.. - - !insertmacro INSTALLOPTIONS_READ $R2 "DeleteSettings.ini" "Field 4" "State" - DetailPrint "Data: $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\" - StrCmp $R2 1 "" skip_delete_caches - ;find the path to caches (system) folder - StrCpy $0 "system" - StrCpy $1 "idea.system.path=" - Call un.getPath - StrCmp $2 "" skip_delete_caches - StrCpy $system_path $2 - RmDir /r "$system_path" - RmDir "$system_path\\.." ; remove parent of system dir if the dir is empty -; RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\system -skip_delete_caches: - - !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 5" "State" - StrCmp $R3 1 "" skip_delete_settings - ;find the path to settings (config) folder - StrCpy $0 "config" - StrCpy $1 "idea.config.path=" - Call un.getPath - StrCmp $2 "" skip_delete_settings - StrCpy $config_path $2 - RmDir /r "$config_path" -; RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\config - Delete "$INSTDIR\bin\${PRODUCT_VM_OPTIONS_NAME}" - Delete "$INSTDIR\bin\idea.properties" - StrCmp $R2 1 "" skip_delete_settings - RmDir "$config_path\\.." ; remove parent of config dir if the dir is empty -; RmDir $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR} -skip_delete_settings: - -; Delete uninstaller itself - Delete "$INSTDIR\bin\Uninstall.exe" - Delete "$INSTDIR\jre\jre\bin\client\classes.jsa" - - Push "Complete" - Push "$INSTDIR\bin\${PRODUCT_EXE_FILE}.vmoptions" - Push "$INSTDIR\bin\idea.properties" - ${UnStrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions" - Push "$INSTDIR\bin\$0" - Call un.compareFileInstallationTime - ${If} $9 != "Modified" - RMDir /r "$INSTDIR" - ${Else} - !include "unidea_win.nsh" - RMDir "$INSTDIR" - ${EndIf} - - ReadRegStr $R9 HKCU "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" "MenuFolder" - StrCmp $R9 "" "" clear_shortcuts - ReadRegStr $R9 HKLM "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" "MenuFolder" - StrCmp $R9 "" clear_Registry - StrCpy $5 "Software\${MANUFACTURER}" -; call un.winVersion -; ${If} $0 == "1" -; StrCpy $5 "Software\Wow6432Node\${MANUFACTURER}" -; ${EndIf} -clear_shortcuts: - ;the user has the admin rights -; UserInfo::GetAccountType -; Pop $R2 - IfFileExists "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" keep_current_user - SetShellVarContext all -keep_current_user: - DetailPrint "Start Menu: $SMPROGRAMS\$R9\${PRODUCT_FULL_NAME_WITH_VER}" - - Delete "$SMPROGRAMS\$R9\${PRODUCT_FULL_NAME_WITH_VER}.lnk" -; Delete "$SMPROGRAMS\$R9\Uninstall ${PRODUCT_FULL_NAME_WITH_VER}.lnk" -; Delete only if empty (last IDEA version is uninstalled) - RMDir "$SMPROGRAMS\$R9" - - Delete "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" - Delete "$QUICKLAUNCH\${PRODUCT_FULL_NAME_WITH_VER}.lnk" - -clear_Registry: - StrCpy $5 "Software\${MANUFACTURER}" - call un.winVersion - ${If} $0 == "1" - StrCpy $5 "Software\Wow6432Node\${MANUFACTURER}" - ${EndIf} - - StrCpy $0 $baseRegKey - StrCpy $1 "$5\${PRODUCT_REG_VER}" - StrCpy $2 "MenuFolder" - Call un.OMDeleteRegValue - - StrCmp "${ASSOCIATION}" "NoAssociation" finish_uninstall - push "${ASSOCIATION}" -loop: - call un.SplitStr - Pop $0 - StrCmp $0 "" finish_uninstall - StrCpy $1 $0 - StrCpy $2 "backup_val" - Call un.ReturnBackupRegValue - goto loop -finish_uninstall: - StrCpy $0 $baseRegKey - StrCpy $1 "$5\${PRODUCT_REG_VER}" - StrCpy $2 "Build" - Call un.OMReadRegStr - - StrCpy $1 "$5\${PRODUCT_REG_VER}" - Call un.OMDeleteRegKey - - StrCpy $1 "$5\${MUI_PRODUCT}" - Call un.OMDeleteRegKeyIfEmpty - - StrCpy $1 "$5" - Call un.OMDeleteRegKeyIfEmpty - - StrCpy $0 "HKCR" - StrCpy $1 "Applications\${PRODUCT_EXE_FILE}" - StrCpy $2 "" - Call un.OMDeleteRegKey - StrCpy $0 "HKCR" - StrCpy $1 "${PRODUCT_PATHS_SELECTOR}" - StrCpy $2 "" - Call un.OMDeleteRegKey - - StrCpy $0 "HKCR" - StrCpy $1 "IntelliJIdeaProjectFile\DefaultIcon" - StrCpy $2 "" - call un.OMReadRegStr - StrCmp $3 "$productDir\${PRODUCT_EXE_FILE},0" remove_IntelliJIdeaProjectFile done -remove_IntelliJIdeaProjectFile: - StrCpy $1 "IntelliJIdeaProjectFile" - Call un.OMDeleteRegKey -done: - DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" - -; UNCOMMENT THIS IN RELEASE BUILD -; ExecShell "" "https://www.jetbrains.com/idea/uninstall/" - -SectionEnd diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index d10f04587072..b25ab9dd9a45 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -112,9 +112,6 @@ target('default': "Build artifacts") { } bundledJDKs() - //EDU installation with a custom page dialog - ant.copy(file: "$ch/python/edu/build/desktop.ini", tofile: "$ch/build/conf/nsis/desktop.ini", overwrite: "true") - ant.copy(file: "$ch/python/edu/build/idea.nsi", tofile: "$ch/build/conf/nsis/idea.nsi", overwrite: "true") ant.patternset(id: "resources.included") { include(name: "**/*.properties") @@ -207,6 +204,9 @@ public layoutEducational(String classesPath, Set usedJars) { buildWinZip("${paths.artifacts}/pycharm${buildName}.zip", [paths.distAll, paths.distWin, "${paths.sandbox}/jdk.win"]) + //EDU installation with a custom page dialog + ant.copy(file: "$ch/python/edu/build/desktop.ini", tofile: "${paths.sandbox}/nsiconf/desktop.ini", overwrite: "true") + ant.copy(file: "$ch/python/edu/build/customInstallActions.nsi", tofile: "${paths.sandbox}/nsiconf/customInstallActions.nsi", overwrite: "true") buildNSIS([paths.distAll, paths.distWin], "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi", "pycharmEDU-", false, true, system_selector) From bc500cd0c332c29eee4ea784201b85fa5a1db471 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 15 Jan 2016 15:42:25 +0300 Subject: [PATCH 146/825] cleanup --- .../com/intellij/openapi/actionSystem/ex/ActionUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java index 46d6e611ad41..1ce55d4c8f3b 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -91,9 +91,9 @@ public class ActionUtil { * @param action action * @param e action event * @param beforeActionPerformed whether to call - * {@link com.intellij.openapi.actionSystem.AnAction#beforeActionPerformedUpdate(com.intellij.openapi.actionSystem.AnActionEvent)} + * {@link AnAction#beforeActionPerformedUpdate(AnActionEvent)} * or - * {@link com.intellij.openapi.actionSystem.AnAction#update(com.intellij.openapi.actionSystem.AnActionEvent)} + * {@link AnAction#update(AnActionEvent)} * @return true if update tried to access indices in dumb mode */ public static boolean performDumbAwareUpdate(@NotNull AnAction action, @NotNull AnActionEvent e, boolean beforeActionPerformed) { From 900cead9ae703fc1635f980196bd987bbb15401d Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 15 Jan 2016 16:04:47 +0300 Subject: [PATCH 147/825] IDEA-149918 Find Action shows strange "New Group (1)" action group --- .../ide/util/gotoByName/GotoActionModel.java | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 7b5088870f3e..4a944b770e81 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -59,11 +59,14 @@ import javax.swing.border.Border; import java.awt.*; import java.util.*; import java.util.List; +import java.util.regex.Matcher; import static com.intellij.ui.SimpleTextAttributes.STYLE_PLAIN; import static com.intellij.ui.SimpleTextAttributes.STYLE_SEARCH_MATCH; public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator, EdtSortingModel, DumbAware { + private static java.util.regex.Pattern INNER_GROUP_WITH_IDS = java.util.regex.Pattern.compile("(.*) \\(\\d+\\)"); + @Nullable private final Project myProject; private final Component myContextComponent; @@ -322,7 +325,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return settings + " > " + name; } - private void collectActions(Map result, ActionGroup group, String containingGroupName) { + private void collectActions(@NotNull Map result, @NotNull ActionGroup group, @Nullable String containingGroupName) { AnAction[] actions = group.getChildren(null); includeGroup(result, group, actions, containingGroupName); for (AnAction action : actions) { @@ -330,7 +333,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C if (action instanceof ActionGroup) { ActionGroup actionGroup = (ActionGroup)action; String groupName = actionGroup.getTemplatePresentation().getText(); - collectActions(result, actionGroup, StringUtil.isEmpty(groupName) || !actionGroup.isPopup() ? containingGroupName : groupName); + collectActions(result, actionGroup, getGroupName(StringUtil.isEmpty(groupName) || !actionGroup.isPopup() ? containingGroupName : groupName)); } else { String groupName = group.getTemplatePresentation().getText(); @@ -338,16 +341,25 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C result.put(action, null); } else { - result.put(action, StringUtil.isEmpty(groupName) ? containingGroupName : groupName); + result.put(action, getGroupName(StringUtil.isEmpty(groupName) ? containingGroupName : groupName)); } } } } - private void includeGroup(Map result, - ActionGroup group, - AnAction[] actions, - String containingGroupName) { + @Nullable + private static String getGroupName(@Nullable String groupName) { + if (groupName != null) { + Matcher matcher = INNER_GROUP_WITH_IDS.matcher(groupName); + if (matcher.matches()) return matcher.group(1); + } + return groupName; + } + + private void includeGroup(@NotNull Map result, + @NotNull ActionGroup group, + @NotNull AnAction[] actions, + @Nullable String containingGroupName) { boolean showGroup = true; for (AnAction action : actions) { if (myActionManager.getId(action) != null) { @@ -356,7 +368,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C } } if (showGroup) { - result.put(group, containingGroupName); + result.put(group, getGroupName(containingGroupName)); } } From 9aaf71fdf1adc67e2d171e3b8c82bc5a202ff294 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 15 Jan 2016 16:17:58 +0300 Subject: [PATCH 148/825] go to action action cleanup --- .../ide/actions/SearchEverywhereAction.java | 4 +- .../ide/util/gotoByName/GotoActionModel.java | 50 ++++++++++++------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 9f7e41f69394..19e62d05ef8e 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -2097,7 +2097,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private GotoActionItemProvider createActionProvider() { GotoActionModel model = new GotoActionModel(project, myFocusComponent, myEditor, myFile) { @Override - protected MatchMode actionMatches(String pattern, @NotNull AnAction anAction) { + protected MatchMode actionMatches(@NotNull String pattern, @NotNull AnAction anAction) { String text = anAction.getTemplatePresentation().getText(); return text != null && NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE) .matches(text) ? MatchMode.NAME : MatchMode.NONE; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 4a944b770e81..c0d4c84dfa63 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -64,8 +64,9 @@ import java.util.regex.Matcher; import static com.intellij.ui.SimpleTextAttributes.STYLE_PLAIN; import static com.intellij.ui.SimpleTextAttributes.STYLE_SEARCH_MATCH; +@SuppressWarnings("TestOnlyProblems") public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator, EdtSortingModel, DumbAware { - private static java.util.regex.Pattern INNER_GROUP_WITH_IDS = java.util.regex.Pattern.compile("(.*) \\(\\d+\\)"); + @NotNull private static java.util.regex.Pattern INNER_GROUP_WITH_IDS = java.util.regex.Pattern.compile("(.*) \\(\\d+\\)"); @Nullable private final Project myProject; private final Component myContextComponent; @@ -106,7 +107,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C fillConfigurablesNames(ShowSettingsUtilImpl.getConfigurables(project, true)); } - private void fillConfigurablesNames(Configurable[] configurables) { + private void fillConfigurablesNames(@NotNull Configurable[] configurables) { for (Configurable configurable : configurables) { if (configurable instanceof SearchableConfigurable) { myConfigurablesNames.put(((SearchableConfigurable)configurable).getId(), configurable.getDisplayName()); @@ -119,6 +120,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return IdeBundle.message("prompt.gotoaction.enter.action"); } + @Nullable @Override public String getCheckBoxName() { return null; @@ -165,6 +167,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return ((ActionWrapper)value).getAction().getTemplatePresentation().getText(); } + @Nullable @Override public String toString() { return getMatchingDegree() + " " + getValueText(); @@ -233,8 +236,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override public ListCellRenderer getListCellRenderer() { return new GotoActionListCellRenderer(new Function() { + @NotNull @Override - public String fun(OptionDescription description) { + public String fun(@NotNull OptionDescription description) { return getGroupName(description); } }); @@ -244,7 +248,8 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return myActionManager.getId(anAction); } - private static JLabel createIconLabel(Icon icon) { + @NotNull + private static JLabel createIconLabel(@Nullable Icon icon) { LayeredIcon layeredIcon = new LayeredIcon(2); layeredIcon.setIcon(EMPTY_ICON, 0); if (icon != null && icon.getIconWidth() <= EMPTY_ICON.getIconWidth() && icon.getIconHeight() <= EMPTY_ICON.getIconHeight()) { @@ -256,9 +261,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C } - protected JLabel createActionLabel(AnAction anAction, String anActionName, + @NotNull + protected JLabel createActionLabel(@NotNull AnAction anAction, String anActionName, Color fg, Color bg, - Icon icon) { + @Nullable Icon icon) { LayeredIcon layeredIcon = new LayeredIcon(2); layeredIcon.setIcon(EMPTY_ICON, 0); if (icon != null && icon.getIconWidth() <= EMPTY_ICON.getIconWidth() && icon.getIconHeight() <= EMPTY_ICON.getIconHeight()) { @@ -274,7 +280,8 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return actionLabel; } - private static Shortcut preferKeyboardShortcut(Shortcut[] shortcuts) { + @Nullable + private static Shortcut preferKeyboardShortcut(@Nullable Shortcut[] shortcuts) { if (shortcuts != null) { for (Shortcut shortcut : shortcuts) { if (shortcut.isKeyboard()) return shortcut; @@ -291,7 +298,8 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return ((MatchedValue)o1).compareTo((MatchedValue)o2); } - public static AnActionEvent updateActionBeforeShow(AnAction anAction, DataContext dataContext) { + @NotNull + public static AnActionEvent updateActionBeforeShow(@NotNull AnAction anAction, @NotNull DataContext dataContext) { AnActionEvent event = AnActionEvent.createFromDataContext(ActionPlaces.ACTION_SEARCH, null, dataContext); ActionUtil.performDumbAwareUpdate(anAction, event, false); ActionUtil.performDumbAwareUpdate(anAction, event, true); @@ -374,7 +382,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C @Override @Nullable - public String getFullName(Object element) { + public String getFullName(@NotNull Object element) { return getElementName(element); } @@ -390,8 +398,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return ArrayUtil.EMPTY_STRING_ARRAY; } + @Nullable @Override - public String getElementName(Object mv) { + public String getElementName(@NotNull Object mv) { return ((MatchedValue) mv).getValueText(); } @@ -402,7 +411,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return actionMatches(pattern, anAction) != MatchMode.NONE; } - protected MatchMode actionMatches(String pattern, @NotNull AnAction anAction) { + protected MatchMode actionMatches(@NotNull String pattern, @NotNull AnAction anAction) { Pattern compiledPattern = getPattern(pattern); Presentation presentation = anAction.getTemplatePresentation(); String text = presentation.getText(); @@ -427,7 +436,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return matches(pattern, compiledPattern, matcher, text + " " + groupName) ? MatchMode.GROUP : MatchMode.NONE; } - private static boolean matches(String pattern, Pattern compiledPattern, PatternMatcher matcher, String str) { + private static boolean matches(@NotNull String pattern, Pattern compiledPattern, @NotNull PatternMatcher matcher, @NotNull String str) { return StringUtil.containsIgnoreCase(str, pattern) || matcher.matches(str, compiledPattern); } @@ -472,7 +481,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C NONE, INTENTION, NAME, DESCRIPTION, GROUP, NON_MENU } - static String convertPattern(String pattern) { + static String convertPattern(@NotNull String pattern) { int eol = pattern.indexOf('\n'); if (eol != -1) { pattern = pattern.substring(0, eol); @@ -552,7 +561,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C return buffer.toString(); } - private static boolean containsOnlyUppercaseLetters(String s) { + private static boolean containsOnlyUppercaseLetters(@NotNull String s) { for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c != '*' && c != ' ' && !Character.isUpperCase(c)) return false; @@ -571,6 +580,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C } private final ThreadLocal myMatcher = new ThreadLocal() { + @NotNull @Override protected PatternMatcher initialValue() { return new Perl5Matcher(); @@ -666,6 +676,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C myGroupNamer = groupNamer; } + @NotNull @Override public Component getListCellRendererComponent(@NotNull JList list, Object matchedValue, @@ -775,13 +786,16 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C panel.setBorder(IdeBorderFactory.createEmptyBorder(0, 2, 0, 2)); } - public String getName(String text, String groupName, boolean toggle) { - return toggle && StringUtil.isNotEmpty(groupName)? groupName + ": "+ text : text; + @NotNull + private static String getName(@Nullable String text, @Nullable String groupName, boolean toggle) { + return toggle && StringUtil.isNotEmpty(groupName) + ? StringUtil.isNotEmpty(text) ? groupName + ": " + text + : groupName : StringUtil.notNullize(text); } private static void appendWithColoredMatches(SimpleColoredComponent nameComponent, - String name, - String pattern, + @NotNull String name, + @NotNull String pattern, Color fg, boolean selected) { SimpleTextAttributes plain = new SimpleTextAttributes(STYLE_PLAIN, fg); From 6dcd9f14bdfe841fbeae10b795a82327487d37d9 Mon Sep 17 00:00:00 2001 From: irengrig Date: Fri, 15 Jan 2016 14:22:12 +0100 Subject: [PATCH 149/825] WEB-19812 Better warning when a deployment configuration corresponding to a remote interpreter is removed --- .../com/intellij/remote/RemoteConnectionCredentialsWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java index 7cbac5774097..d8eed473970f 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java @@ -66,7 +66,7 @@ public class RemoteConnectionCredentialsWrapper { myCredentialsTypeHolder.putUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS, webDeploymentCredentials); } - private WebDeploymentCredentialsHolder getWebDeploymentCredentials() { + public WebDeploymentCredentialsHolder getWebDeploymentCredentials() { return myCredentialsTypeHolder.getUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS); } From fdd2d4075cb84d4492ea7eb4e6a5dec3d13a274d Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 15 Jan 2016 16:27:14 +0300 Subject: [PATCH 150/825] IDEA-149395 Resolve overlapping of translucent scroll bars --- .../com/intellij/ui/components/JBScrollPane.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index c3155ad40f2c..a6ff4f132c89 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -574,6 +574,13 @@ public class JBScrollPane extends JScrollPane { colHead.setBounds(colHeadBounds); colHead.putClientProperty(Alignment.class, hsbOnTop ? Alignment.BOTTOM : Alignment.TOP); } + // Calculate overlaps for translucent scroll bars + int overlapWidth = 0; + int overlapHeight = 0; + if (vsbNeeded && !vsbOpaque && hsbNeeded && !hsbOpaque) { + overlapWidth = vsbBounds.width; // shrink horizontally + //overlapHeight = hsbBounds.height; // shrink vertically + } // Set the bounds of the vertical scroll bar. vsbBounds.y = bounds.y - insets.top; vsbBounds.height = bounds.height + insets.top + insets.bottom; @@ -590,7 +597,8 @@ public class JBScrollPane extends JScrollPane { vsbBounds.height += colHeadBounds.height; } } - vsb.setBounds(vsbBounds); + int overlapY = !hsbOnTop ? 0 : overlapHeight; + vsb.setBounds(vsbBounds.x, vsbBounds.y + overlapY, vsbBounds.width, vsbBounds.height - overlapHeight); vsb.putClientProperty(Alignment.class, vsbOnLeft ? Alignment.LEFT : Alignment.RIGHT); pane.setComponentZOrder(vsb, 0); } @@ -616,7 +624,8 @@ public class JBScrollPane extends JScrollPane { hsbBounds.width += rowHeadBounds.width; } } - hsb.setBounds(hsbBounds); + int overlapX = !vsbOnLeft ? 0 : overlapWidth; + hsb.setBounds(hsbBounds.x + overlapX, hsbBounds.y, hsbBounds.width - overlapWidth, hsbBounds.height); hsb.putClientProperty(Alignment.class, hsbOnTop ? Alignment.TOP : Alignment.BOTTOM); } // Modify the bounds of the translucent scroll bar. From 0eb8dcdd82c7a90e138a264b7447adbfa248a416 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 15 Jan 2016 16:28:24 +0300 Subject: [PATCH 151/825] IDEA-149395 Shrink thumbs in opaque scroll bars --- .../com/intellij/ui/components/DefaultScrollBarUI.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/DefaultScrollBarUI.java b/platform/platform-api/src/com/intellij/ui/components/DefaultScrollBarUI.java index 112bdaa5bb97..fb0d74d7cc71 100644 --- a/platform/platform-api/src/com/intellij/ui/components/DefaultScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/ui/components/DefaultScrollBarUI.java @@ -76,8 +76,14 @@ final class DefaultScrollBarUI extends AbstractScrollBarUI { @Override void paintThumb(Graphics2D g, int x, int y, int width, int height, JComponent c) { Composite old = g.getComposite(); - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .4f + .1f * myThumbValue)); - if (!c.isOpaque()) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .4f + .2f * myThumbValue)); + if (c.isOpaque()) { + x += 1; + y += 1; + width -= 2; + height -= 2; + } + else { Alignment alignment = Alignment.get(c); if (alignment == Alignment.LEFT || alignment == Alignment.RIGHT) { int offset = width - getMinimalThickness(); From e45dbbd9d1d4efb216b67caad482461f6903cd1e Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 15 Jan 2016 17:41:22 +0300 Subject: [PATCH 152/825] vertically center folding anchors (otherwise looks bad with large fonts) --- .../impl/EditorGutterComponentImpl.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 6b1cc18eddf5..9dda5a62e4a9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -1009,9 +1009,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse if (myActiveFoldRegion != null && myActiveFoldRegion.isExpanded() && myActiveFoldRegion.isValid()) { int foldStart = myEditor.offsetToVisualLine(myActiveFoldRegion.getStartOffset()); int foldEnd = myEditor.offsetToVisualLine(getEndOffset(myActiveFoldRegion)); - int startY = myEditor.visibleLineToY(foldStart + 1) - myEditor.getDescent(); - int endY = myEditor.visibleLineToY(foldEnd) + myEditor.getLineHeight() - - myEditor.getDescent(); + int startY = getLineCenterY(foldStart); + int endY = getLineCenterY(foldEnd); if (startY <= clip.y + clip.height && endY + 1 + myEditor.getDescent() >= clip.y) { int lineX = anchorX + width / 2; @@ -1034,11 +1033,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - public int getHeadCenterY(FoldRegion foldRange) { - int width = getFoldingAnchorWidth(); - int foldStart = myEditor.offsetToVisualLine(foldRange.getStartOffset()); + private int getLineCenterY(int line) { + return myEditor.visibleLineToY(line) + myEditor.getLineHeight() / 2; + } - return myEditor.visibleLineToY(foldStart) + myEditor.getLineHeight() - myEditor.getDescent() - width / 2; + private int getFoldAnchorY(int line, int width) { + return getLineCenterY(line) - width / 2; + } + + int getHeadCenterY(FoldRegion foldRange) { + return getLineCenterY(myEditor.offsetToVisualLine(foldRange.getStartOffset())); } private void drawAnchor(int width, Rectangle clip, Graphics2D g, int anchorX, int visualLine, @@ -1046,22 +1050,21 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse final int off = JBUI.scale(2); int height = width + off; - int y; + int y = getFoldAnchorY(visualLine, width); switch (type) { case COLLAPSED: - y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent() - width; if (y <= clip.y + clip.height && y + height >= clip.y) { drawSquareWithPlus(g, anchorX, y, width, active); } break; case EXPANDED_TOP: - y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent() - width; if (y <= clip.y + clip.height && y + height >= clip.y) { drawDirectedBox(g, anchorX, y, width, height, width - off, active); } break; case EXPANDED_BOTTOM: - y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent(); + //noinspection SuspiciousNameCombination + y += width; if (y - height <= clip.y + clip.height && y >= clip.y) { drawDirectedBox(g, anchorX, y, width, -height, -width + off, active); } @@ -1340,9 +1343,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @SuppressWarnings("SuspiciousNameCombination") private Rectangle rectangleByFoldOffset(int foldStart, int anchorWidth, int anchorX) { - int anchorY = myEditor.visibleLineToY(foldStart) + myEditor.getLineHeight() - - myEditor.getDescent() - anchorWidth; - return new Rectangle(anchorX, anchorY, anchorWidth, anchorWidth); + return new Rectangle(anchorX, getFoldAnchorY(foldStart, anchorWidth), anchorWidth, anchorWidth); } @Override From 684aea2161f97bcd34270ebe7862068f0a76431c Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Fri, 15 Jan 2016 17:50:22 +0300 Subject: [PATCH 153/825] IDEA-111425 Accessibility For The Blind And Visually Impaired --- .../lookup/impl/LookupCellRenderer.java | 3 + .../header/InspectionToolsConfigurable.java | 8 + .../intellij/ui/GroupedElementsRenderer.java | 3 + .../intellij/ui/HighlightableComponent.java | 39 +- .../src/com/intellij/ui/HyperlinkLabel.java | 52 + .../intellij/ui/SimpleColoredComponent.java | 7 +- .../com/intellij/ui/components/JBList.java | 58 + .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 475 +++++- .../com/intellij/ui/tabs/impl/TabLabel.java | 37 +- .../com/intellij/ide/actions/Switcher.java | 8 + .../internal/inspector/UiInspectorAction.java | 45 +- .../actionSystem/impl/ActionButton.java | 109 +- .../editor/impl/EditorComponentImpl.java | 1376 ++++++++++++++--- .../options/newEditor/SettingsTreeView.java | 19 +- .../impl/welcomeScreen/FlatWelcomeFrame.java | 5 + .../FlatWelcomeFrameProvider.java | 8 +- .../welcomeScreen/NewRecentProjectPanel.java | 3 + .../welcomeScreen/RecentProjectPanel.java | 7 +- .../src/com/intellij/ui/CardLayoutPanel.java | 20 +- .../util/resources/misc/registry.properties | 3 +- .../accessibility/AccessibleContextUtil.java | 92 ++ 21 files changed, 2146 insertions(+), 231 deletions(-) create mode 100644 platform/util/src/com/intellij/util/ui/accessibility/AccessibleContextUtil.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index 4c6ce48e3d93..f3d422896474 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -38,6 +38,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FList; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.accessibility.AccessibleContextUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -214,6 +215,8 @@ public class LookupCellRenderer implements ListCellRenderer { } } + AccessibleContextUtil.setCombinedName(myPanel, myNameComponent, "", myTailComponent, " - ", myTypeLabel); + AccessibleContextUtil.setCombinedDescription(myPanel, myNameComponent, "", myTailComponent, " - ", myTypeLabel); return myPanel; } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index 654774d70d05..ab5741928632 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -71,6 +71,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; import java.io.File; import java.io.IOException; import java.util.*; @@ -414,6 +416,12 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable toolbar.setLayout(new GridBagLayout()); final JLabel headerTitleLabel = new JLabel(HEADER_TITLE); + headerTitleLabel.addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + System.out.println("HERE"); + } + }); headerTitleLabel.setBorder(IdeBorderFactory.createEmptyBorder(10, 0, 0, 0)); toolbar.add(headerTitleLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); diff --git a/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java b/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java index ad861423ca58..548705960ac1 100644 --- a/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.ui.components.panels.OpaquePanel; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.accessibility.AccessibleContextUtil; import javax.swing.*; import javax.swing.border.Border; @@ -59,6 +60,8 @@ public abstract class GroupedElementsRenderer { myTextLabel.setText(text); myRendererComponent.setToolTipText(tooltip); + AccessibleContextUtil.setName(myRendererComponent, myTextLabel); + AccessibleContextUtil.setDescription(myRendererComponent, myTextLabel); myTextLabel.setIcon(icon); myTextLabel.setDisabledIcon(disabledIcon); diff --git a/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java b/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java index 351e01f23c7f..53ad9d841501 100644 --- a/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java +++ b/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java @@ -19,10 +19,15 @@ package com.intellij.ui; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.Nullable; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import javax.swing.*; import java.awt.*; import java.util.ArrayList; @@ -30,7 +35,7 @@ import java.util.ArrayList; /** * @author Eugene Belyaev */ -public class HighlightableComponent extends JComponent { +public class HighlightableComponent extends JComponent implements Accessible { protected String myText = ""; protected Icon myIcon; protected int myIconTextGap; @@ -60,11 +65,23 @@ public class HighlightableComponent extends JComponent { } public void setText(String text) { + String oldAccessibleName = null; + if (accessibleContext != null) { + oldAccessibleName = accessibleContext.getAccessibleName(); + } + if (text == null) { text = ""; } myText = text; myHighlightedRegions = new ArrayList(4); + + if ((accessibleContext != null) && !StringUtil.equals(accessibleContext.getAccessibleName(), oldAccessibleName)) { + accessibleContext.firePropertyChange( + AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, + oldAccessibleName, + accessibleContext.getAccessibleName()); + } } public void setIcon(Icon icon) { @@ -423,4 +440,24 @@ public class HighlightableComponent extends JComponent { } return text; } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleHighlightable(); + } + return accessibleContext; + } + + protected class AccessibleHighlightable extends JComponent.AccessibleJComponent { + @Override + public String getAccessibleName() { + return myText; + } + + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.LABEL; + } + } } diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java index 8c920d6221be..0051af59a488 100644 --- a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java @@ -16,6 +16,9 @@ package com.intellij.ui; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.markup.EffectType; @@ -245,4 +248,53 @@ public class HyperlinkLabel extends HighlightableComponent { public void updateUI() { setFont(UIUtil.getLabelFont()); } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleHyperlinkLabel(); + } + return accessibleContext; + } + + /** + * Hyperlink accessibility: "HYPERLINK" role and expose a "click" action. + * @see javax.swing.AbstractButton.AccessibleAbstractButton + */ + protected class AccessibleHyperlinkLabel extends AccessibleHighlightable implements AccessibleAction { + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.HYPERLINK; + } + + @Override + public AccessibleAction getAccessibleAction() { + return this; + } + + @Override + public int getAccessibleActionCount() { + return 1; + } + + @Override + public String getAccessibleActionDescription(int i) { + if (i == 0) { + return UIManager.getString("AbstractButton.clickText"); + } + else { + return null; + } + } + + @Override + public boolean doAccessibleAction(int i) { + if (i == 0) { + doClick(); + return true; + } else { + return false; + } + } + } } diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index f1b87678a711..a589a5d5a0ff 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.Nullable; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import javax.swing.*; import javax.swing.border.Border; import javax.swing.tree.TreeCellRenderer; @@ -1033,7 +1034,11 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co private class MyAccessibleContext extends JComponent.AccessibleJComponent { @Override public String getAccessibleName() { - return SimpleColoredComponent.this.toString(); + return getCharSequence(false).toString(); + } + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.LABEL; } } diff --git a/platform/platform-api/src/com/intellij/ui/components/JBList.java b/platform/platform-api/src/com/intellij/ui/components/JBList.java index 9f514d3c551f..fa5bd5c0f468 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBList.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBList.java @@ -18,6 +18,7 @@ package com.intellij.ui.components; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; @@ -27,6 +28,9 @@ import com.intellij.util.ui.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import javax.swing.*; import javax.swing.plaf.UIResource; import javax.swing.text.JTextComponent; @@ -314,4 +318,58 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi return this; } } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJBList(); + } + return accessibleContext; + } + + protected class AccessibleJBList extends AccessibleJList { + @Override + public Accessible getAccessibleAt(Point p) { + return getAccessibleChild(locationToIndex(p)); + } + + @Override + public Accessible getAccessibleChild(int i) { + if (i < 0 || i >= getModel().getSize()) { + return null; + } else { + return new AccessibleJBListChild(JBList.this, i); + } + } + + @Override + public AccessibleRole getAccessibleRole() { + // In some cases, this method is called from the Access Bridge thread + // instead of the AWT thread. See https://code.google.com/p/android/issues/detail?id=193072 + return UIUtil.invokeAndWaitIfNeeded(new Computable() { + @Override + public AccessibleRole compute() { + return AccessibleJBList.super.getAccessibleRole(); + } + }); + } + + protected class AccessibleJBListChild extends AccessibleJListChild { + public AccessibleJBListChild(JBList parent, int indexInParent) { + super(parent, indexInParent); + } + + @Override + public AccessibleRole getAccessibleRole() { + // In some cases, this method is called from the Access Bridge thread + // instead of the AWT thread. See https://code.google.com/p/android/issues/detail?id=193072 + return UIUtil.invokeAndWaitIfNeeded(new Computable() { + @Override + public AccessibleRole compute() { + return AccessibleJBListChild.super.getAccessibleRole(); + } + }); + } + } + } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 94116ee3ab73..fb5006d1807a 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -51,6 +51,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.accessibility.*; import javax.swing.*; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; @@ -66,7 +67,7 @@ import java.util.List; public class JBTabsImpl extends JComponent implements JBTabs, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, - QuickActionProvider { + QuickActionProvider, Accessible { public static final DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); @NonNls public static final Key SIDE_TABS_SIZE_LIMIT_KEY = Key.create("SIDE_TABS_SIZE_LIMIT_KEY"); @@ -83,6 +84,7 @@ public class JBTabsImpl extends JComponent @NotNull final ActionManager myActionManager; private final List myVisibleInfos = new ArrayList(); + private final Map myInfo2Page = new HashMap(); private final Map myHiddenInfos = new HashMap(); private TabInfo mySelectedInfo; @@ -435,6 +437,7 @@ public class JBTabsImpl extends JComponent myImage = null; myActivePopup = null; myInfo2Label.clear(); + myInfo2Page.clear(); myInfo2Toolbar.clear(); myTabListeners.clear(); } @@ -752,6 +755,7 @@ public class JBTabsImpl extends JComponent info.getChangeSupport().addPropertyChangeListener(this); final TabLabel label = createTabLabel(info); myInfo2Label.put(info, label); + myInfo2Page.put(info, new AccessibleTabPage(info)); if (!isDropTarget) { if (index < 0 || index > myVisibleInfos.size() - 1) { @@ -2601,6 +2605,7 @@ public class JBTabsImpl extends JComponent myVisibleInfos.remove(info); myHiddenInfos.remove(info); myInfo2Label.remove(info); + myInfo2Page.remove(info); myInfo2Toolbar.remove(info); resetTabsCache(); @@ -3490,4 +3495,472 @@ public class JBTabsImpl extends JComponent public String toString() { return "JBTabs visible=" + myVisibleInfos + " selected=" + mySelectedInfo; } + + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleJBTabsImpl(); + } + return accessibleContext; + } + + /** + * Custom implementation of Accessible interface. Given JBTabsImpl is similar + * to the built-it JTabbedPane, we expose similar behavior. The one tricky part + * is that JBTabsImpl can only expose the content of the selected tab, as the + * content of tabs is created/deleted on demand when a tab is selected. + */ + protected class AccessibleJBTabsImpl extends AccessibleJComponent implements AccessibleSelection { + + public AccessibleJBTabsImpl() { + super(); + getAccessibleComponent(); + JBTabsImpl.this.addListener(new TabsListener.Adapter() { + @Override + public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) { + firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, null, null); + } + }); + } + + @Override + public String getAccessibleName() { + String name = accessibleName; + if (name == null) { + name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); + } + + if (name == null) { + // Similar to JTabbedPane, we return the name of our selected tab + // as our own name. + TabLabel selectedLabel = getSelectedLabel(); + if (selectedLabel != null) { + if (selectedLabel.getAccessibleContext() != null) { + name = selectedLabel.getAccessibleContext().getAccessibleName(); + } + } + } + + if (name == null) { + name = super.getAccessibleName(); + } + return name; + } + + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PAGE_TAB_LIST; + } + + @Override + public int getAccessibleChildrenCount() { + return getTabCount(); + } + + @Override + public Accessible getAccessibleChild(int i) { + if (i < 0 || i >= getTabCount()) { + return null; + } + return JBTabsImpl.this.myInfo2Page.get(JBTabsImpl.this.getTabAt(i)); + } + + @Override + public AccessibleSelection getAccessibleSelection() { + return this; + } + + @Override + public int getAccessibleSelectionCount() { + return (getSelectedInfo() == null ? 0 : 1); + } + + @Override + public Accessible getAccessibleSelection(int i) { + if (getSelectedInfo() == null) + return null; + return myInfo2Page.get(getSelectedInfo()); + } + + @Override + public boolean isAccessibleChildSelected(int i) { + return (i == getIndexOf(getSelectedInfo())); + } + + @Override + public void addAccessibleSelection(int i) { + TabInfo info = getTabAt(i); + if (info != null) { + select(info, false); + } + } + + @Override + public void removeAccessibleSelection(int i) { + // can't do + } + + @Override + public void clearAccessibleSelection() { + // can't do + } + + @Override + public void selectAllAccessibleSelection() { + // can't do + } + } + + /** + * AccessibleContext implementation for a single tab page. + * + * A tab page has a label as the display zone, name, description, etc. + * A tab page exposes a child component only if it corresponds to the + * selected tab in the tab pane. Inactive tabs don't have a child + * component to expose, as components are created/deleted on demand. + * A tab page exposes one action: select and activate the panel. + */ + private class AccessibleTabPage extends AccessibleContext + implements Accessible, AccessibleComponent, AccessibleAction { + + private final @NotNull JBTabsImpl myParent; + private final @NotNull TabInfo myTabInfo; + private final Component myComponent; + + AccessibleTabPage(@NotNull TabInfo tabInfo) { + myParent = JBTabsImpl.this; + myTabInfo = tabInfo; + myComponent = tabInfo.getComponent(); + initAccessibleContext(); + } + + private @NotNull TabInfo getTabInfo() { + return myTabInfo; + } + + private int getTabIndex() { + return JBTabsImpl.this.getIndexOf(myTabInfo); + } + + private TabLabel getTabLabel() { + return JBTabsImpl.this.myInfo2Label.get(getTabInfo()); + } + + /* + * initializes the AccessibleContext for the page + */ + void initAccessibleContext() { + // Note: null checks because we do not want to load Accessibility classes unnecessarily. + if (JBTabsImpl.this.accessibleContext != null && myComponent instanceof Accessible) { + AccessibleContext ac; + ac = myComponent.getAccessibleContext(); + if (ac != null) { + ac.setAccessibleParent(this); + } + } + } + + ///////////////// + // Accessibility support + //////////////// + + @Override + public AccessibleContext getAccessibleContext() { + return this; + } + + // AccessibleContext methods + + @Override + public String getAccessibleName() { + String name = accessibleName; + if (name == null) { + name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); + } + + if (name == null) { + TabLabel label = getTabLabel(); + if (label != null && label.getAccessibleContext() != null) { + name = label.getAccessibleContext().getAccessibleName(); + } + } + + if (name == null) { + name = super.getAccessibleName(); + } + return name; + } + + @Override + public String getAccessibleDescription() { + String description = accessibleDescription; + if (description == null) { + description = (String)getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY); + } + + if (description == null) { + TabLabel label = getTabLabel(); + if (label != null && label.getAccessibleContext() != null) { + description = label.getAccessibleContext().getAccessibleDescription(); + } + } + + if (description == null) { + description = super.getAccessibleDescription(); + } + return description; + } + + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PAGE_TAB; + } + + @Override + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet states; + states = myParent.getAccessibleContext().getAccessibleStateSet(); + states.add(AccessibleState.SELECTABLE); + TabInfo info = myParent.getSelectedInfo(); + if (info == getTabInfo()) { + states.add(AccessibleState.SELECTED); + } + return states; + } + + @Override + public int getAccessibleIndexInParent() { + return getTabIndex(); + } + + @Override + public int getAccessibleChildrenCount() { + // Expose the tab content only if it is active, as the content for + // inactive tab does is usually not ready (i.e. may never have been + // activated). + if (JBTabsImpl.this.getSelectedInfo() == getTabInfo() && myComponent instanceof Accessible) { + return 1; + } else { + return 0; + } + } + + @Override + public Accessible getAccessibleChild(int i) { + if (JBTabsImpl.this.getSelectedInfo() == getTabInfo() && myComponent instanceof Accessible) { + return (Accessible) myComponent; + } else { + return null; + } + } + + @Override + public Locale getLocale() { + return JBTabsImpl.this.getLocale(); + } + + @Override + public AccessibleComponent getAccessibleComponent() { + return this; + } + + @Override + public AccessibleAction getAccessibleAction() { + return this; + } + + // AccessibleComponent methods + + @Override + public Color getBackground() { + return JBTabsImpl.this.getBackground(); + } + + @Override + public void setBackground(Color c) { + JBTabsImpl.this.setBackground(c); + } + + @Override + public Color getForeground() { + return JBTabsImpl.this.getForeground(); + } + + @Override + public void setForeground(Color c) { + JBTabsImpl.this.setForeground(c); + } + + @Override + public Cursor getCursor() { + return JBTabsImpl.this.getCursor(); + } + + @Override + public void setCursor(Cursor c) { + JBTabsImpl.this.setCursor(c); + } + + @Override + public Font getFont() { + return JBTabsImpl.this.getFont(); + } + + @Override + public void setFont(Font f) { + JBTabsImpl.this.setFont(f); + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return JBTabsImpl.this.getFontMetrics(f); + } + + @Override + public boolean isEnabled() { + return getTabInfo().isEnabled(); + } + + @Override + public void setEnabled(boolean b) { + getTabInfo().setEnabled(b); + } + + @Override + public boolean isVisible() { + return !getTabInfo().isHidden(); + } + + @Override + public void setVisible(boolean b) { + getTabInfo().setHidden(!b); + } + + @Override + public boolean isShowing() { + return JBTabsImpl.this.isShowing(); + } + + @Override + public boolean contains(Point p) { + Rectangle r = getBounds(); + return r.contains(p); + } + + @Override + public Point getLocationOnScreen() { + Point parentLocation = JBTabsImpl.this.getLocationOnScreen(); + Point componentLocation = getLocation(); + componentLocation.translate(parentLocation.x, parentLocation.y); + return componentLocation; + } + + @Override + public Point getLocation() { + Rectangle r = getBounds(); + return new Point(r.x, r.y); + } + + @Override + public void setLocation(Point p) { + // do nothing + } + + /** + * Returns the bounds of tab. The bounds are with respect to the JBTabsImpl coordinate space. + */ + @Override + public Rectangle getBounds() { + return getTabLabel().getBounds(); + } + + @Override + public void setBounds(Rectangle r) { + // do nothing + } + + @Override + public Dimension getSize() { + Rectangle r = getBounds(); + return new Dimension(r.width, r.height); + } + + @Override + public void setSize(Dimension d) { + // do nothing + } + + @Override + public Accessible getAccessibleAt(Point p) { + if (myComponent instanceof Accessible) { + return (Accessible) myComponent; + } else { + return null; + } + } + + @Override + public boolean isFocusTraversable() { + return false; + } + + @Override + public void requestFocus() { + // do nothing + } + + @Override + public void addFocusListener(FocusListener l) { + // do nothing + } + + @Override + public void removeFocusListener(FocusListener l) { + // do nothing + } + + @Override + public AccessibleIcon [] getAccessibleIcon() { + AccessibleIcon accessibleIcon = null; + + if (getTabInfo().getIcon() instanceof ImageIcon) { + AccessibleContext ac = + ((ImageIcon)getTabInfo().getIcon()).getAccessibleContext(); + accessibleIcon = (AccessibleIcon)ac; + } + + if (accessibleIcon != null) { + AccessibleIcon [] returnIcons = new AccessibleIcon[1]; + returnIcons[0] = accessibleIcon; + return returnIcons; + } else { + return null; + } + } + + // AccessibleAction methods + + @Override + public int getAccessibleActionCount() { + return 1; + } + + @Override + public String getAccessibleActionDescription(int i) { + if (i != 0) + return null; + + return "Activate"; + } + + @Override + public boolean doAccessibleAction(int i) { + if (i != 0) + return false; + + JBTabsImpl.this.select(getTabInfo(), true); + return true; + } + } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index 391f719a7805..ce89193e5eb9 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -34,6 +34,8 @@ import com.intellij.util.ui.Centerizer; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; @@ -41,7 +43,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; -public class TabLabel extends JPanel { +public class TabLabel extends JPanel implements Accessible { protected final SimpleColoredComponent myLabel; private final LayeredIcon myIcon; @@ -606,4 +608,37 @@ public class TabLabel extends JPanel { public JComponent getLabelComponent() { return myLabel; } + + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleTabLabel(); + } + return accessibleContext; + } + + protected class AccessibleTabLabel extends AccessibleJPanel { + @Override + public String getAccessibleName() { + String name = super.getAccessibleName(); + if (name == null) { + if (myLabel.getAccessibleContext() != null){ + name = myLabel.getAccessibleContext().getAccessibleName(); + } + } + return name; + } + + @Override + public String getAccessibleDescription() { + String name = super.getAccessibleDescription(); + if (name == null) { + if (myLabel.getAccessibleContext() != null){ + name = myLabel.getAccessibleContext().getAccessibleDescription(); + } + } + return name; + } + } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index fc1f5243aeee..76ed6a540c9e 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -430,6 +430,7 @@ public class Switcher extends AnAction implements DumbAware { int index, boolean selected, boolean hasFocus) { + assert value instanceof FileInfo; final Component c = super.getListCellRendererComponent(list, value, index, selected, selected); final Color bg = UIUtil.getListBackground(); final Color fg = UIUtil.getListForeground(); @@ -439,6 +440,13 @@ public class Switcher extends AnAction implements DumbAware { myPanel.removeAll(); myPanel.add(myLabel, BorderLayout.WEST); myPanel.add(c, BorderLayout.CENTER); + + // Note: Name=name rendered in cell, Description=path to file, as displayed in bottom panel + myPanel.getAccessibleContext().setAccessibleName(c.getAccessibleContext().getAccessibleName()); + VirtualFile file = ((FileInfo)value).first; + String presentableUrl = ObjectUtils.notNull(file.getParent(), file).getPresentableUrl(); + String location = FileUtil.getLocationRelativeToUserHome(presentableUrl); + myPanel.getAccessibleContext().setAccessibleDescription(location); return myPanel; } diff --git a/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java b/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java index c4c18045e9ea..45ba8124563e 100644 --- a/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java +++ b/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java @@ -40,6 +40,8 @@ import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; @@ -455,8 +457,8 @@ public class UiInspectorAction extends ToggleAction implements DumbAware { TableColumnModel columnModel = table.getColumnModel(); TableColumn propertyColumn = columnModel.getColumn(0); - propertyColumn.setMinWidth(150); - propertyColumn.setMaxWidth(150); + propertyColumn.setMinWidth(200); + propertyColumn.setMaxWidth(200); propertyColumn.setResizable(false); TableColumn valueColumn = columnModel.getColumn(1); @@ -737,6 +739,15 @@ public class UiInspectorAction extends ToggleAction implements DumbAware { "isValid", "isDisplayable", "isLightweight" ); + final List ACCESSIBLE_CONTEXT_PROPERTIES = Arrays.asList( + "getAccessibleRole", "getAccessibleName", "getAccessibleDescription", + "getAccessibleAction", "getAccessibleChildrenCount", + "getAccessibleIndexInParent", "getAccessibleRelationSet", + "getAccessibleStateSet", "getAccessibleEditableText", + "getAccessibleTable", "getAccessibleText", + "getAccessibleValue", "accessibleChangeSupport" + ); + final Component myComponent; final List myProperties = ContainerUtil.newArrayList(); @@ -747,27 +758,41 @@ public class UiInspectorAction extends ToggleAction implements DumbAware { } void fillTable() { - Class clazz0 = myComponent.getClass(); + addProperties("", myComponent, PROPERTIES); + Object addedAt = myComponent instanceof JComponent ? ((JComponent)myComponent).getClientProperty("uiInspector.addedAt") : null; + myProperties.add(new PropertyBean("added-at", addedAt)); + + // Add properties related to Accessibility support. This is useful for manually + // inspecting what kind (if any) of accessibility support components expose. + boolean isAccessible = myComponent instanceof Accessible; + myProperties.add(new PropertyBean("accessible", isAccessible)); + AccessibleContext context = myComponent.getAccessibleContext(); + myProperties.add(new PropertyBean("accessibleContext", context)); + if (isAccessible) { + addProperties(" ", myComponent.getAccessibleContext(), ACCESSIBLE_CONTEXT_PROPERTIES); + } + } + + private void addProperties(@NotNull String prefix, @NotNull Object component, @NotNull List methodNames) { + Class clazz0 = component.getClass(); Class clazz = clazz0.isAnonymousClass() ? clazz0.getSuperclass() : clazz0; - myProperties.add(new PropertyBean("class", clazz.getName())); - for (String name: PROPERTIES) { + myProperties.add(new PropertyBean(prefix + "class", clazz.getName())); + for (String name: methodNames) { String propertyName = ObjectUtils.notNull(StringUtil.getPropertyName(name), name); Object propertyValue; try { try { //noinspection ConstantConditions - propertyValue = ReflectionUtil.findMethod(Arrays.asList(clazz.getMethods()), name).invoke(myComponent); + propertyValue = ReflectionUtil.findMethod(Arrays.asList(clazz.getMethods()), name).invoke(component); } catch (Exception e) { - propertyValue = ReflectionUtil.findField(clazz, null, name).get(myComponent); + propertyValue = ReflectionUtil.findField(clazz, null, name).get(component); } - myProperties.add(new PropertyBean(propertyName, propertyValue)); + myProperties.add(new PropertyBean(prefix + propertyName, propertyValue)); } catch (Exception ignored) { } } - Object addedAt = myComponent instanceof JComponent ? ((JComponent)myComponent).getClientProperty("uiInspector.addedAt") : null; - myProperties.add(new PropertyBean("added-at", addedAt)); } @Nullable 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 32bd1a30af0b..c7f4b910803e 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 @@ -33,13 +33,14 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.accessibility.*; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -public class ActionButton extends JComponent implements ActionButtonComponent, AnActionHolder { +public class ActionButton extends JComponent implements ActionButtonComponent, AnActionHolder, Accessible { private static final Icon ourEmptyIcon = EmptyIcon.ICON_18; @@ -358,4 +359,110 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A } } } + + // Accessibility + + @Override + public AccessibleContext getAccessibleContext() { + if(this.accessibleContext == null) { + this.accessibleContext = new AccessibleActionButton(); + } + + return this.accessibleContext; + } + + + protected class AccessibleActionButton extends JComponent.AccessibleJComponent implements AccessibleAction { + public AccessibleActionButton() { + } + + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PUSH_BUTTON; + } + + @Override + public String getAccessibleName() { + String name = accessibleName; + if (name == null) { + name = (String)ActionButton.this.getClientProperty(ACCESSIBLE_NAME_PROPERTY); + if (name == null) { + name = ActionButton.this.getToolTipText(); + if (name == null) { + name = ActionButton.this.myPresentation.getText(); + if (name == null) { + name = super.getAccessibleName(); + } + } + } + } + + return name; + } + + @Override + public AccessibleIcon[] getAccessibleIcon() { + Icon icon = ActionButton.this.getIcon(); + if (icon instanceof Accessible) { + AccessibleContext context = ((Accessible)icon).getAccessibleContext(); + if (context != null && context instanceof AccessibleIcon) { + return new AccessibleIcon[]{(AccessibleIcon)context}; + } + } + + return null; + } + + @Override + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet var1 = super.getAccessibleStateSet(); + int state = ActionButton.this.getPopState(); + + // TODO: Not sure what the "POPPED" state represents + //if (state == POPPED) { + // var1.add(AccessibleState.?); + //} + + if (state == ActionButtonComponent.PUSHED) { + var1.add(AccessibleState.PRESSED); + } + if (state == ActionButtonComponent.SELECTED) { + var1.add(AccessibleState.CHECKED); + } + + if (ActionButton.this.isFocusOwner()) { + var1.add(AccessibleState.FOCUSED); + } + + return var1; + } + + @Override + public AccessibleAction getAccessibleAction() { + return this; + } + + // Implements AccessibleAction + + @Override + public int getAccessibleActionCount() { + return 1; + } + + @Override + public String getAccessibleActionDescription(int index) { + return index == 0 ? UIManager.getString("AbstractButton.clickText") : null; + } + + @Override + public boolean doAccessibleAction(int index) { + if (index == 0) { // + ActionButton.this.click(); + return true; + } + else { + return false; + } + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index a96eb0c429cb..41df21d2e658 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java @@ -25,37 +25,60 @@ import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationImpl; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.DocumentRunnable; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.ReadOnlyFragmentModificationException; import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.editor.actionSystem.EditorActionManager; +import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.event.CaretEvent; import com.intellij.openapi.editor.event.CaretListener; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.ex.util.EditorUIUtil; import com.intellij.openapi.editor.ex.util.EditorUtil; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.TypingTarget; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.impl.IdeBackgroundUtil; import com.intellij.ui.EditorTextField; import com.intellij.ui.Grayer; import com.intellij.ui.components.Magnificator; import com.intellij.util.ui.UIUtil; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; - +import org.jetbrains.annotations.Nullable; import javax.accessibility.*; import javax.swing.*; -import javax.swing.event.DocumentEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.UndoableEditListener; +import javax.swing.plaf.TextUI; +import javax.swing.text.*; import javax.swing.text.AttributeSet; import java.awt.*; import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.InputMethodEvent; +import java.awt.event.*; import java.awt.im.InputMethodRequests; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget, Accessible { +public class EditorComponentImpl extends JTextComponent implements Scrollable, DataProvider, Queryable, TypingTarget, Accessible { private final EditorImpl myEditor; private final ApplicationImpl myApplication; @@ -78,6 +101,19 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP } }); myApplication = (ApplicationImpl)ApplicationManager.getApplication(); + + // This editor extends JTextComponent rather than JComponent *only* for accessibility + // purposes, and the JTextComponent is not fully supported: it does not reflect the + // true contents of the document, it doesn't paint, it doesn't have a proper UI delegate, + // etc. It simply extends JTextComponent and accepts document and caret listeners (and + // dispatches editing events to them) because on some platforms, the accessibility + // support is hardcoded to only work for JTextComponent rather than AccessibleText in + // general. + setupJTextComponentContext(); + + // Remove JTextComponent's mouse/focus listeners added in its ctor. + for (MouseListener l : getMouseListeners()) removeMouseListener(l); + for (FocusListener l : getFocusListeners()) removeFocusListener(l); } @Override @@ -133,7 +169,12 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP @Override protected void processInputMethodEvent(InputMethodEvent e) { - super.processInputMethodEvent(e); + // Don't dispatch to super first; now that EditorComponentImpl is a JTextComponent, + // this would have the side effect of invoking Swing document machinery which relies + // on creating Document positions etc (and won't update the document in an IntelliJ safe + // way, such as running through all the carets etc. + // super.processInputMethodEvent(e); + if (!e.isConsumed()) { switch (e.getID()) { case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: @@ -143,10 +184,12 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP //noinspection fallthrough case InputMethodEvent.CARET_POSITION_CHANGED: myEditor.inputMethodCaretPositionChanged(e); + e.consume(); break; } - e.consume(); } + + super.processInputMethodEvent(e); } @Override @@ -161,6 +204,7 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP return result; } + @Nullable @Override public InputMethodRequests getInputMethodRequests() { return IdeEventQueue.getInstance().isInputMethodEnabled() ? myEditor.getInputMethodRequests() : null; @@ -184,7 +228,12 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP @Override public void revalidate() { - myEditor.resetPaintersWidth(); + // Null-check necessary because JTextView constructor invokes overridden method (updateUI, which calls revalidate) + // before our own constructor has had a chance to run + //noinspection ConstantConditions + if (myEditor != null) { + myEditor.resetPaintersWidth(); + } super.revalidate(); } @@ -249,296 +298,1203 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP return "EditorComponent file=" + myEditor.getVirtualFile(); } + // ----------------------------------------------------------------------------------------------- + // Accessibility/screen reader support for the editor + // ----------------------------------------------------------------------------------------------- + // Swing supports accessibility via the AccessibleText interface, as well as AccessibleEditableText + // and some other accessibility interfaces. In theory, all we would need to do to support + // accessibility for the IDE editor is to implement these in the accessible context for + // the editor component. + // + // However, it turns out that on some platforms, such as on MacOSX, the accessibility integration + // for Java is hardcoded to only work with JTextComponents! Not only does the code ignore + // property change events announcing caret motion and document changes; it performs specific + // instanceof checks, and the way it adds listeners is to directly add caret and document + // listeners on the JTextComponent. It also performs other JTextComponent operations such + // as looking up the TextUI delegate and performing viewToModel calls, it asks for the Swing + // document's root element and uses it to compute line numbers (and line offset ranges), + // etc. + // + // Therefore, in order to support accessibility for the source editor, we have to make the source + // editor actually extend JTextComponent. However, we don't want to use any of the editor functionality, + // so we use very simple stub implementations for: + // - the caret + // - the document + // - the UI delegate + // and we override various JTextComponent to disable their normal operation. This leaves us with + // (1) an accessible component which extends JTextComponent, and which provides a document and + // a caret instance that the accessibility infrastructure will register listeners with + // (2) the ability to translate real IDE editor events (caret motion, editing events) into + // corresponding Swing events and dispatch these to the caret/document listeners + @Override public AccessibleContext getAccessibleContext() { - if (accessibleContext == null && !myEditor.isDisposed()) { - accessibleContext = new AccessibleEditor(); + if (accessibleContext == null) { + accessibleContext = new AccessibleEditorComponentImpl(); } return accessibleContext; } + private void setupJTextComponentContext() { + setDocument(new EditorAccessibilityDocument()); + setCaret(new EditorAccessibilityCaret()); + } + /** - * @author Konstantin Bulenkov + * We're inheriting method now in order to support accessibility, but you + * should NOT call this method if you have an {@linkplain EditorComponentImpl} + * and you're looking for the real document. */ - protected class AccessibleEditor extends AccessibleJComponent implements AccessibleText, AccessibleAction, AccessibleEditableText, - AccessibleExtendedText, CaretListener, DocumentListener { + @Deprecated + @Override + public javax.swing.text.Document getDocument() { + return super.getDocument(); + } - int caretPos; - Point oldLocationOnScreen; + @Override + public int getCaretPosition() { + return myEditor.getCaretModel().getOffset(); + } - public AccessibleEditor() { - getEditor().getDocument().addDocumentListener(this, myEditor.getDisposable()); - getEditor().getCaretModel().addCaretListener(this); - caretPos = getCaretPosition(); + @Override + public void updateUI() { + // Don't use the default TextUI, BaseTextUI, which does a lot of unnecessary + // work. We do however need to provide a TextUI implementation since some + // screen reader support code will invoke it + setUI(new EditorAccessibilityTextUI()); + invalidate(); + } - try { - oldLocationOnScreen = getLocationOnScreen(); - } - catch (IllegalComponentStateException iae) {// + @Override + public String getToolTipText(MouseEvent event) { + // Undo effect of JTextComponent superclass: this is the default JComponent implementation + return this.getToolTipText(); + } + + /** Redispatch an IDE {@link CaretEvent} to a Swing {@link javax.swing.event.CaretListener} */ + private void fireJTextComponentCaretChange(final CaretEvent event) { + javax.swing.event.CaretEvent swingEvent = new javax.swing.event.CaretEvent(this) { + @Override + public int getDot() { + Caret caret = event.getCaret(); + if (caret != null) { + return caret.getOffset(); + } + return 0; } - EditorComponentImpl.this.addComponentListener(new ComponentAdapter() { + @Override + public int getMark() { + Caret caret = event.getCaret(); + if (caret != null) { + return caret.getLeadSelectionOffset(); + } + return 0; + } + }; + for (javax.swing.event.CaretListener listener : getCaretListeners()) { + listener.caretUpdate(swingEvent); + } + } - public void componentMoved(ComponentEvent e) { - try { - Point newLocationOnScreen = getLocationOnScreen(); - firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, oldLocationOnScreen, newLocationOnScreen); - oldLocationOnScreen = newLocationOnScreen; - } - catch (IllegalComponentStateException iae) {// - } + /** Redispatch an IDE {@link DocumentEvent} to a Swing {@link javax.swing.event.DocumentListener} */ + private void fireJTextComponentDocumentChange(final DocumentEvent event) { + //noinspection deprecation + List listeners = ((EditorAccessibilityDocument)getDocument()).getListeners(); + if (listeners == null) { + return; + } + + javax.swing.event.DocumentEvent swingEvent = new javax.swing.event.DocumentEvent() { + @Override + public int getOffset() { + return event.getOffset(); + } + + @Override + public int getLength() { + return event.getNewLength(); + } + + @Override + public javax.swing.text.Document getDocument() { + //noinspection deprecation + return EditorComponentImpl.this.getDocument(); + } + + @Override + public EventType getType() { + return event.getOldLength() == 0 ? EventType.INSERT : event.getNewLength() == 0 ? EventType.REMOVE : EventType.CHANGE; + } + + @Nullable + @Override + public ElementChange getChange(Element element) { + return null; + } + }; + for (javax.swing.event.DocumentListener listener : listeners) { + javax.swing.event.DocumentEvent.EventType type = swingEvent.getType(); + if (type == javax.swing.event.DocumentEvent.EventType.INSERT) { + listener.insertUpdate(swingEvent); + } else if (type == javax.swing.event.DocumentEvent.EventType.REMOVE) { + listener.removeUpdate(swingEvent); + } else if (type == javax.swing.event.DocumentEvent.EventType.CHANGE) { + listener.changedUpdate(swingEvent); + } + } + } + + private static void notSupported() { + throw new RuntimeException("Not supported for this text implementation"); + } + + /** {@linkplain javax.swing.text.PlainDocument} does a lot of work we don't need. + * This exists simply to be able to send editing events to the screen reader. */ + @SuppressWarnings("UnnecessaryFullyQualifiedName") + private class EditorAccessibilityDocument implements javax.swing.text.Document, javax.swing.text.Element { + private List myListeners; + + @Nullable + public List getListeners() { + return myListeners; + } + + @Override + public int getLength() { + return myEditor.getDocument().getTextLength(); + } + + @Override + public void addDocumentListener(javax.swing.event.DocumentListener documentListener) { + if (myListeners == null) { + myListeners = new ArrayList(2); + } + myListeners.add(documentListener); + } + + @Override + public void removeDocumentListener(javax.swing.event.DocumentListener documentListener) { + if (myListeners != null) { + myListeners.remove(documentListener); + } + } + + @Override + public void addUndoableEditListener(UndoableEditListener undoableEditListener) { + } + + @Override + public void removeUndoableEditListener(UndoableEditListener undoableEditListener) { + } + + @Override + @Nullable + public Object getProperty(Object o) { + return null; + } + + @Override + public void putProperty(Object o, Object o1) { + } + + @Override + public void remove(final int offset, final int length) throws BadLocationException { + editDocumentSafely(offset, length, null); + } + + @Override + public void insertString(final int offset, final String text, AttributeSet attributeSet) throws BadLocationException { + editDocumentSafely(offset, 0, text); + } + + @Override + public String getText(final int offset, final int length) throws BadLocationException { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public String compute() { + return myEditor.getDocument().getText(new TextRange(offset, offset + length)); } }); } - public void caretUpdate(CaretEvent e) { - //int dot = e.getDot(); - //int mark = e.getMark(); - //if (caretPos != dot) { - // // the caret moved - // firePropertyChange(ACCESSIBLE_CARET_PROPERTY, new Integer(caretPos), new Integer(dot)); - // caretPos = dot; - // - // try { - // oldLocationOnScreen = getLocationOnScreen(); - // } - // catch (IllegalComponentStateException iae) {// - // } - //} - //if (mark != dot) { - // // there is a selection - // firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null, getSelectedText()); - //} + @Override + public void getText(int offset, int length, Segment segment) throws BadLocationException { + char[] s = getText(offset, length).toCharArray(); + segment.array = s; + segment.offset = 0; + segment.count = s.length; } - - public void insertUpdate(DocumentEvent e) { - documentUpdated(e.getOffset()); + @Nullable + @Override + public Position getStartPosition() { + notSupported(); + return null; } - protected void documentUpdated(int index) { - final Integer offset = new Integer(index); - if (SwingUtilities.isEventDispatchThread()) { - firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, offset); - } - else { - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { + @Nullable + @Override + public Position getEndPosition() { + notSupported(); + return null; + } + + @Nullable + @Override + public Position createPosition(int i) throws BadLocationException { + notSupported(); + return null; + } + + @Override + public Element[] getRootElements() { + return new Element[] { this }; + } + + @Override + public Element getDefaultRootElement() { + return this; + } + + @Override + public void render(Runnable runnable) { + ApplicationManager.getApplication().runReadAction(runnable); + } + + // ---- Implements Element for the root element ---- + // + // This is here because the accessibility code ends up calling some JTextComponent + // methods; in particular, CAccessibleText calls root.getElementIndex(index) + // to map an offset to a line number, and getRangeForLine calls root.getElement(lineIndex) + // to get a range object for a given line, and then getStartOffset() and getEndOffset() + // on the result. + + @Override + public javax.swing.text.Document getDocument() { + return this; + } + + @Nullable + @Override + public Element getParentElement() { + return null; + } + + @Nullable + @Override + public String getName() { + return null; + } + + @Nullable + @Override + public AttributeSet getAttributes() { + return null; + } + + @Override + public int getStartOffset() { + return 0; + } + + @Override + public int getEndOffset() { + return getLength(); + } + + @Override + public int getElementIndex(int i) { + // For the root element this asks for the index of the offset, which + // means the line number + Document document = myEditor.getDocument(); + return document.getLineNumber(i); + } + + @Override + public int getElementCount() { + Document document = myEditor.getDocument(); + return document.getLineCount(); + } + + @Override + public Element getElement(final int i) { + return new Element() { + @Override + public javax.swing.text.Document getDocument() { + return EditorAccessibilityDocument.this; + } + + @Override + public Element getParentElement() { + return EditorAccessibilityDocument.this; + } + + @Nullable + @Override + public String getName() { + return null; + } + + @Nullable + @Override + public AttributeSet getAttributes() { + return null; + } + + @Override + public int getStartOffset() { + Document document = myEditor.getDocument(); + return document.getLineStartOffset(i); + } + + @Override + public int getEndOffset() { + Document document = myEditor.getDocument(); + return document.getLineEndOffset(i); + } + + @Override + public int getElementIndex(int i) { + return 0; + } + + @Override + public int getElementCount() { + return 0; + } + + @Nullable + @Override + public Element getElement(int i) { + return null; + } + + @Override + public boolean isLeaf() { + return true; + } + }; + } + + @Override + public boolean isLeaf() { + return false; + } + } + + @Override + public void setText(String text) { + editDocumentSafely(0, myEditor.getDocument().getTextLength(), text); + } + + /** Inserts, removes or replaces the given text at the given offset */ + private void editDocumentSafely(final int offset, final int length, @Nullable final String text) { + final Project project = myEditor.getProject(); + final Document document = myEditor.getDocument(); + if (!FileDocumentManager.getInstance().requestWriting(document, project)) { + return; + } + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(document, project) { + @Override public void run() { - firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, offset); + document.startGuardedBlockChecking(); + try { + if (text == null) { + // remove + document.deleteString(offset, offset + length); + } else if (length == 0) { + // insert + document.insertString(offset, text); + } else { + document.replaceString(offset, offset + length, text); + } + } + catch (ReadOnlyFragmentModificationException e) { + EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(document).handle(e); + } + finally { + document.stopGuardedBlockChecking(); + } + } + }); + } + }, "", document, UndoConfirmationPolicy.DEFAULT, document); + } + + /** {@linkplain DefaultCaret} does a lot of work we don't want (listening + * for focus events etc). This exists simply to be able to send caret events to the screen reader. */ + private class EditorAccessibilityCaret implements javax.swing.text.Caret { + @Override + public void install(JTextComponent jTextComponent) { + } + + @Override + public void deinstall(JTextComponent jTextComponent) { + } + + @Override + public void paint(Graphics graphics) { + } + + @Override + public void addChangeListener(ChangeListener changeListener) { + } + + @Override + public void removeChangeListener(ChangeListener changeListener) { + } + + @Override + public boolean isVisible() { + return true; + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public boolean isSelectionVisible() { + return true; + } + + @Override + public void setSelectionVisible(boolean visible) { + } + + @Override + public void setMagicCaretPosition(Point point) { + } + + @Nullable + @Override + public Point getMagicCaretPosition() { + return null; + } + + @Override + public void setBlinkRate(int rate) { + } + + @Override + public int getBlinkRate() { + return 250; + } + + @Override + public int getDot() { + return myEditor.getCaretModel().getOffset(); + } + + @Override + public int getMark() { + return myEditor.getSelectionModel().getSelectionStart(); + } + + @Override + public void setDot(int offset) { + myEditor.getCaretModel().moveToOffset(offset); + } + + @Override + public void moveDot(int offset) { + myEditor.getCaretModel().moveToOffset(offset); + } + } + + /** + * Specialized TextUI intended *only* for accessibility usage. Not all the methods are called; only viewToModel, not modelToView. + */ + private class EditorAccessibilityTextUI extends TextUI { + @Nullable + @Override + public Rectangle modelToView(JTextComponent tc, int offset) throws BadLocationException { + LogicalPosition pos = myEditor.offsetToLogicalPosition(offset); + Point point = myEditor.logicalPositionToXY(pos); + FontMetrics fontMetrics = myEditor.getFontMetrics(Font.PLAIN); + char c = myEditor.getDocument().getCharsSequence().subSequence(offset, offset + 1).charAt(0); + return new Rectangle(point.x, point.y, fontMetrics.charWidth(c), fontMetrics.getHeight()); + } + + @Override + public int viewToModel(JTextComponent tc, Point pt) { + LogicalPosition logicalPosition = myEditor.xyToLogicalPosition(pt); + return myEditor.logicalPositionToOffset(logicalPosition); + } + + @Nullable + @Override + public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias ignored) throws BadLocationException { + return modelToView(tc, pos); + } + + @Override + public int viewToModel(JTextComponent tc, Point pt, Position.Bias[] ignored) { + return viewToModel(tc, pt); + } + + @Override + public int getNextVisualPositionFrom(JTextComponent t, int pos, Position.Bias b, + int direction, + Position.Bias[] biasRet) throws BadLocationException { + notSupported(); + return 0; + } + + @Override + public void damageRange(JTextComponent t, int p0, int p1) { + myEditor.repaint(p0, p1); + } + + @Override + public void damageRange(JTextComponent t, int p0, int p1, Position.Bias ignored1, Position.Bias ignored2) { + damageRange(t, p0, p1); + } + + @Nullable + @Override + public EditorKit getEditorKit(JTextComponent t) { + notSupported(); + return null; + } + + @Nullable + @Override + public View getRootView(JTextComponent t) { + notSupported(); + return null; + } + } + + private static class TextAccessibleRole extends AccessibleRole { + // Can't use AccessibleRole.TEXT: The screen reader verbally refers to it as a text field + // and doesn't do multi-line iteration. (This is hardcoded into the sun/lwawt/macosx implementation.) + // As you can see from JavaAccessibilityUtilities.m, we should use the exact key "textarea" to get + // proper text area handling. + // Note: This is true for MacOS only. For other platform, we need to return the "regular" + // TEXT role to ensure screen readers behave as expected. + @SuppressWarnings("SpellCheckingInspection") + private static final AccessibleRole TEXT_AREA = new TextAccessibleRole("textarea"); + + private TextAccessibleRole(String key) { + super(key); + } + } + + private class AccessibleEditorComponentImpl extends AccessibleJComponent + implements AccessibleText, AccessibleEditableText, AccessibleExtendedText, + CaretListener, DocumentListener { + + public AccessibleEditorComponentImpl() { + myEditor.getCaretModel().addCaretListener(this); + myEditor.getDocument().addDocumentListener(this); + } + + // ---- Implements CaretListener ---- + + private int myCaretPos; + + @Override + public void caretPositionChanged(CaretEvent e) { + Caret caret = e.getCaret(); + if (caret == null) { + return; + } + int dot = caret.getOffset(); + int mark = caret.getLeadSelectionOffset(); + if (myCaretPos != dot) { + ApplicationManager.getApplication().assertIsDispatchThread(); + firePropertyChange(ACCESSIBLE_CARET_PROPERTY, + new Integer(myCaretPos), new Integer(dot)); + + if (SystemInfo.isMac) { + // For MacOSX we also need to fire a caret event to anyone listening + // to our Document, since *that* rather than the accessible property + // change is the only way to trigger a speech update + //fireJTextComponentCaretChange(dot, mark); + fireJTextComponentCaretChange(e); + } + + myCaretPos = dot; + } + + if (mark != dot) { + ApplicationManager.getApplication().assertIsDispatchThread(); + firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null, + getSelectedText()); + } + } + + @Override + public void caretAdded(CaretEvent e) { + } + + @Override + public void caretRemoved(CaretEvent e) { + } + + // ---- Implements DocumentListener ---- + + @Override + public void beforeDocumentChange(DocumentEvent event) { + } + + @Override + public void documentChanged(final DocumentEvent event) { + final Integer pos = event.getOffset(); + if (ApplicationManager.getApplication().isDispatchThread()) { + firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos); + if (SystemInfo.isMac) { + // For MacOSX we also need to fire a JTextComponent event to anyone listening + // to our Document, since *that* rather than the accessible property + // change is the only way to trigger a speech update + fireJTextComponentDocumentChange(event); + } + } else { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos); + fireJTextComponentDocumentChange(event); } }); } } - public void removeUpdate(DocumentEvent e) { - documentUpdated(e.getOffset()); - } + // ---- Implements AccessibleContext ---- - public void changedUpdate(DocumentEvent e) { - documentUpdated(e.getOffset()); - } - - - public AccessibleStateSet getAccessibleStateSet() { - AccessibleStateSet states = super.getAccessibleStateSet(); - if (!EditorComponentImpl.this.getEditor().isViewer()) { - states.add(AccessibleState.EDITABLE); + @Nullable + @Override + public String getAccessibleName() { + if (accessibleName != null) { + return accessibleName; } - if (!getEditor().isOneLineMode()) { - states.add(AccessibleState.MULTI_LINE); + + VirtualFile file = myEditor.getVirtualFile(); + if (file != null) { + return "Editor for " + file.getName(); } - return states; + return "Editor"; } + @Override public AccessibleRole getAccessibleRole() { - return AccessibleRole.TEXT; + // See comment on TextAccessibleRole class. + if (SystemInfo.isMac) { + return TextAccessibleRole.TEXT_AREA; + } else { + return AccessibleRole.TEXT; + } } + @Override public AccessibleText getAccessibleText() { return this; } - public int getIndexAtPoint(Point p) { - if (p == null) { - return -1; - } - final EditorImpl editor = EditorComponentImpl.this.getEditor(); - return editor.logicalPositionToOffset(editor.xyToLogicalPosition(p)); - } - - public Rectangle getCharacterBounds(int i) { - final EditorImpl editor = EditorComponentImpl.this.getEditor(); - final Point point = editor.offsetToXY(i, true); - //todo[kb] more accurate calculation here - final int width = editor.getFontMetrics(Font.PLAIN).charWidth(editor.getDocument().getText().charAt(i)); - return new Rectangle(point, new Dimension(width, editor.getLineHeight())); - } - - public int getCharCount() { - return getEditor().getDocument().getTextLength(); - } - - - public int getCaretPosition() { - return getEditor().getCaretModel().getOffset(); - } - - public AttributeSet getCharacterAttribute(int i) { - return null; //todo[kb] - } - - public int getSelectionStart() { - return getEditor().getSelectionModel().getSelectionStart(); - } - - public int getSelectionEnd() { - return getEditor().getSelectionModel().getSelectionEnd(); - } - - public String getSelectedText() { - return getEditor().getSelectionModel().getSelectedText(); - } - @Override - public void caretPositionChanged(CaretEvent e) { - caretUpdate(e); - } - - @Override - public void caretAdded(CaretEvent e) { - caretUpdate(e); - } - - @Override - public void caretRemoved(CaretEvent e) { - caretUpdate(e); - } - - @Override - public void beforeDocumentChange(com.intellij.openapi.editor.event.DocumentEvent event) { - - } - - @Override - public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent event) { - documentUpdated(event.getOffset()); - } - - public String getAtIndex(int part, int index) { - return getAtIndex(part, index, 0); - } - - public String getAfterIndex(int part, int index) { - return getAtIndex(part, index, 1); - } - - public String getBeforeIndex(int part, int index) { - return getAtIndex(part, index, -1); - } - - private String getAtIndex(int part, int index, int direction) { - return "?"; //todo - } - public AccessibleEditableText getAccessibleEditableText() { return this; } + @Override + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (myEditor.getDocument().isWritable()) { + states.add(AccessibleState.EDITABLE); + } + states.add(AccessibleState.MULTI_LINE); + return states; + } + + // ---- Implements AccessibleText ---- + + @Override + public int getIndexAtPoint(Point point) { + LogicalPosition logicalPosition = myEditor.xyToLogicalPosition(point); + return myEditor.logicalPositionToOffset(logicalPosition); + } + + @Override + public Rectangle getCharacterBounds(int offset) { + // Since we report the very end of the document as being 1 character past the document + // length, we need to validate the offset passed back by the screen reader. + if (offset < 0 || offset > myEditor.getDocument().getTextLength() - 1) { + return null; + } + LogicalPosition pos = myEditor.offsetToLogicalPosition(offset); + Point point = myEditor.logicalPositionToXY(pos); + FontMetrics fontMetrics = myEditor.getFontMetrics(Font.PLAIN); + char c = myEditor.getDocument().getCharsSequence().subSequence(offset, offset + 1).charAt(0); + return new Rectangle(point.x, point.y, fontMetrics.charWidth(c), fontMetrics.getHeight()); + } + + @Override + public int getCharCount() { + return myEditor.getDocument().getTextLength(); + } + + @Override + public int getCaretPosition() { + return myEditor.getCaretModel().getOffset(); + } + + @Nullable + @Override + public String getAtIndex( + @MagicConstant(intValues = { + AccessibleText.CHARACTER, + AccessibleText.WORD, + AccessibleText.SENTENCE}) + int part, + int index) { + return getTextAtOffset(part, index, HERE); + } + + @Nullable + @Override + public String getAfterIndex( + @MagicConstant(intValues = {AccessibleText.CHARACTER, AccessibleText.WORD, AccessibleText.SENTENCE}) + int part, + int index) { + return getTextAtOffset(part, index, AFTER); + } + + @Nullable + @Override + public String getBeforeIndex( + @MagicConstant(intValues = {AccessibleText.CHARACTER, AccessibleText.WORD, AccessibleText.SENTENCE}) + int part, + int index) { + return getTextAtOffset(part, index, BEFORE); + } + + @Override + public AttributeSet getCharacterAttribute(int index) { + return new SimpleAttributeSet(); + } + + @Override + public int getSelectionStart() { + return myEditor.getSelectionModel().getSelectionStart(); + } + + @Override + public int getSelectionEnd() { + return myEditor.getSelectionModel().getSelectionEnd(); + } + + @Nullable + @Override + public String getSelectedText() { + return myEditor.getSelectionModel().getSelectedText(); + } + + // ---- Implements AccessibleEditableText ---- + + @Override public void setTextContents(String s) { - getEditor().getDocument().setText(s); + setText(s); } - + @Override public void insertTextAtIndex(int index, String s) { - getEditor().getDocument().insertString(index, s); + editDocumentSafely(index, 0, s); } + @Override public String getTextRange(int startIndex, int endIndex) { - return getEditor().getDocument().getText(TextRange.create(startIndex, endIndex)); + return myEditor.getDocument().getCharsSequence().subSequence(startIndex, endIndex).toString(); } + @Override public void delete(int startIndex, int endIndex) { - if (!getEditor().isViewer()) { - getEditor().getDocument().deleteString(startIndex, endIndex); - } - else { - UIManager.getLookAndFeel().provideErrorFeedback(EditorComponentImpl.this); - } + editDocumentSafely(startIndex, endIndex - startIndex, null); } + @Override public void cut(int startIndex, int endIndex) { - selectText(startIndex, endIndex); - final DataContext context = DataManager.getInstance().getDataContext(EditorComponentImpl.this); - final CutProvider cutProvider = getEditor().getCutProvider(); - if (cutProvider.isCutEnabled(context)) { - cutProvider.performCut(context); + myEditor.getSelectionModel().setSelection(startIndex, endIndex); + DataContext dataContext = DataManager.getInstance().getDataContext(EditorComponentImpl.this); + CutProvider cutProvider = myEditor.getCutProvider(); + if (cutProvider.isCutEnabled(dataContext)) { + cutProvider.performCut(dataContext); } } + @Override public void paste(int startIndex) { - getEditor().getCaretModel().moveToOffset(startIndex); - final PasteProvider pasteProvider = getEditor().getPasteProvider(); - final DataContext context = DataManager.getInstance().getDataContext(EditorComponentImpl.this); - if (pasteProvider.isPasteEnabled(context)) { - pasteProvider.performPaste(context); + myEditor.getCaretModel().moveToOffset(startIndex); + DataContext dataContext = DataManager.getInstance().getDataContext(EditorComponentImpl.this); + PasteProvider pasteProvider = myEditor.getPasteProvider(); + if (pasteProvider.isPasteEnabled(dataContext)) { + pasteProvider.performPaste(dataContext); } } + @Override public void replaceText(int startIndex, int endIndex, String s) { - getEditor().getDocument().replaceString(startIndex, endIndex, s); + editDocumentSafely(startIndex, endIndex, s); } + @Override public void selectText(int startIndex, int endIndex) { - getEditor().getSelectionModel().setSelection(startIndex, endIndex); + myEditor.getSelectionModel().setSelection(startIndex, endIndex); } + @Override public void setAttributes(int startIndex, int endIndex, AttributeSet as) { - //todo[kb] not supported? } - private AccessibleTextSequence getSequenceAtIndex(int part, int index, int direction) { - //todo[kb] - return null; + // ---- Implements AccessibleExtendedText ---- + + /** Looking for text before the given offset */ + private static final int BEFORE = -1; + /** Looking for text at the given offset */ + private static final int HERE = 0; + /** Looking for text after the given offset */ + private static final int AFTER = 1; + + @Nullable + @Override + public AccessibleTextSequence getTextSequenceAt( + @MagicConstant(intValues = { + AccessibleText.CHARACTER, + AccessibleText.WORD, + AccessibleText.SENTENCE, + AccessibleExtendedText.LINE, + AccessibleExtendedText.ATTRIBUTE_RUN}) + int part, + int index) { + return getSequenceAtIndex(part, index, HERE); } - - public AccessibleTextSequence getTextSequenceAt(int part, int index) { - return getSequenceAtIndex(part, index, 0); + @Nullable + @Override + public AccessibleTextSequence getTextSequenceAfter( + @MagicConstant(intValues = { + AccessibleText.CHARACTER, + AccessibleText.WORD, + AccessibleText.SENTENCE, + AccessibleExtendedText.LINE, + AccessibleExtendedText.ATTRIBUTE_RUN}) + int part, + int index) { + return getSequenceAtIndex(part, index, AFTER); } - public AccessibleTextSequence getTextSequenceAfter(int part, int index) { - return getSequenceAtIndex(part, index, 1); - } - - public AccessibleTextSequence getTextSequenceBefore(int part, int index) { - return getSequenceAtIndex(part, index, -1); + @Nullable + @Override + public AccessibleTextSequence getTextSequenceBefore( + @MagicConstant(intValues = { + AccessibleText.CHARACTER, + AccessibleText.WORD, + AccessibleText.SENTENCE, + AccessibleExtendedText.LINE, + AccessibleExtendedText.ATTRIBUTE_RUN}) + int part, + int index) { + return getSequenceAtIndex(part, index, BEFORE); } + @Override + @Nullable public Rectangle getTextBounds(int startIndex, int endIndex) { - final Point start = getEditor().offsetToXY(startIndex, true); - final Point end = getEditor().offsetToXY(endIndex, true); - if (start.y == end.y) { - return new Rectangle(start, new Dimension(end.x - start.x, getEditor().getLineHeight())); + LogicalPosition startPos = myEditor.offsetToLogicalPosition(startIndex); + Point startPoint = myEditor.logicalPositionToXY(startPos); + Rectangle rectangle = new Rectangle(startPoint); + + LogicalPosition endPos = myEditor.offsetToLogicalPosition(endIndex); + Point endPoint = myEditor.logicalPositionToXY(endPos); + FontMetrics fontMetrics = myEditor.getFontMetrics(Font.PLAIN); + char c = myEditor.getDocument().getCharsSequence().subSequence(endIndex - 1, endIndex).charAt(0); + endPoint.x += fontMetrics.charWidth(c); + endPoint.y += fontMetrics.getHeight(); + rectangle.add(endPoint); + + return rectangle; + } + + @Nullable + private String getTextAtOffset( + @MagicConstant(intValues = {AccessibleText.CHARACTER, AccessibleText.WORD, AccessibleText.SENTENCE}) + int type, + int offset, + @MagicConstant(intValues = {BEFORE, HERE, AFTER}) + int direction) { + DocumentEx document = myEditor.getDocument(); + if (offset < 0 || offset >= document.getTextLength()) { + return null; } - final int width = getEditor().getMaxWidthInRange(startIndex, endIndex); - return new Rectangle(start, new Dimension(width, end.y - start.y + getEditor().getLineHeight())); - } + switch (type) { + case AccessibleText.CHARACTER: { + if (offset + direction < document.getTextLength() && offset + direction >= 0) { + int startOffset = offset + direction; + return document.getCharsSequence().subSequence(startOffset, startOffset + 1).toString(); + } + break; + } - public AccessibleAction getAccessibleAction() { - return this; - } + case AccessibleText.WORD: { + int wordStart = getWordAtOffsetStart(offset, direction); + int wordEnd = getWordAtOffsetEnd(offset, direction); + if (wordStart == -1 || wordEnd == -1) { + return null; + } + return myEditor.getDocument().getCharsSequence().subSequence(wordStart, wordEnd).toString(); + } - public int getAccessibleActionCount() { - return 0; - } + case AccessibleText.SENTENCE: { + int lineStart = getLineAtOffsetStart(offset, direction); + int lineEnd = getLineAtOffsetEnd(offset, direction); + if (lineStart == -1 || lineEnd == -1) { + return null; + } + return document.getCharsSequence().subSequence(lineStart, lineEnd).toString(); + } + + case AccessibleExtendedText.LINE: + case AccessibleExtendedText.ATTRIBUTE_RUN: + // Not expected to be called in this method! + assert false : type; + + default: + break; + } - public String getAccessibleActionDescription(int i) { return null; } - public boolean doAccessibleAction(int i) { - return false; + /** + * Similar to {@link #getTextAtOffset} but returns an {@link AccessibleTextSequence} and can accept a few more types. + */ + @Nullable + private AccessibleTextSequence getSequenceAtIndex( + @MagicConstant(intValues = { + AccessibleText.CHARACTER, + AccessibleText.WORD, + AccessibleText.SENTENCE, + AccessibleExtendedText.LINE, + AccessibleExtendedText.ATTRIBUTE_RUN}) + int type, + int offset, + @MagicConstant(intValues = {BEFORE, HERE, AFTER}) + int direction) { + assert direction == BEFORE || direction == HERE || direction == AFTER; + + DocumentEx document = myEditor.getDocument(); + if (offset < 0 || offset >= document.getTextLength()) { + return null; + } + + switch (type) { + case AccessibleText.CHARACTER: + AccessibleTextSequence charSequence = null; + if (offset + direction < document.getTextLength() && + offset + direction >= 0) { + int startOffset = offset + direction; + charSequence = new AccessibleTextSequence(startOffset, startOffset + 1, + document.getCharsSequence().subSequence(startOffset, startOffset + 1).toString()); + } + return charSequence; + + case AccessibleExtendedText.ATTRIBUTE_RUN: + case AccessibleText.WORD: { + int wordStart = getWordAtOffsetStart(offset, direction); + int wordEnd = getWordAtOffsetEnd(offset, direction); + if (wordStart == -1 || wordEnd == -1) { + return null; + } + return new AccessibleTextSequence(wordStart, wordEnd, + document.getCharsSequence().subSequence(wordStart, wordEnd).toString()); + } + + case AccessibleExtendedText.LINE: + case AccessibleText.SENTENCE: { + int lineStart = getLineAtOffsetStart(offset, direction); + int lineEnd = getLineAtOffsetEnd(offset, direction); + if (lineStart == -1 || lineEnd == -1) { + return null; + } + + return new AccessibleTextSequence(lineStart, lineEnd, + document.getCharsSequence().subSequence(lineStart, lineEnd).toString()); + } + } + return null; + } + + private int getLineAtOffsetStart(int offset) { + Document document = myEditor.getDocument(); + if (offset == 0) { + return 0; + } + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + return document.getLineStartOffset(lineNumber); + } + + private int moveLineOffset(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + if (direction == AFTER) { + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + lineNumber++; + Document document = myEditor.getDocument(); + if (lineNumber == document.getLineCount()) { + return -1; + } + return document.getLineStartOffset(lineNumber); + } else if (direction == BEFORE) { + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + lineNumber--; + if (lineNumber < 0) { + return -1; + } + Document document = myEditor.getDocument(); + return document.getLineStartOffset(lineNumber); + } else { + assert direction == HERE; + return offset; + } + } + + private int getLineAtOffsetStart(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + offset = moveLineOffset(offset, direction); + if (offset == -1) { + return -1; + } + + return getLineAtOffsetStart(offset); + } + + private int getLineAtOffsetEnd(int offset) { + Document document = myEditor.getDocument(); + if (offset == 0) { + return 0; + } + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + return document.getLineEndOffset(lineNumber); + } + + private int getLineAtOffsetEnd(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + offset = moveLineOffset(offset, direction); + if (offset == -1) { + return -1; + } + + return getLineAtOffsetEnd(offset); + } + + private int moveWordOffset(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + if (direction == AFTER) { + Document document = myEditor.getDocument(); + CharSequence text = document.getCharsSequence(); + int maxOffset = document.getTextLength(); + int newOffset = offset - 1; + boolean camel = myEditor.getSettings().isCamelWords(); + for (; newOffset < maxOffset; newOffset++) { + if (EditorActionUtil.isWordEnd(text, newOffset, camel)) { + break; + } + } + newOffset++; + for (; newOffset < maxOffset; newOffset++) { + if (EditorActionUtil.isWordStart(text, newOffset, camel)) { + return newOffset; + } + } + + return -1; + } else if (direction == BEFORE) { + Document document = myEditor.getDocument(); + CharSequence text = document.getCharsSequence(); + int newOffset = offset - 1; + boolean camel = myEditor.getSettings().isCamelWords(); + for (; newOffset >= 0; newOffset--) { + if (EditorActionUtil.isWordStart(text, newOffset, camel)) { + break; + } + } + newOffset--; + for (; newOffset >= 0; newOffset--) { + if (EditorActionUtil.isWordEnd(text, newOffset, camel)) { + return newOffset; + } + } + + return -1; + } else { + assert direction == HERE; + return offset; + } + } + + private int getWordAtOffsetStart(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + offset = moveWordOffset(offset, direction); + if (offset == -1) { + return -1; + } + + return getWordAtOffsetStart(offset); + } + + private int getWordAtOffsetEnd(int offset, @MagicConstant(intValues = {BEFORE, HERE, AFTER}) int direction) { + offset = moveWordOffset(offset, direction); + if (offset == -1) { + return -1; + } + + return getWordAtOffsetEnd(offset); + } + + // Based on CaretImpl#getWordAtCaretStart + private int getWordAtOffsetStart(int offset) { + Document document = myEditor.getDocument(); + if (offset == 0) { + return 0; + } + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + CharSequence text = document.getCharsSequence(); + int newOffset = offset - 1; + int minOffset = lineNumber > 0 ? document.getLineEndOffset(lineNumber - 1) : 0; + boolean camel = myEditor.getSettings().isCamelWords(); + for (; newOffset > minOffset; newOffset--) { + if (EditorActionUtil.isWordStart(text, newOffset, camel)) { + break; + } + } + + return newOffset; + } + + // Based on CaretImpl#getWordAtCaretEnd + private int getWordAtOffsetEnd(int offset) { + Document document = myEditor.getDocument(); + + CharSequence text = document.getCharsSequence(); + if (offset >= document.getTextLength() - 1 || document.getLineCount() == 0) { + return offset; + } + + int newOffset = offset + 1; + int lineNumber = myEditor.offsetToLogicalPosition(offset).line; + int maxOffset = document.getLineEndOffset(lineNumber); + if (newOffset > maxOffset) { + if (lineNumber + 1 >= document.getLineCount()) { + return offset; + } + maxOffset = document.getLineEndOffset(lineNumber + 1); + } + boolean camel = myEditor.getSettings().isCamelWords(); + for (; newOffset < maxOffset; newOffset++) { + if (EditorActionUtil.isWordEnd(text, newOffset, camel)) { + break; + } + } + + return newOffset; } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index 9815a95defb0..2648c5ad17f9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -41,7 +41,9 @@ import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import javax.swing.*; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; @@ -66,7 +68,7 @@ import java.util.List; /** * @author Sergey.Malenkov */ -final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague { +final class SettingsTreeView extends JComponent implements Accessible, Disposable, OptionsEditorColleague { private static final int ICON_GAP = 5; private static final String NODE_ICON = "settings.tree.view.icon"; private static final Color WRONG_CONTENT = JBColor.RED; @@ -865,4 +867,19 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd } } } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleSettingsTreeView(); + } + return accessibleContext; + } + + protected class AccessibleSettingsTreeView extends AccessibleJComponent { + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PANEL; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java index 90eb177e4c57..6b51d07c8dd1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -51,6 +51,7 @@ import com.intellij.util.NotNullFunction; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.MouseEventAdapter; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.accessibility.AccessibleContextUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -289,6 +290,8 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout()); panel.setBorder(JBUI.Borders.empty(4, 6, 4, 6)); panel.add(ref.get()); + AccessibleContextUtil.setName(panel, ref.get()); + AccessibleContextUtil.setDescription(panel, ref.get()); panel.add(createArrow(ref.get()), BorderLayout.EAST); installFocusable(panel, action, KeyEvent.VK_UP, KeyEvent.VK_DOWN, focusListOnLeft); return panel; @@ -325,6 +328,8 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame { link.setPaintUnderline(false); link.setNormalColor(getLinkNormalColor()); button.add(link); + AccessibleContextUtil.setName(button, link); + AccessibleContextUtil.setDescription(button, link); if (action instanceof WelcomePopupAction) { button.add(createArrow(link), BorderLayout.EAST); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrameProvider.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrameProvider.java index cb41f8d70b52..db397479f040 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrameProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrameProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -18,6 +18,7 @@ package com.intellij.openapi.wm.impl.welcomeScreen; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.WelcomeFrameProvider; +import com.intellij.util.PlatformUtils; /** * @author Konstantin Bulenkov @@ -29,6 +30,9 @@ public class FlatWelcomeFrameProvider implements WelcomeFrameProvider { } public static boolean isAvailable() { - return Registry.is("ide.new.welcome.screen"); + return Registry.is("ide.new.welcome.screen.force") || + Registry.is("ide.new.welcome.screen") + && (PlatformUtils.isIntelliJ() || PlatformUtils.isCidr() || PlatformUtils.isWebStorm() || + PlatformUtils.isPyCharm() || PlatformUtils.isRubyMine() || PlatformUtils.isPhpStorm()); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java index 9b946f6b6eaf..ff03d3b36d42 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java @@ -31,6 +31,7 @@ import com.intellij.util.IconUtil; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.accessibility.AccessibleContextUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -279,6 +280,8 @@ public class NewRecentProjectPanel extends RecentProjectPanel { panel.add(projectIcon, BorderLayout.WEST); add(panel); } + AccessibleContextUtil.setCombinedName(this, name, " - ", path); + AccessibleContextUtil.setCombinedDescription(this, name, " - ", path); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java index dcd57ed3410a..c28d1427600f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java @@ -46,6 +46,7 @@ import com.intellij.util.Function; import com.intellij.util.SystemProperties; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.accessibility.AccessibleContextUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,6 +57,7 @@ import java.awt.event.*; import java.io.File; public class RecentProjectPanel extends JPanel { + public static final String RECENT_PROJECTS_LABEL = "Recent Projects"; protected final JBList myList; protected final UniqueNameBuilder myPathShortener; protected AnAction removeRecentProjectAction; @@ -306,7 +308,7 @@ public class RecentProjectPanel extends JPanel { }; title.setBorder(new BottomLineBorder()); - JLabel titleLabel = new JLabel("Recent Projects"); + JLabel titleLabel = new JLabel(RECENT_PROJECTS_LABEL); title.add(titleLabel); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setForeground(WelcomeScreenColors.CAPTION_FOREGROUND); @@ -323,6 +325,7 @@ public class RecentProjectPanel extends JPanel { mySize = size; setEmptyText(" No Project Open Yet "); setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + getAccessibleContext().setAccessibleName(RECENT_PROJECTS_LABEL); final MouseHandler handler = new MouseHandler(); addMouseListener(handler); addMouseMotionListener(handler); @@ -440,6 +443,8 @@ public class RecentProjectPanel extends JPanel { myName.setText(group.getGroup().getName()); myPath.setText(""); } + AccessibleContextUtil.setCombinedName(this, myName, " - ", myPath); + AccessibleContextUtil.setCombinedDescription(this, myName, " - ", myPath); return this; } diff --git a/platform/platform-impl/src/com/intellij/ui/CardLayoutPanel.java b/platform/platform-impl/src/com/intellij/ui/CardLayoutPanel.java index e3baec91e85f..6f5eff4ba987 100644 --- a/platform/platform-impl/src/com/intellij/ui/CardLayoutPanel.java +++ b/platform/platform-impl/src/com/intellij/ui/CardLayoutPanel.java @@ -21,6 +21,9 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.util.ActionCallback; import com.intellij.util.ui.JBInsets; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; import javax.swing.JComponent; import java.awt.*; import java.util.IdentityHashMap; @@ -34,7 +37,7 @@ import java.util.Map.Entry; * * @author Sergey.Malenkov */ -public abstract class CardLayoutPanel extends JComponent implements Disposable { +public abstract class CardLayoutPanel extends JComponent implements Accessible, Disposable { private final IdentityHashMap myContent = new IdentityHashMap(); private volatile boolean myDisposed; private K myKey; @@ -198,4 +201,19 @@ public abstract class CardLayoutPanel extends JCompo } myContent.clear(); } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleCardLayoutPanel(); + } + return accessibleContext; + } + + protected class AccessibleCardLayoutPanel extends AccessibleJComponent { + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.PANEL; + } + } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 1d09e4d18c56..c19876254bff 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -274,7 +274,7 @@ vcs.show.history.numbers=true navBar.updateMergeTime=100 navBar.userActivityMergeTime=100 -ide.mac.fix.accessibleLeak=true +ide.mac.fix.accessibleLeak=false projectView.showHierarchyErrors=true projectView.hide.dot.idea=true @@ -581,6 +581,7 @@ decompiler.dump.original.lines.description=Show original line numbers as comment ide.transparency.mode.for.windows=false ide.transparency.mode.for.windows.description=Allow to add transparency to floating windows ide.new.welcome.screen=true +ide.new.welcome.screen.force=false enable.recursive.document.changes=false enable.recursive.document.changes.description=Enables performing document changes in document event listeners (this breaks undo/redo functionality!) diff --git a/platform/util/src/com/intellij/util/ui/accessibility/AccessibleContextUtil.java b/platform/util/src/com/intellij/util/ui/accessibility/AccessibleContextUtil.java new file mode 100644 index 000000000000..345e5b1c7bff --- /dev/null +++ b/platform/util/src/com/intellij/util/ui/accessibility/AccessibleContextUtil.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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.ui.accessibility; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class AccessibleContextUtil { + public static void setName(@NotNull JComponent component, @NotNull JComponent source) { + String name = source.getAccessibleContext().getAccessibleName(); + if (name != null) { + component.getAccessibleContext().setAccessibleName(name); + } + } + + public static void setCombinedName(@NotNull JComponent component, + @NotNull JComponent j1, @NotNull String separator, @NotNull JComponent j2) { + component.getAccessibleContext().setAccessibleName( + combineAccessibleStrings( + j1.getAccessibleContext().getAccessibleName(), + separator, + j2.getAccessibleContext().getAccessibleName())); + } + + public static void setCombinedName(@NotNull JComponent component, + @NotNull JComponent j1, @NotNull String separator1, + @NotNull JComponent j2, @NotNull String separator2, @NotNull JComponent j3) { + component.getAccessibleContext().setAccessibleName( + combineAccessibleStrings( + j1.getAccessibleContext().getAccessibleName(), + separator1, + j2.getAccessibleContext().getAccessibleName(), + separator2, + j3.getAccessibleContext().getAccessibleName())); + } + + public static void setDescription(@NotNull JComponent component, @NotNull JComponent source) { + String description = source.getAccessibleContext().getAccessibleDescription(); + if (description != null) { + component.getAccessibleContext().setAccessibleDescription(description); + } + } + + public static void setCombinedDescription(@NotNull JComponent component, @NotNull JComponent j1, + @NotNull String separator, @NotNull JComponent j2) { + component.getAccessibleContext().setAccessibleDescription( + combineAccessibleStrings( + j1.getAccessibleContext().getAccessibleDescription(), + separator, + j2.getAccessibleContext().getAccessibleDescription())); + } + + public static void setCombinedDescription(@NotNull JComponent component, @NotNull JComponent j1, @NotNull String separator1, + @NotNull JComponent j2, @NotNull String separator2, @NotNull JComponent j3) { + component.getAccessibleContext().setAccessibleDescription( + combineAccessibleStrings( + j1.getAccessibleContext().getAccessibleDescription(), + separator1, + j2.getAccessibleContext().getAccessibleDescription(), + separator2, + j3.getAccessibleContext().getAccessibleDescription())); + } + + public static @Nullable String combineAccessibleStrings(@Nullable String s1, @NotNull String separator, @Nullable String s2) { + if (StringUtil.isEmpty(s1)) + return s2; + if (StringUtil.isEmpty(s2)) + return s1; + return String.format("%s%s%s", s1, separator, s2); + } + + public static @Nullable String combineAccessibleStrings(@Nullable String s1, @NotNull String separator1, @Nullable String s2, + @NotNull String separator2, @Nullable String s3) { + return combineAccessibleStrings(combineAccessibleStrings(s1, separator1, s2), separator2, s3); + } +} From 0f05fa3d5dacb1bde426da7eb62111a9ab0db971 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 15 Jan 2016 16:47:28 +0100 Subject: [PATCH 154/825] wrap borders --- .../src/com/intellij/openapi/wm/impl/IdeMenuBar.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java index 8bd84b1c57cf..d635d7cb55cb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java @@ -37,8 +37,8 @@ import com.intellij.openapi.wm.impl.status.ClockPanel; import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; import com.intellij.ui.ScreenUtil; -import com.intellij.ui.border.CustomLineBorder; import com.intellij.util.ui.Animator; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.MouseEventAdapter; import com.intellij.util.ui.UIUtil; import org.java.ayatana.ApplicationMenu; @@ -47,7 +47,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -127,17 +126,17 @@ public class IdeMenuBar extends JMenuBar implements IdeEventQueue.EventDispatche public Border getBorder() { //avoid moving lines if (myState == State.EXPANDING || myState == State.COLLAPSING) { - return new EmptyBorder(0,0,0,0); + return JBUI.Borders.empty(); } //fix for Darcula double border if (myState == State.TEMPORARY_EXPANDED && UIUtil.isUnderDarcula()) { - return new CustomLineBorder(Gray._75, 0, 0, 1, 0); + return JBUI.Borders.customLine(Gray._75, 0, 0, 1, 0); } //save 1px for mouse handler if (myState == State.COLLAPSED) { - return new EmptyBorder(0, 0, 1, 0); + return JBUI.Borders.emptyBottom(1); } return UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR ? super.getBorder() : null; From c81d426b2c08777f093c93c51aceab3420f6e6d4 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 15 Jan 2016 19:23:56 +0300 Subject: [PATCH 155/825] IDEA-150411 Debug tool window: on reusing it different type of configuration picks up watches from previous type --- .../xdebugger/impl/XDebugSessionImpl.java | 20 +++++++++++++------ .../xdebugger/impl/XDebuggerManagerImpl.java | 11 +++++----- .../xdebugger/impl/ui/XDebugSessionData.java | 11 ++++++++-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 8fc655016873..8e3126afe70f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -262,10 +262,9 @@ public class XDebugSessionImpl implements XDebugSession { return myTopFramePosition; } - public XDebugSessionTab init(@NotNull XDebugProcess process, @NotNull XDebugSessionData sessionData, @Nullable RunContentDescriptor contentToReuse) { + XDebugSessionTab init(@NotNull XDebugProcess process, @Nullable RunContentDescriptor contentToReuse) { LOG.assertTrue(myDebugProcess == null); myDebugProcess = process; - mySessionData = sessionData; if (myDebugProcess.checkCanInitBreakpoints()) { initBreakpoints(); @@ -287,6 +286,14 @@ public class XDebugSessionImpl implements XDebugSession { return mySessionTab; } + void initSessionData(@Nullable XDebugSessionData sessionData) { + String currentConfigurationName = getConfigurationName(); + if (sessionData == null || !sessionData.getConfigurationName().equals(currentConfigurationName)) { + sessionData = new XDebugSessionData(getWatchExpressions(), currentConfigurationName); + } + mySessionData = sessionData; + } + public void reset() { breakpointsInitialized = false; } @@ -1013,7 +1020,8 @@ public class XDebugSessionImpl implements XDebugSession { } } - private String getWatchesKey() { + @NotNull + private String getConfigurationName() { if (myEnvironment != null) { RunProfile profile = myEnvironment.getRunProfile(); if (profile instanceof RunConfiguration) { @@ -1025,13 +1033,13 @@ public class XDebugSessionImpl implements XDebugSession { public void setWatchExpressions(@NotNull XExpression[] watchExpressions) { mySessionData.setWatchExpressions(watchExpressions); - myDebuggerManager.getWatchesManager().setWatches(getWatchesKey(), watchExpressions); + myDebuggerManager.getWatchesManager().setWatches(getConfigurationName(), watchExpressions); if (Registry.is("debugger.watches.in.variables")) { rebuildViews(); } } XExpression[] getWatchExpressions() { - return myDebuggerManager.getWatchesManager().getWatches(getWatchesKey()); + return myDebuggerManager.getWatchesManager().getWatches(getConfigurationName()); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 2d328cca9332..fa1a381c91a8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -226,17 +226,16 @@ public class XDebuggerManagerImpl extends XDebuggerManager oldSessionData = XDebugSessionData.DATA_KEY.getData(DataManager.getInstance().getDataContext(component)); } } - if (oldSessionData == null) { - oldSessionData = new XDebugSessionData(session.getWatchExpressions()); - } + + session.initSessionData(oldSessionData); // Perform custom configuration of session data for XDebugProcessConfiguratorStarter classes if (processStarter instanceof XDebugProcessConfiguratorStarter) { session.activateSession(); - ((XDebugProcessConfiguratorStarter)processStarter).configure(oldSessionData); + ((XDebugProcessConfiguratorStarter)processStarter).configure(session.getSessionData()); } - session.init(process, oldSessionData, contentToReuse); + session.init(process, contentToReuse); mySessions.put(session.getDebugProcess().getProcessHandler(), session); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java index 08bf63aea430..924b3a567c4a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -27,10 +27,12 @@ public class XDebugSessionData { @NotNull private XExpression[] myWatchExpressions; + private final String myConfigurationName; private boolean myBreakpointsMuted = false; - public XDebugSessionData(final @NotNull XExpression[] watchExpressions) { + public XDebugSessionData(@NotNull XExpression[] watchExpressions, @NotNull String configurationName) { myWatchExpressions = watchExpressions; + myConfigurationName = configurationName; } public void setWatchExpressions(@NotNull XExpression[] watchExpressions) { @@ -49,4 +51,9 @@ public class XDebugSessionData { public void setBreakpointsMuted(boolean breakpointsMuted) { myBreakpointsMuted = breakpointsMuted; } + + @NotNull + public String getConfigurationName() { + return myConfigurationName; + } } From 62ce78ab5f7ee70684c32abecb7e09da73bebaa1 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 15 Jan 2016 12:31:16 +0100 Subject: [PATCH 156/825] cleanup, prefer additionalVariable because it is more smart variable (e.g. NavigatableVariable) --- .../src/org/jetbrains/concurrency/promise.kt | 9 +++- .../backend/src/EvaluateContextBase.kt | 4 +- .../debugger/MemberFilterWithNameMappings.kt | 8 +--- .../org/jetbrains/debugger/VariableView.kt | 10 ++--- .../src/org/jetbrains/debugger/Variables.kt | 45 +++++++++++++------ 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt b/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt index a198438ea378..d3e1ba53bf1a 100644 --- a/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt +++ b/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt @@ -45,14 +45,19 @@ inline fun Promise.done(node: Obsolescent, crossinline handler: (T) -> Un override fun consume(param: T) = handler(param) }) +@Suppress("UNCHECKED_CAST") +inline fun Promise<*>.processed(node: Obsolescent, crossinline handler: () -> Unit) = (this as Promise).processed(object : ObsolescentConsumer(node) { + override fun consume(param: Any?) = handler() +}) + @Suppress("UNCHECKED_CAST") inline fun Promise<*>.doneRun(crossinline handler: () -> Unit) = (this as Promise).done { handler() } @Suppress("UNCHECKED_CAST") -inline fun Promise<*>.then(crossinline handler: () -> Unit): Promise<*> = (this as Promise).then { it: Any? -> handler() } +inline fun Promise<*>.then(crossinline handler: () -> T): Promise = (this as Promise).then { handler() } @Suppress("UNCHECKED_CAST") -inline fun Promise<*>.processed(crossinline handler: () -> Unit): Promise<*> = (this as Promise).processed { it: Any? -> handler() } +inline fun Promise<*>.processed(crossinline handler: () -> Unit): Promise<*> = (this as Promise).processed { handler() } inline fun Promise.thenAsync(node: Obsolescent, crossinline handler: (T) -> Promise) = thenAsync(object : ValueNodeAsyncFunction(node) { diff --git a/platform/script-debugger/backend/src/EvaluateContextBase.kt b/platform/script-debugger/backend/src/EvaluateContextBase.kt index 9477f118f5c7..b3c6625be6f8 100644 --- a/platform/script-debugger/backend/src/EvaluateContextBase.kt +++ b/platform/script-debugger/backend/src/EvaluateContextBase.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -22,5 +22,5 @@ import org.jetbrains.debugger.values.ValueManager abstract class EvaluateContextBase(val valueManager: VALUE_MANAGER) : EvaluateContext { override fun withValueManager(objectGroup: String) = this - override fun refreshOnDone(promise: Promise<*>): Promise<*> = (promise as Promise).then { valueManager.clearCaches() } + override fun refreshOnDone(promise: Promise<*>): Promise<*> = promise.then { valueManager.clearCaches() } } \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/MemberFilterWithNameMappings.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/MemberFilterWithNameMappings.kt index f273d77539e7..b1f0cb06b10d 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/MemberFilterWithNameMappings.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/MemberFilterWithNameMappings.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -16,11 +16,7 @@ package org.jetbrains.debugger open class MemberFilterWithNameMappings(rawNameToSource: Map?) : MemberFilter { - protected val rawNameToSource: Map - - init { - this.rawNameToSource = rawNameToSource ?: emptyMap() - } + protected val rawNameToSource = rawNameToSource ?: emptyMap() override fun hasNameMappings(): Boolean { return !rawNameToSource.isEmpty() diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.kt index 904ae71baabe..f39968f7cda9 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -178,9 +178,7 @@ class VariableView(name: String, private val variable: Variable, private val con } if (hasIndexedProperties == hasNamedProperties || additionalProperties != null) { - (Promise.all(promises) as Promise).processed(object : ObsolescentConsumer(node) { - override fun consume(aVoid: Any?) = node.addChildren(XValueChildrenList.EMPTY, true) - }) + Promise.all(promises).processed(node) { node.addChildren(XValueChildrenList.EMPTY, true) } } } @@ -302,8 +300,8 @@ class VariableView(name: String, private val variable: Variable, private val con } override fun setValue(expression: String, callback: XValueModifier.XModificationCallback) { - (variable.valueModifier!!.setValue(variable, expression, evaluateContext) as Promise) - .done { + variable.valueModifier!!.setValue(variable, expression, evaluateContext) + .doneRun { value = null callback.valueModified() } diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.kt index 55464c82ff98..79b76dc874c6 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -29,9 +29,7 @@ import java.util.regex.Pattern private val UNNAMED_FUNCTION_PATTERN = Pattern.compile("^function[\\t ]*\\(") -private val NATURAL_NAME_COMPARATOR = object : Comparator { - override fun compare(o1: Variable, o2: Variable) = naturalCompare(o1.name, o2.name) -} +private val NATURAL_NAME_COMPARATOR = Comparator { o1, o2 -> naturalCompare(o1.name, o2.name) } // start properties loading to achieve, possibly, parallel execution (properties loading & member filter computation) fun processVariables(context: VariableContext, @@ -69,10 +67,10 @@ fun processScopeVariables(scope: Scope, } val comparator = if (memberFilter.hasNameMappings()) comparator { o1, o2 -> naturalCompare(memberFilter.rawNameToSource(o1), memberFilter.rawNameToSource(o2)) } else NATURAL_NAME_COMPARATOR - Collections.sort(properties, comparator) - Collections.sort(functions, comparator) + properties.sortWith(comparator) + functions.sortWith(comparator) - addAditionalVariables(variables, additionalVariables, properties, memberFilter) + addAditionalVariables(additionalVariables, properties, memberFilter) if (!properties.isEmpty()) { node.addChildren(createVariablesList(properties, context, memberFilter), functions.isEmpty() && isLast) @@ -124,22 +122,41 @@ fun filterAndSort(variables: List, memberFilter: MemberFilter): List, - additionalVariables: Collection, +private fun addAditionalVariables(additionalVariables: Collection, result: MutableList, - memberFilter: MemberFilter) { + memberFilter: MemberFilter, + functions: MutableList? = null) { + val oldSize = result.size ol@ for (variable in additionalVariables) { - for (frameVariable in variables) { - if (memberFilter.rawNameToSource(frameVariable) == memberFilter.rawNameToSource(variable)) { + for (i in 0..(oldSize - 1)) { + val vmVariable = result[i] + if (memberFilter.rawNameToSource(vmVariable) == memberFilter.rawNameToSource(variable)) { + // we prefer additionalVariable here because it is more smart variable (e.g. NavigatableVariable) + val vmValue = vmVariable.value + // to avoid evaluation, use vm value directly + if (vmValue != null && variable.value == null) { + variable.value = vmValue + } + + result.set(i, variable) continue@ol } } + + if (functions != null) { + for (function in functions) { + if (memberFilter.rawNameToSource(function) == memberFilter.rawNameToSource(variable)) { + continue@ol + } + } + } + result.add(variable) } } From 9cafbdfd18f2fb322cc7995ca188acece90581fb Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 15 Jan 2016 12:37:08 +0100 Subject: [PATCH 157/825] =?UTF-8?q?avoid=20new=20ArrayList=20creation=20?= =?UTF-8?q?=E2=80=94=20doesn't=20make=20any=20sense,=20add=20directly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/IdentifierHighlighterPass.java | 15 ++++++----- .../highlighting/HighlightUsagesHandler.java | 26 ++++++++++++++----- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java index aa6cce31a5cc..d01d5682669a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -129,8 +129,8 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { * @return a pair where first element is read usages and second is write usages */ public static Couple> getHighlightUsages(@NotNull PsiElement target, PsiElement psiElement, boolean withDeclarations) { - Collection readRanges = new ArrayList(); - Collection writeRanges = new ArrayList(); + List readRanges = new ArrayList(); + List writeRanges = new ArrayList(); final ReadWriteAccessDetector detector = ReadWriteAccessDetector.findDetector(target); final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(target.getProject())).getFindUsagesManager(); final FindUsagesHandler findUsagesHandler = findUsagesManager.getFindUsagesHandler(target, true); @@ -143,13 +143,14 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { LOG.error("Null reference returned, findUsagesHandler=" + findUsagesHandler + "; target=" + target + " of " + target.getClass()); continue; } - final List textRanges = HighlightUsagesHandler.getRangesToHighlight(psiReference); + List destination; if (detector == null || detector.getReferenceAccess(target, psiReference) == ReadWriteAccessDetector.Access.Read) { - readRanges.addAll(textRanges); + destination = readRanges; } else { - writeRanges.addAll(textRanges); + destination = writeRanges; } + HighlightUsagesHandler.collectRangesToHighlight(psiReference, destination); } if (withDeclarations) { @@ -164,7 +165,7 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { } } - return Couple.of(readRanges, writeRanges); + return Couple.>of(readRanges, writeRanges); } private void highlightTargetUsages(@NotNull PsiElement target) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java index b19ade8c20e7..3d9db0b9044e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -406,21 +406,35 @@ public class HighlightUsagesHandler extends HighlightHandlerBase { TextAttributes attributes, boolean clearHighlights) { List textRanges = new ArrayList(refs.size()); for (PsiReference ref : refs) { - textRanges.addAll(getRangesToHighlight(ref)); + collectRangesToHighlight(ref, textRanges); } highlightRanges(highlightManager, editor, attributes, clearHighlights, textRanges); } - public static List getRangesToHighlight(final PsiReference ref) { + @SuppressWarnings("unused") + @NotNull + @Deprecated + /** + * @deprecated Use {@link #collectRangesToHighlight} + */ + public static List getRangesToHighlight(@NotNull PsiReference ref) { + return collectRangesToHighlight(ref, null); + } + + @NotNull + public static List collectRangesToHighlight(@NotNull PsiReference ref, @Nullable List result) { final List relativeRanges = ReferenceRange.getRanges(ref); - List answer = new ArrayList(relativeRanges.size()); + if (result == null) { + result = new ArrayList(relativeRanges.size()); + } + for (TextRange relativeRange : relativeRanges) { PsiElement element = ref.getElement(); TextRange range = safeCut(element.getTextRange(), relativeRange); // injection occurs - answer.add(InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, range)); + result.add(InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, range)); } - return answer; + return result; } private static TextRange safeCut(TextRange range, TextRange relative) { From 9995adfde4b4197b3e2a7597730e16904faec8f5 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 15 Jan 2016 12:51:16 +0100 Subject: [PATCH 158/825] =?UTF-8?q?getUsages=20=E2=80=94=20in=20most=20cas?= =?UTF-8?q?es=20we=20don't=20need=20to=20detect=20access?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../debugger/impl/DebuggerContextUtil.java | 12 +++--------- .../impl/IdentifierHighlighterPass.java | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java index 564c1a75fea9..67749f3b4588 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -27,7 +27,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; -import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -37,9 +36,7 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; public class DebuggerContextUtil { public static void setStackFrame(final DebuggerStateManager manager, final StackFrameProxyImpl stackFrame) { @@ -98,11 +95,8 @@ public class DebuggerContextUtil { //final Editor editor = fileEditor instanceof TextEditorImpl ? ((TextEditorImpl)fileEditor).getEditor() : null; if (editor != null && position != null && file.getVirtualFile().equals(position.getFile())) { PsiMethod method = PsiTreeUtil.getParentOfType(PositionUtil.getContextElement(context), PsiMethod.class, false); - final Couple> usages = - IdentifierHighlighterPass.getHighlightUsages(psi, method != null ? method : file, false); - final List ranges = new ArrayList(); - ranges.addAll(usages.first); - ranges.addAll(usages.second); + final Collection ranges = + IdentifierHighlighterPass.getUsages(psi, method != null ? method : file, false); final int breakPointLine = position.getLine(); int bestLine = -1; int bestOffset = -1; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java index d01d5682669a..ecce5532102d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java @@ -128,10 +128,27 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { * @param psiElement psi element to search in * @return a pair where first element is read usages and second is write usages */ + @NotNull public static Couple> getHighlightUsages(@NotNull PsiElement target, PsiElement psiElement, boolean withDeclarations) { + return getUsages(target, psiElement, withDeclarations, true); + } + + /** + * Returns usages of psi element inside a single element + * + * @param target target psi element + * @param psiElement psi element to search in + */ + @NotNull + public static Collection getUsages(@NotNull PsiElement target, PsiElement psiElement, boolean withDeclarations) { + return getUsages(target, psiElement, withDeclarations, false).first; + } + + @NotNull + private static Couple> getUsages(@NotNull PsiElement target, PsiElement psiElement, boolean withDeclarations, boolean detectAccess) { List readRanges = new ArrayList(); List writeRanges = new ArrayList(); - final ReadWriteAccessDetector detector = ReadWriteAccessDetector.findDetector(target); + final ReadWriteAccessDetector detector = detectAccess ? ReadWriteAccessDetector.findDetector(target) : null; final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(target.getProject())).getFindUsagesManager(); final FindUsagesHandler findUsagesHandler = findUsagesManager.getFindUsagesHandler(target, true); final LocalSearchScope scope = new LocalSearchScope(psiElement); From fb9997aa1b4e722d4473cae3a17fea6cf6ff7f0c Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 15 Jan 2016 17:02:46 +0100 Subject: [PATCH 159/825] =?UTF-8?q?js=20debugger=20inline=20data=20?= =?UTF-8?q?=E2=80=94=20add=20for=20all=20usage=20places?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jetbrains/debugger/SourceInfo.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/SourceInfo.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/SourceInfo.java index f1c899be3e04..47485237899c 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/SourceInfo.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/SourceInfo.java @@ -1,3 +1,18 @@ +/* + * 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. + */ package org.jetbrains.debugger; import com.intellij.openapi.application.AccessToken; @@ -21,11 +36,12 @@ public class SourceInfo implements XSourcePosition { private int offset = -1; - private SourceInfo(@Nullable String functionName, @NotNull VirtualFile file, int line, int column) { + public SourceInfo(@Nullable String functionName, @NotNull VirtualFile file, int line, int column, int offset) { this.functionName = functionName; this.file = file; this.line = line; this.column = column; + this.offset = offset; } @Nullable @@ -33,7 +49,7 @@ public class SourceInfo implements XSourcePosition { if (file == null || !file.isValid()) { return null; } - return new SourceInfo(functionName, file, line, column); + return new SourceInfo(functionName, file, line, column, -1); } @Nullable @@ -80,7 +96,7 @@ public class SourceInfo implements XSourcePosition { @NotNull @Override public Navigatable createNavigatable(@NotNull Project project) { - return new OpenFileDescriptor(project, getFile(), getLine(), getColumn()); + return new OpenFileDescriptor(project, file, line, column); } @Override From 5b88e640e4c9fbc2258a2c1987bd0d3c09f442c8 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Fri, 15 Jan 2016 21:50:27 +0300 Subject: [PATCH 160/825] get/set env data with single method call for convenient client usage --- .../configuration/EnvironmentVariablesComponent.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java index 098cd4b186ca..adbb73406e86 100644 --- a/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java +++ b/platform/lang-impl/src/com/intellij/execution/configuration/EnvironmentVariablesComponent.java @@ -66,6 +66,15 @@ public class EnvironmentVariablesComponent extends LabeledComponent envs) { final Element envsElement = element.getChild(ENVS); if (envsElement != null) { From b725bdf94b4fc7da34ec3aa8d61a319a918be28b Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 30 Apr 2015 18:40:30 +0300 Subject: [PATCH 161/825] [vcs-log] refactor branches panel: use components for groups + flow layout for proper gaps; use scrollpane --- .../vcs/log/ui/frame/BranchesPanel.java | 253 +++++------------- .../intellij/vcs/log/ui/frame/MainFrame.java | 3 +- 2 files changed, 73 insertions(+), 183 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 64b3cef909f0..3ba4c560d5e4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -1,16 +1,11 @@ package com.intellij.vcs.log.ui.frame; -import com.google.common.collect.Ordering; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.ListUtil; import com.intellij.ui.awt.RelativePoint; -import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.RefsModel; import com.intellij.vcs.log.data.VcsLogDataHolder; @@ -23,9 +18,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.EmptyBorder; import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Collection; @@ -39,46 +33,25 @@ import java.util.Map; public class BranchesPanel extends JPanel { private static final int SMALL_ROOTS_GAP = 3; private static final int BIG_ROOTS_GAP = 7; - private static final int VERTICAL_SPACE = 3; - private final VcsLogDataHolder myDataHolder; - private final VcsLogUiImpl myUI; + private static final int TOP = 0; + private static final int BOTTOM = 3; + @NotNull private final VcsLogDataHolder myDataHolder; + @NotNull private final VcsLogUiImpl myUI; + @NotNull private final VcsRefPainter myReferencePainter; - private LinkedHashMap> myRefGroups; - private final VcsRefPainter myReferencePainter; + @NotNull private LinkedHashMap> myRefGroups; @Nullable private Collection myRoots = null; - private Map myRefPositions = ContainerUtil.newHashMap(); - public BranchesPanel(@NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUiImpl UI, @NotNull RefsModel initialRefsModel) { + super(new FlowLayout(FlowLayout.LEADING, BIG_ROOTS_GAP - 2 * SMALL_ROOTS_GAP, 0)); + setBorder(new EmptyBorder(TOP, SMALL_ROOTS_GAP, BOTTOM, SMALL_ROOTS_GAP)); + myDataHolder = dataHolder; myUI = UI; myRefGroups = getRefsToDisplayOnPanel(initialRefsModel); myReferencePainter = new VcsRefPainter(myUI.getColorManager(), true); - setPreferredSize(new Dimension(-1, myReferencePainter.getHeight(this) + UIUtil.DEFAULT_VGAP + VERTICAL_SPACE)); - - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (!myUI.getMainFrame().areGraphActionsEnabled()) { - return; - } - - final RefGroup group = findRef(e); - if (group == null) { - return; - } - if (group.getRefs().size() == 1) { - VcsRef ref = group.getRefs().iterator().next(); - myUI.jumpToCommit(ref.getCommitHash(), ref.getRoot()); - } - else { - final ReferencePopupComponent view = new ReferencePopupComponent(group, myUI, myReferencePainter); - JBPopup popup = view.getPopup(); - popup.show(new RelativePoint(BranchesPanel.this, new Point(e.getX(), BranchesPanel.this.getHeight()))); - } - } - }); + recreateComponents(); myUI.addLogListener(new VcsLogListener() { @Override @@ -90,49 +63,19 @@ public class BranchesPanel extends JPanel { }); } - @Override - public Dimension getPreferredSize() { - return new Dimension(-1, myReferencePainter.getHeight(this) + 10); - } - - @Nullable - private RefGroup findRef(MouseEvent e) { - List sortedPositions = Ordering.natural().sortedCopy(myRefPositions.keySet()); - int index = Ordering.natural().binarySearch(sortedPositions, e.getX()); - if (index < 0) { - index = -index - 2; - } - if (index < 0) { - return null; - } - return myRefPositions.get(sortedPositions.get(index)); - } - - @Override - protected void paintComponent(Graphics g) { - myRefPositions = ContainerUtil.newHashMap(); - int paddingX = BIG_ROOTS_GAP; + private void recreateComponents() { for (Map.Entry> entry : myRefGroups.entrySet()) { - VirtualFile root = entry.getKey(); - for (RefGroup group : entry.getValue()) { - // it is assumed here that all refs in a single group belong to a single root - if (myRoots == null || myRoots.contains(root)) { - Color rootIndicatorColor = VcsLogColorManagerImpl.getIndicatorColor(myUI.getColorManager().getRootColor(root)); - Rectangle rectangle = myReferencePainter - .paint(group.getName(), g, paddingX, (getHeight() - myReferencePainter.getHeight(this)) / 2 - VERTICAL_SPACE, - group.getBgColor(), - rootIndicatorColor); - paddingX += rectangle.width + SMALL_ROOTS_GAP; - myRefPositions.put(rectangle.x, group); - } + if (myRoots == null || myRoots.contains(entry.getKey())) { + add(new RootGroupComponent(entry.getValue(), entry.getKey())); } - paddingX += BIG_ROOTS_GAP - SMALL_ROOTS_GAP; } } public void rebuild(@NotNull VcsLogRefs refsModel) { myRefGroups = getRefsToDisplayOnPanel(refsModel); - getParent().repaint(); + removeAll(); + recreateComponents(); + getParent().validate(); } @NotNull @@ -170,138 +113,84 @@ public class BranchesPanel extends JPanel { public void onFiltersChange(@NotNull VcsLogFilterCollection filters) { myRoots = VcsLogUtil.getAllVisibleRoots(myDataHolder.getRoots(), filters.getRootFilter(), filters.getStructureFilter()); - getParent().repaint(); + removeAll(); + recreateComponents(); + getParent().validate(); } - private static class ReferencePopupComponent extends JPanel { - @NotNull private final JBPopup myPopup; - @NotNull private final JBList myList; - @NotNull private final VcsLogUiImpl myUi; - @NotNull private final SingleReferenceComponent myRendererComponent; - @NotNull private final ListCellRenderer myCellRenderer; + public JComponent createScrollPane() { + JBScrollPane scrollPane = + new JBScrollPane(this, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + scrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(0, 0)); + scrollPane.getHorizontalScrollBar().setUnitIncrement(10); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + return scrollPane; + } - ReferencePopupComponent(@NotNull RefGroup group, @NotNull VcsLogUiImpl ui, @NotNull VcsRefPainter referencePainter) { - super(new BorderLayout()); - myUi = ui; + private class RootGroupComponent extends JPanel { + @NotNull private final List myGroups; - myRendererComponent = new SingleReferenceComponent(referencePainter); - myCellRenderer = new ListCellRenderer() { - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - myRendererComponent.setReference((VcsRef)value); - myRendererComponent.setSelected(isSelected); - return myRendererComponent; - } - }; + private RootGroupComponent(@NotNull List groups, @NotNull VirtualFile root) { + super(new FlowLayout(FlowLayout.LEADING, SMALL_ROOTS_GAP, 0)); + myGroups = groups; - myList = createList(group); - myPopup = createPopup(); - add(new JBScrollPane(myList)); - } - - private JBList createList(RefGroup group) { - JBList list = new JBList(createListModel(group)); - list.setCellRenderer(myCellRenderer); - ListUtil.installAutoSelectOnMouseMove(list); - list.setSelectedIndex(0); - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - jumpOnMouseClick(list); - jumpOnEnter(list); - - return list; - } - - private void jumpOnMouseClick(JBList list) { - list.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - jumpToSelectedRef(); - } - }); - } - - private void jumpOnEnter(JBList list) { - list.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - jumpToSelectedRef(); - } - } - }); - } - - private JBPopup createPopup() { - return JBPopupFactory.getInstance(). - createComponentPopupBuilder(this, myList). - setCancelOnClickOutside(true). - setCancelOnWindowDeactivation(true). - setFocusable(true). - setRequestFocus(true). - setResizable(true). - setDimensionServiceKey(myUi.getProject(), "Vcs.Log.Branch.Panel.RefGroup.Popup", false). - createPopup(); - } - - private static DefaultListModel createListModel(RefGroup group) { - DefaultListModel model = new DefaultListModel(); - for (final VcsRef vcsRef : group.getRefs()) { - model.addElement(vcsRef); - } - return model; - } - - @NotNull - JBPopup getPopup() { - return myPopup; - } - - private void jumpToSelectedRef() { - myPopup.cancel(); // close the popup immediately not to stay at the front if jumping to a commits takes long time. - VcsRef selectedRef = (VcsRef)myList.getSelectedValue(); - if (selectedRef != null) { - myUi.jumpToCommit(selectedRef.getCommitHash(), selectedRef.getRoot()); + for (RefGroup group : myGroups) { + add(new ReferenceGroupComponent(group, myReferencePainter, myUI, root)); } } } - private static class SingleReferenceComponent extends JPanel { - private static final int PADDING_Y = 2; - private static final int PADDING_X = 5; + private static class ReferenceGroupComponent extends JPanel { + @NotNull private final RefGroup myGroup; @NotNull private final VcsRefPainter myReferencePainter; + @NotNull private final VcsLogUiImpl myUI; + @NotNull private final VirtualFile myRoot; - @Nullable private VcsRef myReference; - public boolean mySelected; - - public SingleReferenceComponent(@NotNull VcsRefPainter referencePainter) { + private ReferenceGroupComponent(@NotNull RefGroup group, + @NotNull VcsRefPainter referencePainter, + @NotNull VcsLogUiImpl ui, + @NotNull VirtualFile root) { + myGroup = group; myReferencePainter = referencePainter; + myUI = ui; + myRoot = root; + addMouseListener(new MyMouseAdapter()); } @Override protected void paintComponent(Graphics g) { - g.setColor(mySelected ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - - if (myReference != null) { - myReferencePainter.paint(myReference, g, PADDING_X, PADDING_Y); - } + Color rootIndicatorColor = VcsLogColorManagerImpl.getIndicatorColor(myUI.getColorManager().getRootColor(myRoot)); + myReferencePainter + .paint(myGroup.getName(), g, 0, (getHeight() - myReferencePainter.getHeight(this)) / 2, myGroup.getBgColor(), rootIndicatorColor); } @Override public Dimension getPreferredSize() { - if (myReference == null) return super.getPreferredSize(); - Dimension size = myReferencePainter.getSize(myReference, this); - return new Dimension(size.width + 2 * PADDING_X, size.height + 2 * PADDING_Y); + return myReferencePainter.getSize(myGroup.getName(), this); } - public void setReference(@NotNull VcsRef reference) { - myReference = reference; + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); } - public void setSelected(boolean selected) { - mySelected = selected; + private class MyMouseAdapter extends MouseAdapter { + @Override + public void mouseClicked(MouseEvent e) { + if (!myUI.getMainFrame().areGraphActionsEnabled()) { + return; + } + + if (myGroup.getRefs().size() == 1) { + VcsRef ref = myGroup.getRefs().iterator().next(); + myUI.jumpToCommit(ref.getCommitHash(), ref.getRoot()); + } + else { + final ReferencePopupComponent view = new ReferencePopupComponent(myGroup, myUI, myReferencePainter); + JBPopup popup = view.getPopup(); + popup.show(new RelativePoint(ReferenceGroupComponent.this, new Point(e.getX(), ReferenceGroupComponent.this.getHeight()))); + } + } } } - } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 5dca33647da2..8cbbf56f4666 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLoadingPanel; +import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Function; @@ -111,7 +112,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { JComponent toolbars = new JPanel(new BorderLayout()); toolbars.add(myToolbar, BorderLayout.NORTH); - toolbars.add(myBranchesPanel, BorderLayout.CENTER); + toolbars.add(myBranchesPanel.createScrollPane(), BorderLayout.CENTER); JComponent toolbarsAndTable = new JPanel(new BorderLayout()); toolbarsAndTable.add(toolbars, BorderLayout.NORTH); toolbarsAndTable.add(myDetailsSplitter, BorderLayout.CENTER); From 6ac7d06349f59590a975359e142515dad48c0e9f Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Fri, 8 May 2015 18:06:36 +0300 Subject: [PATCH 162/825] [vcs-log] when branches panel is invisible it has zero size --- .../src/com/intellij/vcs/log/ui/frame/BranchesPanel.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 3ba4c560d5e4..7d925549d45b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -63,6 +63,14 @@ public class BranchesPanel extends JPanel { }); } + @Override + public Dimension getPreferredSize() { + if (!isVisible()) { + return new Dimension(0, 0); + } + return super.getPreferredSize(); + } + private void recreateComponents() { for (Map.Entry> entry : myRefGroups.entrySet()) { if (myRoots == null || myRoots.contains(entry.getKey())) { From 3f3e1ef9e08802971f6507c0c7ba7671bf4333dc Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Fri, 8 May 2015 20:05:20 +0300 Subject: [PATCH 163/825] [vcs-log] set visibility to branches panel scroll pane to switch it off --- .../intellij/vcs/log/ui/frame/BranchesPanel.java | 9 +-------- .../com/intellij/vcs/log/ui/frame/MainFrame.java | 15 +++++++++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 7d925549d45b..303883ab78a5 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -6,6 +6,7 @@ import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.ScrollUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.RefsModel; import com.intellij.vcs.log.data.VcsLogDataHolder; @@ -63,14 +64,6 @@ public class BranchesPanel extends JPanel { }); } - @Override - public Dimension getPreferredSize() { - if (!isVisible()) { - return new Dimension(0, 0); - } - return super.getPreferredSize(); - } - private void recreateComponents() { for (Map.Entry> entry : myRefGroups.entrySet()) { if (myRoots == null || myRoots.contains(entry.getKey())) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 8cbbf56f4666..6d594e9bf9a4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -21,11 +21,11 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLoadingPanel; -import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.table.ComponentsListFocusTraversalPolicy; import com.intellij.vcs.CommittedChangeListForRevision; import com.intellij.vcs.log.*; @@ -88,7 +88,8 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { // initialize components myGraphTable = new VcsLogGraphTable(vcsLogUI, logDataHolder, initialDataPack); myBranchesPanel = new BranchesPanel(logDataHolder, vcsLogUI, initialDataPack.getRefsModel()); - myBranchesPanel.setVisible(settings.isShowBranchesPanel()); + JComponent branchScrollPane = myBranchesPanel.createScrollPane(); + branchScrollPane.setVisible(settings.isShowBranchesPanel()); myDetailsPanel = new DetailsPanel(logDataHolder, myGraphTable, vcsLogUI.getColorManager(), initialDataPack); myChangesBrowser = new RepositoryChangesBrowser(project, null, Collections.emptyList(), null); @@ -112,7 +113,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { JComponent toolbars = new JPanel(new BorderLayout()); toolbars.add(myToolbar, BorderLayout.NORTH); - toolbars.add(myBranchesPanel.createScrollPane(), BorderLayout.CENTER); + toolbars.add(branchScrollPane, BorderLayout.CENTER); JComponent toolbarsAndTable = new JPanel(new BorderLayout()); toolbarsAndTable.add(toolbars, BorderLayout.NORTH); toolbarsAndTable.add(myDetailsSplitter, BorderLayout.CENTER); @@ -290,7 +291,13 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } public void setBranchesPanelVisible(boolean visible) { - myBranchesPanel.setVisible(visible); + JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, myBranchesPanel); + if (scrollPane != null) { + scrollPane.setVisible(visible); + } + else { + myBranchesPanel.setVisible(visible); + } } @Override From c5540c49786f2fb12cb5daf8ac0093faef56df22 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sat, 9 May 2015 23:12:55 +0300 Subject: [PATCH 164/825] [vcs-log] do not include tracked branches in remote groups, remote has only one branch show it outright --- .../vcs/log/ui/frame/BranchesPanel.java | 12 ++- .../src/git4idea/log/GitRefManager.java | 8 +- .../tests/git4idea/log/GitRefGroupsTest.java | 75 +++++++++++++++++++ 3 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 plugins/git4idea/tests/git4idea/log/GitRefGroupsTest.java diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 303883ab78a5..f4fffda4a72b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -85,19 +85,17 @@ public class BranchesPanel extends JPanel { LinkedHashMap> groups = ContainerUtil.newLinkedHashMap(); for (Map.Entry> entry : VcsLogUtil.groupRefsByRoot(allRefs).entrySet()) { - VirtualFile root = entry.getKey(); - List list = ContainerUtil.newArrayList(); - list.addAll(expandExpandableGroups(myDataHolder.getLogProvider(root).getReferenceManager().group(entry.getValue()))); - groups.put(root, list); + groups.put(entry.getKey(), + expandExpandableGroups(myDataHolder.getLogProvider(entry.getKey()).getReferenceManager().group(entry.getValue()))); } return groups; } - private static Collection expandExpandableGroups(List refGroups) { - Collection groups = ContainerUtil.newArrayList(); + private static List expandExpandableGroups(List refGroups) { + List groups = ContainerUtil.newArrayList(); for (RefGroup group : refGroups) { - if (group.isExpanded()) { + if (group.isExpanded() || group.getRefs().size() == 1) { groups.addAll(ContainerUtil.map(group.getRefs(), new Function() { @Override public RefGroup fun(VcsRef ref) { diff --git a/plugins/git4idea/src/git4idea/log/GitRefManager.java b/plugins/git4idea/src/git4idea/log/GitRefManager.java index 2aab1c8b2666..f9b7d67f99be 100644 --- a/plugins/git4idea/src/git4idea/log/GitRefManager.java +++ b/plugins/git4idea/src/git4idea/log/GitRefManager.java @@ -105,10 +105,12 @@ public class GitRefManager implements VcsLogRefManager { localBranches.add(ref); } else if (allRemote.containsKey(refName)) { - remoteRefGroups.putValue(allRemote.get(refName), ref); if (tracked.contains(refName)) { trackedBranches.add(ref); } + else { + remoteRefGroups.putValue(allRemote.get(refName), ref); + } } else { LOG.debug("Didn't find ref neither in local nor in remote branches: " + ref); @@ -118,8 +120,8 @@ public class GitRefManager implements VcsLogRefManager { List result = ContainerUtil.newArrayList(); result.addAll(simpleGroups); - result.add(new LogicalRefGroup("Local", localBranches)); - result.add(new LogicalRefGroup("Tracked", trackedBranches)); + if (!localBranches.isEmpty()) result.add(new LogicalRefGroup("Local", localBranches)); + if (!trackedBranches.isEmpty()) result.add(new LogicalRefGroup("Tracked", trackedBranches)); for (Map.Entry> entry : remoteRefGroups.entrySet()) { final GitRemote remote = entry.getKey(); final Collection branches = entry.getValue(); diff --git a/plugins/git4idea/tests/git4idea/log/GitRefGroupsTest.java b/plugins/git4idea/tests/git4idea/log/GitRefGroupsTest.java new file mode 100644 index 000000000000..5446003eb7b9 --- /dev/null +++ b/plugins/git4idea/tests/git4idea/log/GitRefGroupsTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.log; + +import com.intellij.openapi.util.Pair; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.RefGroup; +import com.intellij.vcs.log.VcsRef; +import com.intellij.vcs.log.impl.SingletonRefGroup; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class GitRefGroupsTest extends GitRefManagerTest { + public void test_single_tracked_branch() throws IOException { + check(given("HEAD", "master", "origin/master"), ContainerUtil.list("HEAD"), Pair.create("Local", ContainerUtil.list("master")), + Pair.create("Tracked", ContainerUtil.list("origin/master"))); + } + + public void test_single_local_branch() throws IOException { + check(given("HEAD", "master"), ContainerUtil.list("HEAD"), Pair.create("Local", ContainerUtil.list("master"))); + } + + public void test_local_tracked_and_remote_branch() throws IOException { + check(given("HEAD", "master", "origin/master", "origin/remote_branch", "local_branch"), ContainerUtil.list("HEAD"), + Pair.create("Local", ContainerUtil.list("master", "local_branch")), Pair.create("Tracked", ContainerUtil.list("origin/master")), + Pair.create("origin/...", ContainerUtil.list("origin/remote_branch"))); + } + + private void check(@NotNull Collection actual, + @NotNull List expectedSingleGroups, + Pair>... expectedOtherGroups) { + + List actualGroups = new GitRefManager(myGitRepositoryManager).group(actual); + + List singleGroups = ContainerUtil.findAll(actualGroups, SingletonRefGroup.class); + assertEquals(expectedSingleGroups, ContainerUtil.map(singleGroups, new Function() { + @Override + public String fun(RefGroup singletonRefGroup) { + return singletonRefGroup.getName(); + } + })); + + actualGroups.removeAll(singleGroups); + + assertEquals(Arrays.asList(expectedOtherGroups), ContainerUtil.map(actualGroups, new Function>>() { + @Override + public Pair> fun(RefGroup refGroup) { + return Pair.create(refGroup.getName(), ContainerUtil.map(refGroup.getRefs(), new Function() { + @Override + public String fun(VcsRef vcsRef) { + return vcsRef.getName(); + } + })); + } + })); + } +} From 3fb66466d7d5dc3ce0415a80d1d85cc357c56cfa Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Mon, 11 May 2015 04:23:57 +0300 Subject: [PATCH 165/825] [vcs-log] remove flags from remote references popup and add speedsearch IDEA-140104 --- .../vcs/log/ui/frame/BranchesPanel.java | 7 ++----- ...ponent.java => ReferencePopupBuilder.java} | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) rename platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/{ReferencePopupComponent.java => ReferencePopupBuilder.java} (86%) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index f4fffda4a72b..3c1ef5f1a4fa 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -1,8 +1,6 @@ package com.intellij.vcs.log.ui.frame; -import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -185,9 +183,8 @@ public class BranchesPanel extends JPanel { myUI.jumpToCommit(ref.getCommitHash(), ref.getRoot()); } else { - final ReferencePopupComponent view = new ReferencePopupComponent(myGroup, myUI, myReferencePainter); - JBPopup popup = view.getPopup(); - popup.show(new RelativePoint(ReferenceGroupComponent.this, new Point(e.getX(), ReferenceGroupComponent.this.getHeight()))); + ReferencePopupBuilder popupBuilder = new ReferencePopupBuilder(myGroup, myUI); + popupBuilder.getPopup().showUnderneathOf(ReferenceGroupComponent.this); } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupBuilder.java similarity index 86% rename from platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupComponent.java rename to platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupBuilder.java index ddc4ebdeafa8..5bcacc245df2 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/ReferencePopupBuilder.java @@ -18,8 +18,10 @@ package com.intellij.vcs.log.ui.frame; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.ui.ListUtil; +import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBList; -import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.speedSearch.ListWithFilter; +import com.intellij.util.Function; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.RefGroup; import com.intellij.vcs.log.VcsRef; @@ -35,18 +37,17 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -class ReferencePopupComponent extends JPanel { +class ReferencePopupBuilder { @NotNull private final JBPopup myPopup; @NotNull private final JBList myList; @NotNull private final VcsLogUiImpl myUi; @NotNull private final SingleReferenceComponent myRendererComponent; @NotNull private final ListCellRenderer myCellRenderer; - ReferencePopupComponent(@NotNull RefGroup group, @NotNull VcsLogUiImpl ui, @NotNull VcsRefPainter referencePainter) { - super(new BorderLayout()); + ReferencePopupBuilder(@NotNull RefGroup group, @NotNull VcsLogUiImpl ui) { myUi = ui; - myRendererComponent = new SingleReferenceComponent(referencePainter); + myRendererComponent = new SingleReferenceComponent(new VcsRefPainter(ui.getColorManager(), false)); myCellRenderer = new ListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -58,7 +59,6 @@ class ReferencePopupComponent extends JPanel { myList = createList(group); myPopup = createPopup(); - add(new JBScrollPane(myList)); } private JBList createList(RefGroup group) { @@ -95,8 +95,13 @@ class ReferencePopupComponent extends JPanel { } private JBPopup createPopup() { - return JBPopupFactory.getInstance(). - createComponentPopupBuilder(this, myList). + return JBPopupFactory.getInstance() + .createComponentPopupBuilder(ListWithFilter.wrap(myList, ScrollPaneFactory.createScrollPane(myList), new Function() { + @Override + public String fun(VcsRef vcsRef) { + return vcsRef.getName(); + } + }), myList). setCancelOnClickOutside(true). setCancelOnWindowDeactivation(true). setFocusable(true). From 97887baf02ec13bcbad2b2189a6be6c1a8f7a5a8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 15 Jan 2016 22:34:54 +0300 Subject: [PATCH 166/825] IDEA-149395 Align scrollable view with an empty border --- .../intellij/ui/components/JBViewport.java | 182 ++++++++++++------ 1 file changed, 125 insertions(+), 57 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/JBViewport.java b/platform/platform-api/src/com/intellij/ui/components/JBViewport.java index b5a89627c745..97956e4ae90a 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBViewport.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBViewport.java @@ -16,7 +16,6 @@ package com.intellij.ui.components; import com.intellij.openapi.ui.TypingTarget; -import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.components.JBScrollPane.Alignment; import com.intellij.ui.table.JBTable; @@ -26,6 +25,11 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.plaf.TreeUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicTreeUI; import java.awt.*; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; @@ -173,61 +177,6 @@ public class JBViewport extends JViewport implements ZoomableViewport { return myPaintingNow; } - @Override - public Color getBackground() { - Component view = getView(); - return view != null && view.isBackgroundSet() - ? view.getBackground() - : super.getBackground(); - } - - @Override - public Dimension getExtentSize() { - Dimension size = super.getExtentSize(); - if (SystemInfo.isMac) return size; - JScrollPane pane = getScrollPane(this); - if (pane != null) { - JScrollBar vsb = pane.getVerticalScrollBar(); - if (null != getAlignment(vsb)) { - int width = vsb.getWidth(); - if (size.width > width) size.width -= width; - } - JScrollBar hsb = pane.getHorizontalScrollBar(); - if (null != getAlignment(hsb)) { - int height = hsb.getHeight(); - if (size.height > height) size.height -= height; - } - } - return size; - } - - @Override - public Point getViewPosition() { - return updateViewPosition(super.getViewPosition(), false); - } - - @Override - public void setViewPosition(Point p) { - super.setViewPosition(updateViewPosition(p, true)); - } - - private Point updateViewPosition(Point p, boolean minus) { - JScrollPane pane = getScrollPane(this); - if (pane != null) { - JScrollBar vsb = pane.getVerticalScrollBar(); - if (Alignment.LEFT == getAlignment(vsb)) { - int width = vsb.getWidth(); - p.x += minus ? -width : width; - } - JScrollBar hsb = pane.getHorizontalScrollBar(); - if (Alignment.TOP == getAlignment(hsb)) { - int height = hsb.getHeight(); - p.y += minus ? -height : height; - } - } - return p; - } - /** * Returns the alignment of the specified scroll bar * if and only if the specified scroll bar @@ -261,8 +210,10 @@ public class JBViewport extends JViewport implements ZoomableViewport { } private static void doLayout(JScrollPane pane, JViewport viewport, Component view) { + updateBorder(view); + Dimension actualSize = viewport.getSize(); - Dimension extentSize = viewport.getExtentSize(); + Dimension extentSize = viewport.toViewCoordinates(actualSize); Dimension viewPreferredSize = view.getPreferredSize(); Dimension viewSize = new Dimension(viewPreferredSize); Point viewPosition = viewport.getViewPosition(); @@ -314,4 +265,121 @@ public class JBViewport extends JViewport implements ZoomableViewport { viewport.setViewPosition(viewPosition); viewport.setViewSize(viewSize); } + + private static void updateBorder(Component view) { + if (view instanceof JTable) return; // tables are not supported yet + if (view instanceof JComponent) { + JComponent component = (JComponent)view; + Border border = component.getBorder(); + if (border instanceof ViewBorder) return; // already set + component.setBorder(border == null || border instanceof UIResource + ? new ResourceViewBorder(border) + : new ViewBorder(border)); + } + } + + /** + * This border is used to add additional space for a view + * and can be changed on UI update. + */ + private static class ResourceViewBorder extends ViewBorder implements UIResource { + ResourceViewBorder(Border border) { + super(border); + } + } + + /** + * This border is used to add additional space for a view. + */ + private static class ViewBorder extends AbstractBorder { + private final Insets myInsets = new Insets(0, 0, 0, 0); + private final Border myBorder; + + ViewBorder(Border border) { + myBorder = border; + } + + @Override + public Insets getBorderInsets(Component view, Insets insets) { + if (insets == null) { + insets = new Insets(0, 0, 0, 0); + } + else { + insets.set(0, 0, 0, 0); + } + if (myBorder != null) { + Insets inner = myBorder.getBorderInsets(view); + if (inner != null) insets.set(inner.top, inner.left, inner.bottom, inner.right); + } + if (view instanceof JComponent) { + addViewInsets((JComponent)view, insets); + } + if (!myInsets.equals(insets)) { + myInsets.set(insets.top, insets.left, insets.bottom, insets.right); + if (view instanceof JComponent) { + JComponent component = (JComponent)view; + if (component instanceof JTree) { + // invalidate cached preferred size + JTree tree = (JTree)component; + TreeUI ui = tree.getUI(); + if (ui instanceof BasicTreeUI) { + BasicTreeUI basic = (BasicTreeUI)ui; + basic.setLeftChildIndent(basic.getLeftChildIndent()); + } + } + component.revalidate(); + } + else { + view.invalidate(); + view.repaint(); + } + } + return insets; + } + + @Override + public void paintBorder(Component view, Graphics g, int x, int y, int width, int height) { + if (myBorder != null) { + if (view instanceof JComponent) { + Insets insets = new Insets(0, 0, 0, 0); + addViewInsets((JComponent)view, insets); + x += insets.left; + y += insets.top; + width -= insets.left + insets.right; + height -= insets.top + insets.bottom; + } + myBorder.paintBorder(view, g, x, y, width, height); + } + } + + private void addViewInsets(JComponent view, Insets insets) { + if (this == view.getBorder()) { + Container parent = view.getParent(); + if (parent instanceof JViewport) { + JViewport viewport = (JViewport)parent; + JScrollPane pane = getScrollPane(viewport); + if (pane != null) { + // calculate empty border under vertical scroll bar + JScrollBar vsb = pane.getVerticalScrollBar(); + Alignment va = getAlignment(vsb); + if (va == Alignment.LEFT) { + insets.left += vsb.getWidth(); + } + else if (va == Alignment.RIGHT) { + insets.right += vsb.getWidth(); + } + // calculate empty border under horizontal scroll bar + JScrollBar hsb = pane.getHorizontalScrollBar(); + Alignment ha = getAlignment(hsb); + if (ha == Alignment.TOP) { + insets.top += hsb.getHeight(); + } + else if (ha == Alignment.BOTTOM) { + insets.bottom += hsb.getHeight(); + } + } + } + } + } + } } From b643ab99586d4a4f0aa6da285b1c7a50259f516c Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 16 Jan 2016 00:10:51 +0300 Subject: [PATCH 167/825] tox test fix: nose runner should not return 1 in case of error since all runners always return 0 --- python/helpers/pycharm/noserunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/helpers/pycharm/noserunner.py b/python/helpers/pycharm/noserunner.py index 9f8b84e8e088..ff45dba4c6e5 100644 --- a/python/helpers/pycharm/noserunner.py +++ b/python/helpers/pycharm/noserunner.py @@ -90,7 +90,7 @@ def process_args(): config = MyConfig(plugins=manager) config.configure(argv) - TestProgram(argv=argv, config=config) + TestProgram(argv=argv, config=config, exit=False) if __name__ == "__main__": process_args() \ No newline at end of file From 97e9950c71c3d625fdbfdaebe4dce323eea82a4e Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 16 Jan 2016 00:11:27 +0300 Subject: [PATCH 168/825] tox test fix: do not call "enter matrix" when running inside of tox --- python/helpers/pycharm/pytest_teamcity.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/helpers/pycharm/pytest_teamcity.py b/python/helpers/pycharm/pytest_teamcity.py index 8e305236b88b..e9bd4f02f356 100644 --- a/python/helpers/pycharm/pytest_teamcity.py +++ b/python/helpers/pycharm/pytest_teamcity.py @@ -15,7 +15,8 @@ if sys.argv: CURRENT_DIR_NAME = os.path.dirname(sys.argv[-1]) messages = TeamcityServiceMessages(prepend_linebreak=True) -messages.testMatrixEntered() +if not "_jb_do_not_call_enter_matrix" in os.environ: + messages.testMatrixEntered() try: import pytest PYVERSION = [int(x) for x in pytest.__version__.split(".")] From 793dea71bf280e84b313391aade341e27aba8418 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 16 Jan 2016 01:28:30 +0300 Subject: [PATCH 169/825] tox test fix: provide explicit interpreter instead of default --- python/helpers/pycharm/_jb_tox_runner.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/python/helpers/pycharm/_jb_tox_runner.py b/python/helpers/pycharm/_jb_tox_runner.py index 26535fbb7094..b8188dbe0bba 100644 --- a/python/helpers/pycharm/_jb_tox_runner.py +++ b/python/helpers/pycharm/_jb_tox_runner.py @@ -16,26 +16,26 @@ helpers_dir = str(os.path.split(__file__)[0]) class _Unit2(object): - def fix(self, command, dir_to_run): + def fix(self, command, dir_to_run, bin): if command[0] == "unit2": - return ["python", os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"] + return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"] elif command == ["python", "-m", "unittest", "discover"]: - return ["python", os.path.join(helpers_dir, "utrunner.py"), dir_to_run, "true"] + return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run, "true"] return None class _PyTest(object): - def fix(self, command, dir_to_run): + def fix(self, command, dir_to_run, bin): if command[0] != "py.test": return None - return [os.path.join(helpers_dir, "pytestrunner.py"), "-p", "pytest_teamcity", dir_to_run] + command[1:] + return [bin, os.path.join(helpers_dir, "pytestrunner.py"), "-p", "pytest_teamcity", dir_to_run] + command[1:] class _Nose(object): - def fix(self, command, dir_to_run): + def fix(self, command, dir_to_run, bin): if command[0] != "nosetests": return None - return [os.path.join(helpers_dir, "noserunner.py"), dir_to_run] + command[1:] + return [bin, os.path.join(helpers_dir, "noserunner.py"), dir_to_run] + command[1:] @@ -84,9 +84,10 @@ for env, tmp_config in config.envconfigs.items(): if not isinstance(commands, list) or not len(commands): continue for fixer in _RUNNERS: - dir_to_run = str(config.envconfigs[env].changedir) + _env = config.envconfigs[env] + dir_to_run = str(_env.changedir) for i, command in enumerate(commands): - fixed_command = fixer.fix(command, dir_to_run) + fixed_command = fixer.fix(command, dir_to_run, str(_env.envpython)) if fixed_command: commands[i] = fixed_command tmp_config.commands = commands From 0f0774f40e1137eb3fe64b72d7a32093c5adde71 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 16 Jan 2016 01:51:15 +0300 Subject: [PATCH 170/825] tox test fix: bad names for broken tests in nose --- python/helpers/pycharm/nose_utils.py | 36 ++++++++++++++++------------ 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/python/helpers/pycharm/nose_utils.py b/python/helpers/pycharm/nose_utils.py index 2094d830665b..ed7bd096651f 100644 --- a/python/helpers/pycharm/nose_utils.py +++ b/python/helpers/pycharm/nose_utils.py @@ -9,6 +9,7 @@ from tcunittest import TeamcityTestResult try: + from nose.failure import Failure from nose.util import isclass # backwards compat from nose.config import Config from nose.result import TextTestResult @@ -17,7 +18,7 @@ try: except (Exception, ): e = sys.exc_info()[1] raise NameError( - "Something went wrong, do you have nosetest installed? I got this error: %s" % e) + "Something went wrong, do you have nosetest installed? I got this error: %s" % e) class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): """ @@ -39,11 +40,11 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): self.config = config self.output = stream self.messages = TeamcityServiceMessages(self.output, - prepend_linebreak=True) + prepend_linebreak=True) self.messages.testMatrixEntered() self.current_suite = None TextTestResult.__init__(self, stream, descriptions, verbosity, config, - errorClasses) + errorClasses) TeamcityTestResult.__init__(self, stream) def configure(self, options, conf): @@ -55,10 +56,11 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): def addError(self, test, err): exctype, value, tb = err err = self.formatErr(err) + if exctype == SkipTest: - self.messages.testIgnored(self.getTestName(test), message='Skip') + self.messages.testIgnored(self.getTestName(test), message='Skip') else: - self.messages.testError(self.getTestName(test), message='Error', details=err, duration=self.__getDuration(test)) + self.messages.testError(self.getTestName(test), message='Error', details=err, duration=self.__getDuration(test)) def formatErr(self, err): exctype, value, tb = err @@ -77,6 +79,8 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): def getTestName(self, test): + if isinstance(test.test, Failure): + return "ERROR" if hasattr(test, "error_context"): return test.error_context test_name_full = str(test) @@ -93,7 +97,7 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): err = self.formatErr(err) self.messages.testFailed(self.getTestName(test), - message='Failure', details=err) + message='Failure', details=err) def addSkip(self, test, reason): @@ -117,14 +121,14 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): if hasattr(test.test, "descriptor") and test.test.descriptor: suite_location = "file://" + self.test_address( - test.test.descriptor) + test.test.descriptor) location = suite_location + ":" + str( - func_lineno(test.test.descriptor)) + func_lineno(test.test.descriptor)) else: suite_location = "file://" + self.test_address( - test.test.test) + test.test.test) location = "file://" + self.test_address( - test.test.test) + ":" + str(func_lineno(test.test.test)) + test.test.test) + ":" + str(func_lineno(test.test.test)) except: test_id = test.id() suite_id = test_id[:test_id.rfind(".")] @@ -155,6 +159,8 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): def getSuiteName(self, test): + if isinstance(test.test, Failure): + return "ERROR" test_name_full = str(test) ind_1 = test_name_full.rfind('(') @@ -179,7 +185,7 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): self.messages.testSuiteFinished(self.current_suite) self.current_suite = suite self.messages.testSuiteStarted(self.current_suite, - location=suite_location) + location=suite_location) setattr(test, "startTime", datetime.datetime.now()) self.messages.testStarted(self.getTestName(test), location=location) @@ -187,7 +193,7 @@ class TeamcityPlugin(ErrorClassPlugin, TextTestResult, TeamcityTestResult): def stopTest(self, test): duration = self.__getDuration(test) self.messages.testFinished(self.getTestName(test), - duration=int(duration)) + duration=int(duration)) def __getDuration(self, test): start = getattr(test, "startTime", datetime.datetime.now()) @@ -216,9 +222,9 @@ class TeamcityNoseRunner(unittest.TextTestRunner): def _makeResult(self): return TeamcityPlugin(self.stream, - self.descriptions, - self.verbosity, - self.config) + self.descriptions, + self.verbosity, + self.config) def run(self, test): """Overrides to provide plugin hooks and defer all output to From 08988f79d97e4c2666f5a4f713f63a0fd2378f85 Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Thu, 24 Dec 2015 13:08:01 +0300 Subject: [PATCH 171/825] PY-14614 Don't showPyAbstractClassInspection if NotImplementedError is conditional in parent class --- .../override/PyOverrideImplementUtil.java | 51 +++++++++++-------- .../conditionalRaiseNestedIfs.py | 18 +++++++ .../conditionalRaiseReturnInElifPart.py | 18 +++++++ .../conditionalRaiseReturnInElsePart.py | 18 +++++++ .../conditionalRaiseReturnInIfPart.py | 16 ++++++ .../PyAbstractClassInspectionTest.java | 16 ++++++ 6 files changed, 117 insertions(+), 20 deletions(-) create mode 100644 python/testData/inspections/PyAbstractClassInspection/conditionalRaiseNestedIfs.py create mode 100644 python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElifPart.py create mode 100644 python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElsePart.py create mode 100644 python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInIfPart.py diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java index 8f0305e38543..00164fbf73ae 100644 --- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java @@ -288,26 +288,10 @@ public class PyOverrideImplementUtil { } public static boolean raisesNotImplementedError(@NotNull PyFunction function) { - for (PyStatement statement : function.getStatementList().getStatements()) { - if (!(statement instanceof PyRaiseStatement)) { - continue; - } - final PyRaiseStatement raiseStatement = (PyRaiseStatement)statement; - final PyExpression[] expressions = raiseStatement.getExpressions(); - if (expressions.length > 0) { - final PyExpression firstExpression = expressions[0]; - if (firstExpression instanceof PyCallExpression) { - final PyExpression callee = ((PyCallExpression)firstExpression).getCallee(); - if (callee != null && callee.getText().equals(PyNames.NOT_IMPLEMENTED_ERROR)) { - return true; - } - } - else if (firstExpression.getText().equals(PyNames.NOT_IMPLEMENTED_ERROR)) { - return true; - } - } - } - return false; + PyStatementList statementList = function.getStatementList(); + IfVisitor visitor = new IfVisitor(); + statementList.accept(visitor); + return !visitor.hasReturnInside && visitor.raiseNotImplemented; } // TODO find a better place for this logic @@ -342,4 +326,31 @@ public class PyOverrideImplementUtil { } return Lists.newArrayList(functions.values()); } + + private static class IfVisitor extends PyRecursiveElementVisitor { + private boolean hasReturnInside; + private boolean raiseNotImplemented; + + @Override + public void visitPyReturnStatement(PyReturnStatement node) { + hasReturnInside = true; + } + + @Override + public void visitPyRaiseStatement(PyRaiseStatement node) { + final PyExpression[] expressions = node.getExpressions(); + if (expressions.length > 0) { + final PyExpression firstExpression = expressions[0]; + if (firstExpression instanceof PyCallExpression) { + final PyExpression callee = ((PyCallExpression)firstExpression).getCallee(); + if (callee != null && callee.getText().equals(PyNames.NOT_IMPLEMENTED_ERROR)) { + raiseNotImplemented = true; + } + } + else if (firstExpression.getText().equals(PyNames.NOT_IMPLEMENTED_ERROR)) { + raiseNotImplemented = true; + } + } + } + } } diff --git a/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseNestedIfs.py b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseNestedIfs.py new file mode 100644 index 000000000000..3eb83b59bd28 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseNestedIfs.py @@ -0,0 +1,18 @@ +class A: + @classmethod + def test(cls, x, y): + return None + + +class B(A): + @classmethod + def test(cls, x, y): + if x == 1: + print(y) + if x == y: + return 1 + raise NotImplementedError + + +class C(B): + pass \ No newline at end of file diff --git a/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElifPart.py b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElifPart.py new file mode 100644 index 000000000000..9e12c7f529f7 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElifPart.py @@ -0,0 +1,18 @@ +class A: + @classmethod + def test(cls, x, y): + return None + + +class B(A): + @classmethod + def test(cls, x, y): + if x == 1: + print(y) + elif x == y: + return 1 + raise NotImplementedError + + +class C(B): + pass \ No newline at end of file diff --git a/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElsePart.py b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElsePart.py new file mode 100644 index 000000000000..c94bf627a028 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInElsePart.py @@ -0,0 +1,18 @@ +class A: + @classmethod + def test(cls, param): + return None + + +class B(A): + @classmethod + def test(cls, param): + if param == 1: + print(param) + else: + return 1 + raise NotImplementedError + + +class C(B): + pass \ No newline at end of file diff --git a/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInIfPart.py b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInIfPart.py new file mode 100644 index 000000000000..50e9fc2686ef --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/conditionalRaiseReturnInIfPart.py @@ -0,0 +1,16 @@ +class A: + @classmethod + def test(cls, param): + return None + + +class B(A): + @classmethod + def test(cls, param): + if param == 1: + return 1 + raise NotImplementedError + + +class C(B): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java index d5e5ad3127e8..c91e21730c31 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java @@ -57,6 +57,22 @@ public class PyAbstractClassInspectionTest extends PyInspectionTestCase { doTest(); } + public void testConditionalRaiseReturnInIfPart() { + doTest(); + } + + public void testConditionalRaiseReturnInElsePart() { + doTest(); + } + + public void testConditionalRaiseNestedIfs() { + doTest(); + } + + public void testConditionalRaiseReturnInElifPart() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() { From f71abda0e2fdd517c5f8f6f915a6c2893d3d3fc9 Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Thu, 24 Dec 2015 16:12:41 +0300 Subject: [PATCH 172/825] PY-14234 Fix false positive when underscored module imported inside the package --- .../inspections/PyProtectedMemberInspection.java | 13 ++++++++++++- .../importFromTheSamePackage/my_package/__init__.py | 0 .../my_package/_package_internal_module.py | 2 ++ .../my_package/my_public_module.py | 3 +++ .../PyProtectedMemberInspectionTest.java | 9 +++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/__init__.py create mode 100644 python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/_package_internal_module.py create mode 100644 python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/my_public_module.py diff --git a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java index 8ad9527b6784..8d13596eb622 100644 --- a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java @@ -21,6 +21,7 @@ import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiReference; @@ -85,8 +86,18 @@ public class PyProtectedMemberInspection extends PyInspection { if (!(statement instanceof PyFromImportStatement)) return; final PyReferenceExpression importReferenceExpression = node.getImportReferenceExpression(); final PyReferenceExpression importSource = ((PyFromImportStatement)statement).getImportSource(); - if (importReferenceExpression != null && importSource != null) + if (importReferenceExpression != null && importSource != null && !isImportFromTheSamePackage(importSource)) { checkReference(importReferenceExpression, importSource); + } + } + + private boolean isImportFromTheSamePackage(PyReferenceExpression importSource) { + PsiDirectory directory = importSource.getContainingFile().getContainingDirectory(); + if (PyUtil.isPackage(directory, true, importSource.getContainingFile()) && + directory.getName().equals(importSource.getName())) { + return true; + } + return false; } @Override diff --git a/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/__init__.py b/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/_package_internal_module.py b/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/_package_internal_module.py new file mode 100644 index 000000000000..27ee855c4efb --- /dev/null +++ b/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/_package_internal_module.py @@ -0,0 +1,2 @@ +def very_smart_func(param): + return None \ No newline at end of file diff --git a/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/my_public_module.py b/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/my_public_module.py new file mode 100644 index 000000000000..c29039630586 --- /dev/null +++ b/python/testData/inspections/PyProtectedMemberInspection/importFromTheSamePackage/my_package/my_public_module.py @@ -0,0 +1,3 @@ +from my_package import _package_internal_module # False positive here + +_package_internal_module.very_smart_func("spam") \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyProtectedMemberInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyProtectedMemberInspectionTest.java index 51c81c2474db..a273f83e182a 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyProtectedMemberInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyProtectedMemberInspectionTest.java @@ -69,6 +69,15 @@ public class PyProtectedMemberInspectionTest extends PyTestCase { myFixture.checkHighlighting(false, false, true); } + //PY-14234 + public void testImportFromTheSamePackage() { + String path = getTestName(true); + myFixture.copyDirectoryToProject(path + "/my_package", "./my_package"); + myFixture.configureByFile("/my_package/my_public_module.py"); + myFixture.enableInspections(PyProtectedMemberInspection.class); + myFixture.checkHighlighting(false, false, true); + } + public void testModule() { myFixture.configureByFiles(getTestName(true) + ".py", "tmp.py"); myFixture.enableInspections(PyProtectedMemberInspection.class); From 55a6fe92642b125fdf49d83d4c7e1a707516460f Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 18 Jan 2016 11:37:14 +0300 Subject: [PATCH 173/825] IDEA-111425 [reverted debug printing] --- .../ui/header/InspectionToolsConfigurable.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index ab5741928632..654774d70d05 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -71,8 +71,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionAdapter; import java.io.File; import java.io.IOException; import java.util.*; @@ -416,12 +414,6 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable toolbar.setLayout(new GridBagLayout()); final JLabel headerTitleLabel = new JLabel(HEADER_TITLE); - headerTitleLabel.addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - System.out.println("HERE"); - } - }); headerTitleLabel.setBorder(IdeBorderFactory.createEmptyBorder(10, 0, 0, 0)); toolbar.add(headerTitleLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); From 8d4e6df45ced89b47bad9895af2933177992e9c4 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 18 Jan 2016 12:10:53 +0300 Subject: [PATCH 174/825] github: EA-77214 - URISE: URI.create --- .../jetbrains/plugins/github/util/GithubUtil.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java index f71b81c7c8e8..3e328af50000 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java @@ -24,16 +24,13 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Consumer; -import com.intellij.util.ThrowableConsumer; import com.intellij.util.ThrowableConvertor; import com.intellij.util.containers.Convertor; import git4idea.DialogManager; @@ -50,7 +47,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.github.api.GithubApiUtil; import org.jetbrains.plugins.github.api.GithubConnection; -import org.jetbrains.plugins.github.api.GithubFullPath; import org.jetbrains.plugins.github.api.GithubUserDetailed; import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException; import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException; @@ -59,6 +55,8 @@ import org.jetbrains.plugins.github.ui.GithubBasicLoginDialog; import org.jetbrains.plugins.github.ui.GithubLoginDialog; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.List; import java.util.concurrent.ScheduledFuture; @@ -315,6 +313,13 @@ public class GithubUtil { throw new GithubAuthenticationException("Target host not defined"); } + try { + new URI(auth.getHost()); + } + catch (URISyntaxException e) { + throw new GithubAuthenticationException("Invalid host URL"); + } + switch (auth.getAuthType()) { case BASIC: GithubAuthData.BasicAuth basicAuth = auth.getBasicAuth(); From b812bc104fce950468e30a4580de009b791c45c2 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 18 Jan 2016 11:19:41 +0100 Subject: [PATCH 175/825] IDEA-CR-7643IDEA-146929 IntelliJ 15 EAP - Won't start when there is 100% packet loss - Crash --- .../src/com/intellij/idea/SocketLock.java | 13 ++--------- .../src/org/jetbrains/io/BuiltInServer.java | 23 +++++++++++++++++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/idea/SocketLock.java b/platform/platform-impl/src/com/intellij/idea/SocketLock.java index c629d3f2d37a..5c1f6a797e38 100644 --- a/platform/platform-impl/src/com/intellij/idea/SocketLock.java +++ b/platform/platform-impl/src/com/intellij/idea/SocketLock.java @@ -32,7 +32,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.oio.OioEventLoopGroup; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.io.BuiltInServer; @@ -133,21 +132,13 @@ public final class SocketLock { final String[] lockedPaths = {myConfigPath, mySystemPath}; int workerCount = PlatformUtils.isIdeaCommunity() || PlatformUtils.isDatabaseIDE() || PlatformUtils.isCidr() ? 1 : 2; - NotNullProducer handler = new NotNullProducer() { + myServer = BuiltInServer.startNioOrOio(workerCount, 6942, 50, false, new NotNullProducer() { @NotNull @Override public ChannelHandler produce() { return new MyChannelInboundHandler(lockedPaths, myActivateListener); } - }; - try { - myServer = BuiltInServer.start(workerCount, 6942, 50, false, handler); - } - catch (IllegalStateException e) { - Logger.getInstance(SocketLock.class).warn(e); - myServer = BuiltInServer.start(new OioEventLoopGroup(1, new BuiltInServer.BuiltInServerThreadFactory()), true, 6942, 50, false, handler); - } - + }); byte[] portBytes = Integer.toString(myServer.getPort()).getBytes(CharsetToolkit.UTF8_CHARSET); FileUtil.writeToFile(portMarkerC, portBytes); FileUtil.writeToFile(portMarkerS, portBytes); diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java index 05d7b9e3b886..35bc72e594ec 100644 --- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java +++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -25,6 +25,7 @@ import com.intellij.util.net.NetUtils; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.oio.OioEventLoopGroup; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -90,6 +91,24 @@ public class BuiltInServer implements Disposable { return start(new NioEventLoopGroup(workerCount, new BuiltInServerThreadFactory()), true, firstPort, portsCount, tryAnyPort, handler); } + @NotNull + public static BuiltInServer startNioOrOio(int workerCount, + int firstPort, + int portsCount, + boolean tryAnyPort, + @Nullable NotNullProducer handler) throws Exception { + BuiltInServerThreadFactory threadFactory = new BuiltInServerThreadFactory(); + NioEventLoopGroup nioEventLoopGroup; + try { + nioEventLoopGroup = new NioEventLoopGroup(workerCount, threadFactory); + } + catch (IllegalStateException e) { + Logger.getInstance(BuiltInServer.class).warn(e); + return start(new OioEventLoopGroup(1, threadFactory), true, 6942, 50, false, handler); + } + return start(nioEventLoopGroup, true, firstPort, portsCount, tryAnyPort, handler); + } + @NotNull public static BuiltInServer start(@NotNull EventLoopGroup eventLoopGroup, boolean isEventLoopGroupOwner, @@ -155,7 +174,7 @@ public class BuiltInServer implements Disposable { context.pipeline().replace(DelegatingHttpRequestHandler.class, "replacedDefaultHandler", channelHandler); } - public static class BuiltInServerThreadFactory implements ThreadFactory { + private static class BuiltInServerThreadFactory implements ThreadFactory { private final AtomicInteger counter = new AtomicInteger(); @Override From 6c9485f94627ed3465c45c4b17143d2ce37a2c57 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 18 Jan 2016 11:21:18 +0100 Subject: [PATCH 176/825] [java] unifies handling of .class file format error (IDEA-150463) --- .../intellij/psi/ClassFileViewProvider.java | 59 +++++++++++-------- .../psi/impl/compiled/ClsFileImpl.java | 8 +-- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java index 72017210db58..26912f00ebae 100644 --- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java +++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java @@ -17,9 +17,7 @@ package com.intellij.psi; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Key; @@ -29,7 +27,12 @@ import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; import com.intellij.psi.impl.file.PsiBinaryFileImpl; import org.jetbrains.annotations.NotNull; -import org.jetbrains.org.objectweb.asm.*; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.org.objectweb.asm.ClassReader; +import org.jetbrains.org.objectweb.asm.ClassVisitor; +import org.jetbrains.org.objectweb.asm.Opcodes; + +import java.io.IOException; import static com.intellij.psi.impl.compiled.ClsFileImpl.EMPTY_ATTRIBUTES; @@ -63,34 +66,44 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { public static boolean isInnerClass(@NotNull VirtualFile file) { String name = file.getNameWithoutExtension(); int p = name.lastIndexOf('$', name.length() - 2); - return p > 0 && detectInnerClass(file); + return p > 0 && detectInnerClass(file, null); } - private static boolean detectInnerClass(VirtualFile file) { + public static boolean isInnerClass(@NotNull VirtualFile file, @NotNull byte[] content) { + String name = file.getNameWithoutExtension(); + int p = name.lastIndexOf('$', name.length() - 2); + return p > 0 && detectInnerClass(file, content); + } + + private static boolean detectInnerClass(VirtualFile file, @Nullable byte[] content) { Boolean isInner = IS_INNER_CLASS.get(file); if (isInner != null) return isInner; + if (content == null) { + try { + content = file.contentsToByteArray(false); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + ClassReader reader = new ClassReader(content); + final Ref ref = Ref.create(Boolean.FALSE); - try { - ClassReader reader = new ClassReader(file.contentsToByteArray(false)); - final String className = reader.getClassName(); - reader.accept(new ClassVisitor(Opcodes.ASM5) { - @Override - public void visitOuterClass(String owner, String name, String desc) { + final String className = reader.getClassName(); + reader.accept(new ClassVisitor(Opcodes.ASM5) { + @Override + public void visitOuterClass(String owner, String name, String desc) { + ref.set(Boolean.TRUE); + } + + @Override + public void visitInnerClass(String name, String outer, String inner, int access) { + if (className.equals(name)) { ref.set(Boolean.TRUE); } - - @Override - public void visitInnerClass(String name, String outer, String inner, int access) { - if (className.equals(name)) { - ref.set(Boolean.TRUE); - } - } - }, EMPTY_ATTRIBUTES, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); - } - catch (Exception e) { - Logger.getInstance(ClassFileViewProvider.class).warn(file.getPath(), e); - } + } + }, EMPTY_ATTRIBUTES, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); isInner = ref.get(); IS_INNER_CLASS.set(file, isInner); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index 431d1611e5da..54fab09a5dd9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -584,11 +584,11 @@ public class ClsFileImpl extends ClsRepositoryPsiElement @Nullable public static PsiJavaFileStub buildFileStub(@NotNull VirtualFile file, @NotNull byte[] bytes) throws ClsFormatException { - if (ClassFileViewProvider.isInnerClass(file)) { - return null; - } - try { + if (ClassFileViewProvider.isInnerClass(file, bytes)) { + return null; + } + ClassReader reader = new ClassReader(bytes); String className = file.getNameWithoutExtension(); String packageName = getPackageName(reader.getClassName()); From d9cb1091d0a8a14073cff6ff2af6df5462b9ed69 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 18 Jan 2016 13:21:38 +0300 Subject: [PATCH 177/825] IDEA-150534 DebugConfigureAction DebugLogConfigureDialog is missing getDimensionServiceKey() --- .../src/com/intellij/ide/actions/DebugLogConfigureAction.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.kt b/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.kt index 92e8dc88b4c6..b8e6efacdce0 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.kt +++ b/platform/platform-impl/src/com/intellij/ide/actions/DebugLogConfigureAction.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -60,6 +60,10 @@ private class DebugLogConfigureDialog(project: Project, categories: ListAppend '$TRACE_SUFFIX' suffix to a category to enable TRACE level.")) } From 2b967867173716ddb4c27dda746913469a6f0834 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 18 Jan 2016 13:29:59 +0300 Subject: [PATCH 178/825] IDEA-150458 Xml: invalid regular expression error --- .../src/META-INF/XmlPlugin.xml | 2 + .../daemon/XmlHighlightingTest.java | 4 + .../testData/xml/WrongRegExpCategory.xsd | 9 +++ .../testData/xml/WrongRegExpInSchema.xsd | 2 +- .../testData/xml/WrongRegExpInSchema2.xsd | 4 +- .../providers/SchemaReferencesProvider.java | 65 ++------------- .../impl/providers/XsdRegExpInjector.java | 53 ++++++++++++ .../providers/XsdRegExpParserDefinition.java | 60 ++++++++++++++ .../source/xml/XmlAttributeValueImpl.java | 80 ++++++++++++++++++- xml/xml-psi-impl/xml-psi-impl.iml | 4 +- 10 files changed, 220 insertions(+), 63 deletions(-) create mode 100644 xml/tests/testData/xml/WrongRegExpCategory.xsd create mode 100644 xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpInjector.java create mode 100644 xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpParserDefinition.java diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 50f6344e39f7..72f5eae8af75 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -363,6 +363,8 @@ implementationClass="com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider"/> + + diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java index 4c3dc2f5886b..87526b8326b5 100644 --- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java +++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java @@ -627,6 +627,10 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { doTest(getFullRelativeTestName("2.xsd"), true, false); } + public void testWrongRegExpCategory() throws Exception { + doTest(getFullRelativeTestName(".xsd"), true, false); + } + public void testXercesMessagesBinding2() throws Exception { final String url = getTestName(false) + ".xsd"; ExternalResourceManagerExImpl.registerResourceTemporarily(url, url, getTestRootDisposable()); diff --git a/xml/tests/testData/xml/WrongRegExpCategory.xsd b/xml/tests/testData/xml/WrongRegExpCategory.xsd new file mode 100644 index 000000000000..d6359d706f1b --- /dev/null +++ b/xml/tests/testData/xml/WrongRegExpCategory.xsd @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/xml/WrongRegExpInSchema.xsd b/xml/tests/testData/xml/WrongRegExpInSchema.xsd index d458eff2bd7d..6bcd0cd11871 100644 --- a/xml/tests/testData/xml/WrongRegExpInSchema.xsd +++ b/xml/tests/testData/xml/WrongRegExpInSchema.xsd @@ -1,7 +1,7 @@ - +*)"/> diff --git a/xml/tests/testData/xml/WrongRegExpInSchema2.xsd b/xml/tests/testData/xml/WrongRegExpInSchema2.xsd index 1e149efb3b2c..5032989f5601 100644 --- a/xml/tests/testData/xml/WrongRegExpInSchema2.xsd +++ b/xml/tests/testData/xml/WrongRegExpInSchema2.xsd @@ -6,8 +6,8 @@ - - + + diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java index 97613a6f2bcf..a5ae697f06ab 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java @@ -15,11 +15,15 @@ */ package com.intellij.psi.impl.source.resolve.reference.impl.providers; -import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; +import com.intellij.psi.ElementManipulators; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.impl.source.xml.SchemaPrefixReference; -import com.intellij.psi.xml.*; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; @@ -31,7 +35,6 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -import java.util.regex.Pattern; /** * @by Maxim.Mossienko @@ -39,7 +42,6 @@ import java.util.regex.Pattern; */ public class SchemaReferencesProvider extends PsiReferenceProvider { @NonNls private static final String VALUE_ATTR_NAME = "value"; - @NonNls private static final String PATTERN_TAG_NAME = "pattern"; @NonNls static final String NAME_ATTR_NAME = "name"; @NonNls static final String MEMBER_TYPES_ATTR_NAME = "memberTypes"; @@ -62,53 +64,6 @@ public class SchemaReferencesProvider extends PsiReferenceProvider { VALUE_ATTR_NAME, ITEM_TYPE_ATTR_NAME}; } - static class RegExpReference extends BasicAttributeValueReference implements EmptyResolveMessageProvider { - private String message; - - public RegExpReference(final PsiElement element) { - super(element); - } - - private static final Pattern pattern = Pattern.compile("^(?:\\\\i|\\\\l)"); - private static final Pattern pattern2 = Pattern.compile("([^\\\\])(?:\\\\i|\\\\l)"); - - @Override - @Nullable - public PsiElement resolve() { - try { - String text = getCanonicalText(); - - // \i and \l are special classes that does not present in java reg exps, so replace their occurences with more usable \w - text = pattern2.matcher(pattern.matcher(text).replaceFirst("\\\\w")).replaceAll("$1\\\\w"); - - Pattern.compile(text); - message = null; - return myElement; - } - catch (Exception e) { - message = PsiBundle.message("invalid.regular.expression.message", getCanonicalText()); - return null; - } - } - - @Override - @NotNull - public Object[] getVariants() { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - @Override - public boolean isSoft() { - return false; - } - - @Override - @NotNull - public String getUnresolvedMessagePattern() { - return message; - } - } - public static class NameReference implements PsiReference { private final PsiElement myElement; @@ -178,11 +133,7 @@ public class SchemaReferencesProvider extends PsiReferenceProvider { final String attrName = ((XmlAttribute)parent).getName(); if (VALUE_ATTR_NAME.equals(attrName)) { - if (PATTERN_TAG_NAME.equals(((XmlAttribute)parent).getParent().getLocalName())) { - return new PsiReference[] { new RegExpReference(element) }; - } else { - return PsiReference.EMPTY_ARRAY; - } + return PsiReference.EMPTY_ARRAY; } else if (NAME_ATTR_NAME.equals(attrName)) { return new PsiReference[] { new NameReference(element) }; } else if (MEMBER_TYPES_ATTR_NAME.equals(attrName)) { diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpInjector.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpInjector.java new file mode 100644 index 000000000000..6e8ebde2d692 --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpInjector.java @@ -0,0 +1,53 @@ +/* + * 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. + */ +package com.intellij.psi.impl.source.resolve.reference.impl.providers; + +import com.intellij.lang.injection.MultiHostInjector; +import com.intellij.lang.injection.MultiHostRegistrar; +import com.intellij.patterns.XmlAttributeValuePattern; +import com.intellij.patterns.XmlPatterns; +import com.intellij.psi.ElementManipulators; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.xml.util.XmlUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class XsdRegExpInjector implements MultiHostInjector { + + private static final XmlAttributeValuePattern PATTERN = + XmlPatterns.xmlAttributeValue("value").withSuperParent(2, XmlPatterns.xmlTag().withLocalName("pattern").withNamespace( + XmlUtil.SCHEMA_URIS)); + + @Override + public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) { + + if (PATTERN.accepts(context)) { + registrar.startInjecting(XsdRegExpParserDefinition.LANGUAGE). + addPlace(null, null, (PsiLanguageInjectionHost)context, ElementManipulators.getValueTextRange(context)). + doneInjecting(); + } + } + + @NotNull + @Override + public List> elementsToInjectIn() { + return Collections.singletonList(XmlAttributeValue.class); + } +} diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpParserDefinition.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpParserDefinition.java new file mode 100644 index 000000000000..df41bfe6a10a --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/XsdRegExpParserDefinition.java @@ -0,0 +1,60 @@ +/* + * 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. + */ +package com.intellij.psi.impl.source.resolve.reference.impl.providers; + +import com.intellij.lang.Language; +import com.intellij.lang.PsiParser; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.project.Project; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IFileElementType; +import org.intellij.lang.regexp.*; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; + +public class XsdRegExpParserDefinition extends RegExpParserDefinition { + + public static Language LANGUAGE = new Language(RegExpLanguage.INSTANCE, "XsdRegExp") {}; + + private static final IFileElementType XSD_REGEXP_FILE = new IFileElementType("XSD_REGEXP_FILE", LANGUAGE); + + private final EnumSet CAPABILITIES = EnumSet.of(RegExpCapability.XML_SCHEMA_MODE, + RegExpCapability.NESTED_CHARACTER_CLASSES, + RegExpCapability.ALLOW_HORIZONTAL_WHITESPACE_CLASS, + RegExpCapability.UNICODE_CATEGORY_SHORTHAND); + + @NotNull + public Lexer createLexer(Project project) { + return new RegExpLexer(CAPABILITIES); + } + + @Override + public PsiParser createParser(Project project) { + return new RegExpParser(CAPABILITIES); + } + + @Override + public IFileElementType getFileNodeType() { + return XSD_REGEXP_FILE; + } + + @Override + public PsiFile createFile(FileViewProvider viewProvider) { + return new RegExpFile(viewProvider, LANGUAGE); + } +} diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java index 690ec23e015a..d7ce54c3ac27 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeValueImpl.java @@ -34,14 +34,20 @@ import com.intellij.psi.xml.XmlElementType; import com.intellij.psi.xml.XmlTokenType; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import org.intellij.lang.regexp.DefaultRegExpPropertiesProvider; +import org.intellij.lang.regexp.RegExpLanguageHost; +import org.intellij.lang.regexp.psi.RegExpChar; +import org.intellij.lang.regexp.psi.RegExpGroup; +import org.intellij.lang.regexp.psi.RegExpNamedGroupRef; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; /** * @author Mike */ -public class XmlAttributeValueImpl extends XmlElementImpl implements XmlAttributeValue, PsiLanguageInjectionHost, PsiMetaOwner, PsiMetaData { +public class XmlAttributeValueImpl extends XmlElementImpl implements XmlAttributeValue, PsiLanguageInjectionHost, RegExpLanguageHost, PsiMetaOwner, PsiMetaData { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlAttributeValueImpl"); private volatile PsiReference[] myCachedReferences; private volatile long myModCount; @@ -197,4 +203,76 @@ public class XmlAttributeValueImpl extends XmlElementImpl implements XmlAttribut } }; } + + @Override + public boolean characterNeedsEscaping(char c) { + return c == ']' || c == '}'; + } + + @Override + public boolean supportsPerl5EmbeddedComments() { + return false; + } + + @Override + public boolean supportsPossessiveQuantifiers() { + return true; + } + + @Override + public boolean supportsPythonConditionalRefs() { + return false; + } + + @Override + public boolean supportsNamedGroupSyntax(RegExpGroup group) { + return true; + } + + @Override + public boolean supportsNamedGroupRefSyntax(RegExpNamedGroupRef ref) { + return true; + } + + @Override + public boolean supportsExtendedHexCharacter(RegExpChar regExpChar) { + return false; + } + + @Override + public boolean isValidCategory(@NotNull String category) { + if (category.startsWith("Is")) { + try { + return Character.UnicodeBlock.forName(category.substring(2)) != null; + } + catch (IllegalArgumentException e) { + return false; + } + } + category = StringUtil.trimStart(category, "Is"); + for (String[] name : DefaultRegExpPropertiesProvider.getInstance().getAllKnownProperties()) { + if (name[0].equals(category)) { + return true; + } + } + return false; + } + + @NotNull + @Override + public String[][] getAllKnownProperties() { + return DefaultRegExpPropertiesProvider.getInstance().getAllKnownProperties(); + } + + @Nullable + @Override + public String getPropertyDescription(@Nullable String name) { + return DefaultRegExpPropertiesProvider.getInstance().getPropertyDescription(name); + } + + @NotNull + @Override + public String[][] getKnownCharacterClasses() { + return DefaultRegExpPropertiesProvider.getInstance().getKnownCharacterClasses(); + } } diff --git a/xml/xml-psi-impl/xml-psi-impl.iml b/xml/xml-psi-impl/xml-psi-impl.iml index 88df9f4d1616..a11dcfa5948b 100644 --- a/xml/xml-psi-impl/xml-psi-impl.iml +++ b/xml/xml-psi-impl/xml-psi-impl.iml @@ -17,6 +17,6 @@ + - - + \ No newline at end of file From 17ce7979906dad66c66a345be39feadc11ac234a Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 18 Jan 2016 13:19:28 +0300 Subject: [PATCH 179/825] Move Java-specific highlighting info to Java implementation --- .../actions/JavaMarkObjectActionHandler.java | 4 +- .../daemon/impl/JavaHighlightInfoTypes.java | 57 ++++++++++++++++--- .../impl/analysis/HighlightNamesUtil.java | 39 ++++++------- .../impl/analysis/HighlightVisitorImpl.java | 4 +- .../daemon/DaemonAnalyzerTestCase.java | 2 +- .../daemon/JavaExpectedHighlightingData.java | 46 +++++++++++++++ .../daemon/LightDaemonAnalyzerTestCase.java | 3 +- .../daemon/impl/HighlightInfo.java | 21 +------ .../daemon/impl/HighlightInfoType.java | 44 ++++++-------- .../ExpectedHighlightingData.java | 8 ++- 10 files changed, 149 insertions(+), 79 deletions(-) create mode 100644 java/testFramework/src/com/intellij/codeInsight/daemon/JavaExpectedHighlightingData.java diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java index a4ecca3e709b..56597fe99a15 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java @@ -15,7 +15,7 @@ */ package com.intellij.debugger.actions; -import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes; import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.DebuggerUtils; @@ -269,7 +269,7 @@ public class JavaMarkObjectActionHandler extends MarkObjectActionHandler { public static Color getAutoMarkupColor() { final EditorColorsManager manager = EditorColorsManager.getInstance(); - final TextAttributes textAttributes = manager.getGlobalScheme().getAttributes(HighlightInfoType.STATIC_FIELD.getAttributesKey()); + final TextAttributes textAttributes = manager.getGlobalScheme().getAttributes(JavaHighlightInfoTypes.STATIC_FIELD.getAttributesKey()); return textAttributes.getForegroundColor(); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java index 2558ccf43feb..04573c4dbb55 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/JavaHighlightInfoTypes.java @@ -20,14 +20,57 @@ import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection; import com.intellij.ide.highlighter.JavaHighlightingColors; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.colors.CodeInsightColors; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import org.jetbrains.annotations.NotNull; -/** - * @author anna - * Date: 01-Feb-2008 - */ -public interface JavaHighlightInfoTypes { - HighlightInfoType UNUSED_IMPORT = new HighlightInfoType.HighlightInfoTypeSeverityByKey( +public final class JavaHighlightInfoTypes { + private JavaHighlightInfoTypes() { + } + + public final static HighlightInfoType UNUSED_IMPORT = new HighlightInfoType.HighlightInfoTypeSeverityByKey( HighlightDisplayKey.findOrRegister(UnusedImportLocalInspection.SHORT_NAME, UnusedImportLocalInspection.DISPLAY_NAME), CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); - HighlightInfoType JAVA_KEYWORD = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, JavaHighlightingColors.KEYWORD); + public final static HighlightInfoType JAVA_KEYWORD = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, JavaHighlightingColors.KEYWORD); + + public final static HighlightInfoType CLASS_NAME = createSymbolTypeInfo(CodeInsightColors.CLASS_NAME_ATTRIBUTES); + public final static HighlightInfoType LOCAL_VARIABLE = createSymbolTypeInfo(CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); + public final static HighlightInfoType INSTANCE_FIELD = createSymbolTypeInfo(CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); + public final static HighlightInfoType INSTANCE_FINAL_FIELD = createSymbolTypeInfo(CodeInsightColors.INSTANCE_FINAL_FIELD_ATTRIBUTES); + public final static HighlightInfoType STATIC_FIELD = createSymbolTypeInfo(CodeInsightColors.STATIC_FIELD_ATTRIBUTES); + public final static HighlightInfoType STATIC_FINAL_FIELD = createSymbolTypeInfo(CodeInsightColors.STATIC_FINAL_FIELD_ATTRIBUTES); + public final static HighlightInfoType PARAMETER = createSymbolTypeInfo(CodeInsightColors.PARAMETER_ATTRIBUTES); + public final static HighlightInfoType METHOD_CALL = createSymbolTypeInfo(CodeInsightColors.METHOD_CALL_ATTRIBUTES); + public final static HighlightInfoType METHOD_DECLARATION = createSymbolTypeInfo(CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); + public final static HighlightInfoType CONSTRUCTOR_CALL = createSymbolTypeInfo(CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); + public final static HighlightInfoType CONSTRUCTOR_DECLARATION = createSymbolTypeInfo(CodeInsightColors.CONSTRUCTOR_DECLARATION_ATTRIBUTES); + public final static HighlightInfoType STATIC_METHOD = createSymbolTypeInfo(CodeInsightColors.STATIC_METHOD_ATTRIBUTES); + public final static HighlightInfoType ABSTRACT_METHOD = createSymbolTypeInfo(CodeInsightColors.ABSTRACT_METHOD_ATTRIBUTES); + public final static HighlightInfoType INHERITED_METHOD = createSymbolTypeInfo(CodeInsightColors.INHERITED_METHOD_ATTRIBUTES); + public final static HighlightInfoType ANONYMOUS_CLASS_NAME = createSymbolTypeInfo(CodeInsightColors.ANONYMOUS_CLASS_NAME_ATTRIBUTES); + public final static HighlightInfoType INTERFACE_NAME = createSymbolTypeInfo(CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); + public final static HighlightInfoType ENUM_NAME = createSymbolTypeInfo(CodeInsightColors.ENUM_NAME_ATTRIBUTES); + public final static HighlightInfoType TYPE_PARAMETER_NAME + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES); + public final static HighlightInfoType ABSTRACT_CLASS_NAME = createSymbolTypeInfo(CodeInsightColors.ABSTRACT_CLASS_NAME_ATTRIBUTES); + public final static HighlightInfoType ANNOTATION_NAME + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES); + public final static HighlightInfoType ANNOTATION_ATTRIBUTE_NAME + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES); + public final static HighlightInfoType REASSIGNED_LOCAL_VARIABLE + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); + public final static HighlightInfoType REASSIGNED_PARAMETER + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); + public final static HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER + = new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, + CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); + + private static HighlightInfoType createSymbolTypeInfo(@NotNull TextAttributesKey attributesKey) { + return new HighlightInfoType.HighlightInfoTypeImpl(HighlightInfoType.SYMBOL_TYPE_SEVERITY, attributesKey, false); + } + } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java index eb085f3649eb..7d8fc50db7a1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java @@ -22,6 +22,7 @@ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.application.options.colors.ScopeAttributesUtil; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.TextAttributesKey; @@ -171,32 +172,32 @@ public class HighlightNamesUtil { private static HighlightInfoType getMethodNameHighlightType(@NotNull PsiMethod method, boolean isDeclaration, boolean isInheritedMethod) { if (method.isConstructor()) { - return isDeclaration ? HighlightInfoType.CONSTRUCTOR_DECLARATION : HighlightInfoType.CONSTRUCTOR_CALL; + return isDeclaration ? JavaHighlightInfoTypes.CONSTRUCTOR_DECLARATION : JavaHighlightInfoTypes.CONSTRUCTOR_CALL; } - if (isDeclaration) return HighlightInfoType.METHOD_DECLARATION; + if (isDeclaration) return JavaHighlightInfoTypes.METHOD_DECLARATION; if (method.hasModifierProperty(PsiModifier.STATIC)) { - return HighlightInfoType.STATIC_METHOD; + return JavaHighlightInfoTypes.STATIC_METHOD; } - if (isInheritedMethod) return HighlightInfoType.INHERITED_METHOD; + if (isInheritedMethod) return JavaHighlightInfoTypes.INHERITED_METHOD; if(method.hasModifierProperty(PsiModifier.ABSTRACT)) { - return HighlightInfoType.ABSTRACT_METHOD; + return JavaHighlightInfoTypes.ABSTRACT_METHOD; } - return HighlightInfoType.METHOD_CALL; + return JavaHighlightInfoTypes.METHOD_CALL; } @Nullable private static HighlightInfoType getVariableNameHighlightType(PsiVariable var) { if (var instanceof PsiLocalVariable || var instanceof PsiParameter && ((PsiParameter)var).getDeclarationScope() instanceof PsiForeachStatement) { - return HighlightInfoType.LOCAL_VARIABLE; + return JavaHighlightInfoTypes.LOCAL_VARIABLE; } if (var instanceof PsiField) { return var.hasModifierProperty(PsiModifier.STATIC) - ? var.hasModifierProperty(PsiModifier.FINAL) ? HighlightInfoType.STATIC_FINAL_FIELD : HighlightInfoType.STATIC_FIELD - : var.hasModifierProperty(PsiModifier.FINAL) ? HighlightInfoType.INSTANCE_FINAL_FIELD : HighlightInfoType.INSTANCE_FIELD; + ? var.hasModifierProperty(PsiModifier.FINAL) ? JavaHighlightInfoTypes.STATIC_FINAL_FIELD : JavaHighlightInfoTypes.STATIC_FIELD + : var.hasModifierProperty(PsiModifier.FINAL) ? JavaHighlightInfoTypes.INSTANCE_FINAL_FIELD : JavaHighlightInfoTypes.INSTANCE_FIELD; } if (var instanceof PsiParameter) { - return HighlightInfoType.PARAMETER; + return JavaHighlightInfoTypes.PARAMETER; } return null; } @@ -204,27 +205,27 @@ public class HighlightNamesUtil { @NotNull private static HighlightInfoType getClassNameHighlightType(@Nullable PsiClass aClass, @Nullable PsiElement element) { if (element instanceof PsiJavaCodeReferenceElement && element.getParent() instanceof PsiAnonymousClass) { - return HighlightInfoType.ANONYMOUS_CLASS_NAME; + return JavaHighlightInfoTypes.ANONYMOUS_CLASS_NAME; } if (aClass != null) { - if (aClass.isAnnotationType()) return HighlightInfoType.ANNOTATION_NAME; - if (aClass.isInterface()) return HighlightInfoType.INTERFACE_NAME; - if (aClass.isEnum()) return HighlightInfoType.ENUM_NAME; - if (aClass instanceof PsiTypeParameter) return HighlightInfoType.TYPE_PARAMETER_NAME; + if (aClass.isAnnotationType()) return JavaHighlightInfoTypes.ANNOTATION_NAME; + if (aClass.isInterface()) return JavaHighlightInfoTypes.INTERFACE_NAME; + if (aClass.isEnum()) return JavaHighlightInfoTypes.ENUM_NAME; + if (aClass instanceof PsiTypeParameter) return JavaHighlightInfoTypes.TYPE_PARAMETER_NAME; final PsiModifierList modList = aClass.getModifierList(); - if (modList != null && modList.hasModifierProperty(PsiModifier.ABSTRACT)) return HighlightInfoType.ABSTRACT_CLASS_NAME; + if (modList != null && modList.hasModifierProperty(PsiModifier.ABSTRACT)) return JavaHighlightInfoTypes.ABSTRACT_CLASS_NAME; } // use class by default - return HighlightInfoType.CLASS_NAME; + return JavaHighlightInfoTypes.CLASS_NAME; } @Nullable static HighlightInfo highlightReassignedVariable(PsiVariable variable, PsiElement elementToHighlight) { if (variable instanceof PsiLocalVariable) { - return HighlightInfo.newHighlightInfo(HighlightInfoType.REASSIGNED_LOCAL_VARIABLE).range(elementToHighlight).create(); + return HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.REASSIGNED_LOCAL_VARIABLE).range(elementToHighlight).create(); } if (variable instanceof PsiParameter) { - return HighlightInfo.newHighlightInfo(HighlightInfoType.REASSIGNED_PARAMETER).range(elementToHighlight).create(); + return HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.REASSIGNED_PARAMETER).range(elementToHighlight).create(); } return null; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 68710e22e50e..9630347d7847 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -926,7 +926,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) { PsiIdentifier nameId = pair.getNameIdentifier(); if (nameId != null) { - HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME).range(nameId).create(); + HighlightInfo result = HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.ANNOTATION_ATTRIBUTE_NAME).range(nameId).create(); myHolder.add(result); } } @@ -1080,7 +1080,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh !PsiTreeUtil.isAncestor(containingClass, variable, false) && !(variable instanceof PsiField)) { if (!PsiTreeUtil.isAncestor(((PsiAnonymousClass) containingClass).getArgumentList(), ref, false)) { - myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER).range(ref).create()); + myHolder.add(HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.IMPLICIT_ANONYMOUS_CLASS_PARAMETER).range(ref).create()); } } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index e7132dac9283..96874087f166 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -216,7 +216,7 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { public HighlightTestInfo doTest() { try { configureByFiles(projectRoot, filePaths); } catch (Exception e) { throw new RuntimeException(e); } - ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); + ExpectedHighlightingData data = new JavaExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); if (checkSymbolNames) data.checkSymbolNames(); checkHighlighting(data); return this; diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/JavaExpectedHighlightingData.java b/java/testFramework/src/com/intellij/codeInsight/daemon/JavaExpectedHighlightingData.java new file mode 100644 index 000000000000..5a427b1762f4 --- /dev/null +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/JavaExpectedHighlightingData.java @@ -0,0 +1,46 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon; + +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes; +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.ExpectedHighlightingData; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; + +public class JavaExpectedHighlightingData extends ExpectedHighlightingData { + public JavaExpectedHighlightingData(@NotNull Document document, + boolean checkWarnings, + boolean checkWeakWarnings, + boolean checkInfos, @Nullable PsiFile file) { + super(document, checkWarnings, checkWeakWarnings, checkInfos, file); + } + + @Override + protected HighlightInfoType getTypeByName(String typeString) throws Exception { + try { + Field field = JavaHighlightInfoTypes.class.getField(typeString); + return (HighlightInfoType)field.get(null); + } + catch (Exception e) { + return super.getTypeByName(typeString); + } + } +} diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index d06a63fb70a0..4746140f3bb6 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon; import com.intellij.codeHighlighting.Pass; import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.lang.injection.InjectedLanguageManager; @@ -126,7 +127,7 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa public HighlightTestInfo doTest() { String path = assertOneElement(filePaths); configureByFile(path); - ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); + ExpectedHighlightingData data = new JavaExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile); if (checkSymbolNames) data.checkSymbolNames(); checkHighlighting(data, composeLocalPath(path)); diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index efefd95623b9..e3a614952c4d 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -292,24 +292,9 @@ public class HighlightInfo implements Segment { private static boolean calcNeedUpdateOnTyping(@Nullable Boolean needsUpdateOnTyping, HighlightInfoType type) { if (needsUpdateOnTyping != null) return needsUpdateOnTyping.booleanValue(); - if (type == HighlightInfoType.TODO) return false; - if (type == HighlightInfoType.LOCAL_VARIABLE) return false; - if (type == HighlightInfoType.INSTANCE_FIELD) return false; - if (type == HighlightInfoType.STATIC_FIELD) return false; - if (type == HighlightInfoType.STATIC_FINAL_FIELD) return false; - if (type == HighlightInfoType.PARAMETER) return false; - if (type == HighlightInfoType.METHOD_CALL) return false; - if (type == HighlightInfoType.METHOD_DECLARATION) return false; - if (type == HighlightInfoType.STATIC_METHOD) return false; - if (type == HighlightInfoType.ABSTRACT_METHOD) return false; - if (type == HighlightInfoType.INHERITED_METHOD) return false; - if (type == HighlightInfoType.CONSTRUCTOR_CALL) return false; - if (type == HighlightInfoType.CONSTRUCTOR_DECLARATION) return false; - if (type == HighlightInfoType.INTERFACE_NAME) return false; - if (type == HighlightInfoType.ABSTRACT_CLASS_NAME) return false; - if (type == HighlightInfoType.ENUM_NAME) return false; - if (type == HighlightInfoType.CLASS_NAME) return false; - if (type == HighlightInfoType.ANONYMOUS_CLASS_NAME) return false; + if (type instanceof HighlightInfoType.UpdateOnTypingSuppressible) { + return ((HighlightInfoType.UpdateOnTypingSuppressible)type).needsUpdateOnTyping(); + } return true; } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java index ade2f5040ba4..826c8c512be4 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java @@ -67,32 +67,7 @@ public interface HighlightInfoType { HighlightSeverity SYMBOL_TYPE_SEVERITY = new HighlightSeverity("SYMBOL_TYPE_SEVERITY", HighlightSeverity.INFORMATION.myVal-2); - HighlightInfoType LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); - HighlightInfoType INSTANCE_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); - HighlightInfoType INSTANCE_FINAL_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INSTANCE_FINAL_FIELD_ATTRIBUTES); - HighlightInfoType STATIC_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_FIELD_ATTRIBUTES); - HighlightInfoType STATIC_FINAL_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_FINAL_FIELD_ATTRIBUTES); - HighlightInfoType PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.PARAMETER_ATTRIBUTES); - HighlightInfoType METHOD_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_CALL_ATTRIBUTES); - HighlightInfoType METHOD_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); - HighlightInfoType CONSTRUCTOR_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); - HighlightInfoType CONSTRUCTOR_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_DECLARATION_ATTRIBUTES); - HighlightInfoType STATIC_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_METHOD_ATTRIBUTES); - HighlightInfoType ABSTRACT_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ABSTRACT_METHOD_ATTRIBUTES); - HighlightInfoType INHERITED_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INHERITED_METHOD_ATTRIBUTES); - HighlightInfoType CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CLASS_NAME_ATTRIBUTES); - HighlightInfoType ANONYMOUS_CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANONYMOUS_CLASS_NAME_ATTRIBUTES); - HighlightInfoType INTERFACE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); - HighlightInfoType ENUM_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ENUM_NAME_ATTRIBUTES); - HighlightInfoType TYPE_PARAMETER_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES); - HighlightInfoType ABSTRACT_CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ABSTRACT_CLASS_NAME_ATTRIBUTES); - HighlightInfoType ANNOTATION_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES); - HighlightInfoType ANNOTATION_ATTRIBUTE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES); - HighlightInfoType REASSIGNED_LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); - HighlightInfoType REASSIGNED_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); - HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); - - HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.TODO_DEFAULT_ATTRIBUTES); // these are default attributes, can be configured differently for specific patterns + HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.TODO_DEFAULT_ATTRIBUTES, false); // these are default attributes, can be configured differently for specific patterns HighlightInfoType UNHANDLED_EXCEPTION = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); HighlightSeverity INJECTED_FRAGMENT_SEVERITY = new HighlightSeverity("INJECTED_FRAGMENT", SYMBOL_TYPE_SEVERITY.myVal - 1); @@ -108,9 +83,10 @@ public interface HighlightInfoType { TextAttributesKey getAttributesKey(); - class HighlightInfoTypeImpl implements HighlightInfoType { + class HighlightInfoTypeImpl implements HighlightInfoType, HighlightInfoType.UpdateOnTypingSuppressible { private final HighlightSeverity mySeverity; private final TextAttributesKey myAttributesKey; + private boolean myNeedsUpdateOnTyping; //read external only HighlightInfoTypeImpl(@NotNull Element element) { @@ -119,8 +95,13 @@ public interface HighlightInfoType { } public HighlightInfoTypeImpl(@NotNull HighlightSeverity severity, TextAttributesKey attributesKey) { + this(severity, attributesKey, true); + } + + public HighlightInfoTypeImpl(@NotNull HighlightSeverity severity, TextAttributesKey attributesKey, boolean needsUpdateOnTyping) { mySeverity = severity; myAttributesKey = attributesKey; + myNeedsUpdateOnTyping = needsUpdateOnTyping; } @Override @@ -169,6 +150,11 @@ public interface HighlightInfoType { result = 29 * result + myAttributesKey.hashCode(); return result; } + + @Override + public boolean needsUpdateOnTyping() { + return myNeedsUpdateOnTyping; + } } class HighlightInfoTypeSeverityByKey implements HighlightInfoType { @@ -212,4 +198,8 @@ public interface HighlightInfoType { interface Iconable { Icon getIcon(); } + + interface UpdateOnTypingSuppressible { + boolean needsUpdateOnTyping(); + } } diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java index 596655def38a..b2100962ec23 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java +++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java @@ -292,8 +292,7 @@ public class ExpectedHighlightingData { HighlightInfoType type = WHATEVER; if (typeString != null) { try { - Field field = HighlightInfoType.class.getField(typeString); - type = (HighlightInfoType)field.get(null); + type = getTypeByName(typeString); } catch (Exception e) { LOG.error(e); @@ -351,6 +350,11 @@ public class ExpectedHighlightingData { return toContinueFrom; } + protected HighlightInfoType getTypeByName(String typeString) throws Exception { + Field field = HighlightInfoType.class.getField(typeString); + return (HighlightInfoType)field.get(null); + } + private static final HighlightInfoType WHATEVER = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, HighlighterColors.TEXT); From 76d0c49f82298d1700a63b8824b92a13071069d5 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 18 Jan 2016 14:34:15 +0300 Subject: [PATCH 180/825] assertion fixed --- .../ide/projectWizard/ProjectTypeStep.java | 52 +++++++++---------- .../com/intellij/openapi/progress/Task.java | 10 +++- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java index 1fdce85e8883..d3abd0cf129d 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java @@ -604,40 +604,40 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D } void loadRemoteTemplates(final ChooseTemplateStep chooseTemplateStep) { + myTemplatesList.setPaintBusy(true); + chooseTemplateStep.getTemplateList().setPaintBusy(true); ProgressManager.getInstance().run(new Task.Backgroundable(myContext.getProject(), "Loading Templates") { @Override public void run(@NotNull ProgressIndicator indicator) { - try { - myTemplatesList.setPaintBusy(true); - chooseTemplateStep.getTemplateList().setPaintBusy(true); - RemoteTemplatesFactory factory = new RemoteTemplatesFactory(); - for (String group : factory.getGroups()) { - ProjectTemplate[] templates = factory.createTemplates(group, myContext); - for (ProjectTemplate template : templates) { - String id = ((ArchivedProjectTemplate)template).getCategory(); - for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) { - if (Comparing.equal(id, templatesGroup.getId()) || Comparing.equal(group, templatesGroup.getName())) { - myTemplatesMap.putValue(templatesGroup, template); - } + RemoteTemplatesFactory factory = new RemoteTemplatesFactory(); + for (String group : factory.getGroups()) { + ProjectTemplate[] templates = factory.createTemplates(group, myContext); + for (ProjectTemplate template : templates) { + String id = ((ArchivedProjectTemplate)template).getCategory(); + for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) { + if (Comparing.equal(id, templatesGroup.getId()) || Comparing.equal(group, templatesGroup.getName())) { + myTemplatesMap.putValue(templatesGroup, template); } } } - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - public void run() { - TemplatesGroup group = getSelectedGroup(); - if (group == null) return; - Collection templates = myTemplatesMap.get(group); - setTemplatesList(group, templates, true); - chooseTemplateStep.updateStep(); - } - }); - } - finally { - myTemplatesList.setPaintBusy(false); - chooseTemplateStep.getTemplateList().setPaintBusy(false); } } + + @Override + public void onSuccess() { + super.onSuccess(); + TemplatesGroup group = getSelectedGroup(); + if (group == null) return; + Collection templates = myTemplatesMap.get(group); + setTemplatesList(group, templates, true); + chooseTemplateStep.updateStep(); + } + + @Override + public void finished() { + myTemplatesList.setPaintBusy(false); + chooseTemplateStep.getTemplateList().setPaintBusy(false); + } }); } diff --git a/platform/core-api/src/com/intellij/openapi/progress/Task.java b/platform/core-api/src/com/intellij/openapi/progress/Task.java index dd64a8ed8582..a8ce293589d1 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/Task.java +++ b/platform/core-api/src/com/intellij/openapi/progress/Task.java @@ -62,12 +62,18 @@ public abstract class Task implements TaskInfo, Progressive { /** * This callback will be invoked on AWT dispatch thread. */ - public void onCancel() { } + public void onCancel() { + finished(); + } /** * This callback will be invoked on AWT dispatch thread. */ - public void onSuccess() { } + public void onSuccess() { + finished(); + } + + protected void finished() {} public final Project getProject() { return myProject; From 68da9940419f6feccf2570c3a984feba81335b93 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 18 Jan 2016 11:55:03 +0100 Subject: [PATCH 181/825] cleanup --- .../src/com/intellij/util/io/HttpRequests.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java index 87004435fff6..c01d258d4b42 100644 --- a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java +++ b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -126,7 +126,7 @@ public final class HttpRequests { return CharsetToolkit.UTF8_CHARSET; } - static T process(final RequestBuilder builder, RequestProcessor processor) throws IOException { + static T process(@NotNull final RequestBuilder builder, @NotNull RequestProcessor processor) throws IOException { class RequestImpl implements Request { private URLConnection myConnection; private InputStream myInputStream; @@ -191,6 +191,7 @@ public final class HttpRequests { } } + @Override @NotNull public byte[] readBytes(@Nullable ProgressIndicator indicator) throws IOException { int contentLength = getConnection().getContentLength(); @@ -199,6 +200,7 @@ public final class HttpRequests { return ArrayUtil.realloc(out.getInternalBuffer(), out.size()); } + @Override @NotNull public File saveToFile(@NotNull File file, @Nullable ProgressIndicator indicator) throws IOException { FileUtilRt.createParentDirs(file); @@ -236,6 +238,7 @@ public final class HttpRequests { } } + @NotNull private static URLConnection openConnection(RequestBuilder builder) throws IOException { String url = builder.myUrl; @@ -284,11 +287,11 @@ public final class HttpRequests { int responseCode = ((HttpURLConnection)connection).getResponseCode(); if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { ((HttpURLConnection)connection).disconnect(); - url = connection.getHeaderField("Location"); - if (url != null) { - continue; + url = connection.getHeaderField("Location"); + if (url != null) { + continue; + } } - } } return connection; From c463c12867e7bc7c5c083c94d36e60cf7b410726 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 18 Jan 2016 12:33:42 +0100 Subject: [PATCH 182/825] IDEA-CR-2176 "HttpRequests class was written for handling content requests; the situation "all a client wants is a response code" seems rare to me - so a better solution would be to either add something like int tryConnect() to RequestBuilder, or throw an IOException subclass, or both." --- .../frameworks/SettingsConnectionService.java | 9 +---- .../paths/WebReferencesAnnotatorBase.java | 16 ++------ .../com/intellij/util/io/HttpRequests.java | 37 ++++++++++++++++++- .../com/intellij/util/io/RequestBuilder.java | 21 ++++++++++- .../util/net/HttpProxySettingsUi.java | 13 +------ .../http/DefaultRemoteContentProvider.java | 8 +--- 6 files changed, 63 insertions(+), 41 deletions(-) diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java index a4ec415abcb6..03eb24efb92f 100644 --- a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java +++ b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.net.HttpURLConnection; import java.util.Collections; import java.util.Map; @@ -69,12 +68,6 @@ public abstract class SettingsConnectionService { .connect(new HttpRequests.RequestProcessor>() { @Override public Map process(@NotNull HttpRequests.Request request) throws IOException { - if (!request.isSuccessful()) { - HttpURLConnection connection = (HttpURLConnection)request.getConnection(); - LOG.warn(connection.getResponseCode() + " " + connection.getResponseMessage()); - return Collections.emptyMap(); - } - Map settings = ContainerUtilRt.newLinkedHashMap(); try { Element root = JDOMUtil.load(request.getReader()); diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/WebReferencesAnnotatorBase.java b/platform/lang-impl/src/com/intellij/openapi/paths/WebReferencesAnnotatorBase.java index 1ceb9dc9b5c7..42b3e162af30 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/WebReferencesAnnotatorBase.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/WebReferencesAnnotatorBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -32,8 +32,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URLConnection; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collection; @@ -188,14 +186,7 @@ public abstract class WebReferencesAnnotatorBase extends ExternalAnnotator() { - @Override - public MyFetchResult process(@NotNull HttpRequests.Request request) throws IOException { - URLConnection connection = request.getConnection(); - int code = connection instanceof HttpURLConnection ? ((HttpURLConnection)connection).getResponseCode() : 0; - return code == 200 || code == 408 ? MyFetchResult.OK : MyFetchResult.NONEXISTENCE; - } - }); + HttpRequests.request(url).connectTimeout(3000).readTimeout(3000).tryConnect(); } catch (UnknownHostException e) { LOG.info(e); @@ -203,12 +194,11 @@ public abstract class WebReferencesAnnotatorBase extends ExternalAnnotator processor = new HttpRequests.RequestProcessor() { + @Override + public Integer process(@NotNull HttpRequests.Request request) throws IOException { + URLConnection connection = request.getConnection(); + return connection instanceof HttpURLConnection ? ((HttpURLConnection)connection).getResponseCode() : -1; + } + }; + + if (ourWrapClassLoader) { + return HttpRequests.wrapAndProcess(this, processor); + } + else { + return HttpRequests.process(this, processor); + } + } + public T connect(@NotNull HttpRequests.RequestProcessor processor, T errorValue, @Nullable Logger logger) { try { return connect(processor); diff --git a/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java index e4f8d0237ebe..7cf912f1daeb 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -40,7 +40,6 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; -import java.net.HttpURLConnection; import java.util.concurrent.atomic.AtomicReference; class HttpProxySettingsUi implements ConfigurableUi { @@ -178,15 +177,7 @@ class HttpProxySettingsUi implements ConfigurableUi { //noinspection ConstantConditions HttpRequests.request(answer) .readTimeout(3 * 1000) - .connect(new HttpRequests.RequestProcessor() { - @Override - public Void process(@NotNull HttpRequests.Request request) throws IOException { - if (!request.isSuccessful()) { - exceptionReference.set(new IOException("Error code: " + ((HttpURLConnection)request.getConnection()).getResponseCode())); - } - return null; - } - }); + .tryConnect(); } catch (IOException e) { exceptionReference.set(e); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java index 80b8c78f10e9..c74cecb41df7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -15,7 +15,6 @@ */ package com.intellij.openapi.vfs.impl.http; -import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; @@ -33,7 +32,6 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; -import java.net.HttpURLConnection; public class DefaultRemoteContentProvider extends RemoteContentProvider { private static final Logger LOG = Logger.getInstance(DefaultRemoteContentProvider.class); @@ -65,10 +63,6 @@ public class DefaultRemoteContentProvider extends RemoteContentProvider { .connect(new HttpRequests.RequestProcessor() { @Override public Object process(@NotNull HttpRequests.Request request) throws IOException { - if (!request.isSuccessful()) { - throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", ((HttpURLConnection)request.getConnection()).getResponseCode())); - } - int size = request.getConnection().getContentLength(); callback.setProgressText(VfsBundle.message("download.progress.downloading", presentableUrl), size == -1); request.saveToFile(file, new AbstractProgressIndicatorExBase() { From 9520aa658693e2b856baa5557a8683a2681fe49d Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 18 Jan 2016 14:40:35 +0300 Subject: [PATCH 183/825] IDEA-150547 some labels are not accessible by mouse --- .../intellij/openapi/ui/impl/DialogWrapperPeerImpl.java | 7 +++++++ .../openapi/ui/impl/GlassPaneDialogWrapperPeer.java | 7 +++++++ .../src/com/intellij/openapi/wm/impl/IdeRootPane.java | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index a3cbe29dbd85..7b8723838b52 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -1092,6 +1092,13 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra super.setGlassPane(glass); } + @Override + public void setContentPane(Container contentPane) { + if (contentPane != null) { + contentPane.addMouseMotionListener(new MouseMotionAdapter() {}); // listen to mouse motino events for a11y + } + } + @Override public Object getData(@NonNls String dataId) { final DialogWrapper wrapper = myDialogWrapper.get(); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index 9e2e3942c2a6..19b169c2769e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -734,6 +734,13 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc public void setDefaultButton(final JButton defaultButton) { myDialog.setDefaultButton(defaultButton); } + + @Override + public void setContentPane(Container contentPane) { + if (contentPane != null) { + contentPane.addMouseMotionListener(new MouseMotionAdapter() {}); // listen to mouse motion events for a11y + } + } } public static class GlasspanePeerUnavailableException extends Exception { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java index 15143b8480d5..e5bc597dd70d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java @@ -49,6 +49,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseMotionAdapter; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; @@ -91,6 +93,8 @@ public class IdeRootPane extends JRootPane implements UISettingsListener { myContentPane.add(myNorthPanel, BorderLayout.NORTH); + myContentPane.addMouseMotionListener(new MouseMotionAdapter() {}); // listen to mouse motion events for a11y + myStatusBarCustomComponentFactories = application.getExtensions(StatusBarCustomComponentFactory.EP_NAME); myApplication = application; From 5f203646e836d15a0530942650c9dab30ad59ef9 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Mon, 18 Jan 2016 14:43:13 +0300 Subject: [PATCH 184/825] updated versions of educational plugins --- python/edu/course-creator-python/resources/META-INF/plugin.xml | 2 +- .../interactive-learning-python/resources/META-INF/plugin.xml | 2 +- python/edu/resources/META-INF/plugin.xml | 2 +- python/educational/course-creator/resources/META-INF/plugin.xml | 2 +- .../interactive-learning/resources/META-INF/plugin.xml | 2 +- python/educational/resources/META-INF/plugin.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/edu/course-creator-python/resources/META-INF/plugin.xml b/python/edu/course-creator-python/resources/META-INF/plugin.xml index 23336b9e0df0..31ea1abbc582 100644 --- a/python/edu/course-creator-python/resources/META-INF/plugin.xml +++ b/python/edu/course-creator-python/resources/META-INF/plugin.xml @@ -1,7 +1,7 @@ com.jetbrains.edu.coursecreator.python Course Creator for PyCharm Edu - 2.0 + 2.0.3 . diff --git a/python/edu/interactive-learning-python/resources/META-INF/plugin.xml b/python/edu/interactive-learning-python/resources/META-INF/plugin.xml index 50e440f105b1..6bb96a57f776 100644 --- a/python/edu/interactive-learning-python/resources/META-INF/plugin.xml +++ b/python/edu/interactive-learning-python/resources/META-INF/plugin.xml @@ -2,7 +2,7 @@ com.jetbrains.python.edu.interactivelearning.python Educational plugin for PyCharm - 2.0.2 + 2.0.4 com.jetbrains.python.edu.core Python-specific part for Stepic connector - 2.0 + 2.0.3 com.jetbrains.edu.coursecreator Course Creator Plugin - 2.0 + 2.0.3 com.jetbrains.edu.interactivelearning Educational plugin core - 2.0.2 + 2.0.4 com.jetbrains.edu.core Stepic connector - 2.0 + 2.0.3 Date: Mon, 18 Jan 2016 15:27:01 +0300 Subject: [PATCH 185/825] API cleanup: removed long ago deprecated --- .../com/intellij/xdebugger/XDebugSession.java | 7 +--- .../com/intellij/xdebugger/XNamedValue.java | 30 ---------------- .../evaluation/XDebuggerEvaluator.java | 35 ++----------------- .../frame/XInlineDebuggerDataCallback.java | 14 +------- .../frame/XInlineSourcePosition.java | 24 ------------- .../frame/XNearestSourcePosition.java | 24 ------------- .../intellij/xdebugger/frame/XValueNode.java | 20 +---------- .../xdebugger/impl/XDebugSessionImpl.java | 5 --- .../impl/ui/tree/nodes/XValueNodeImpl.java | 29 ++------------- .../XValueNodePresentationConfigurator.java | 21 +---------- 10 files changed, 10 insertions(+), 199 deletions(-) delete mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java delete mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineSourcePosition.java delete mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/frame/XNearestSourcePosition.java diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java index 39d0b125488a..24931333f84f 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -93,11 +93,6 @@ public interface XDebugSession extends AbstractDebuggerSession { void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame, boolean isTopFrame); - /** - * @deprecated use {@link #setCurrentStackFrame(com.intellij.xdebugger.frame.XExecutionStack, com.intellij.xdebugger.frame.XStackFrame, boolean)} instead - */ - void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame); - /** * Call this method to setup custom icon and/or error message (it will be shown in tooltip) for breakpoint * diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java deleted file mode 100644 index 8e6c01c1560a..000000000000 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - */ -package com.intellij.xdebugger; - -import com.intellij.openapi.util.text.StringUtil; - -/** - * @deprecated use {@link com.intellij.xdebugger.frame.XNamedValue} instead. Note that {@code name} parameter in its constructor cannot be {@code null} - * - * @author traff - */ -@Deprecated -public abstract class XNamedValue extends com.intellij.xdebugger.frame.XNamedValue { - public XNamedValue(String name) { - super(StringUtil.notNullize(name)); - } -} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java index e008252ecf85..646ef723030d 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -16,14 +16,10 @@ package com.intellij.xdebugger.evaluation; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.xdebugger.XDebugSession; -import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpoint; @@ -126,30 +122,6 @@ public abstract class XDebuggerEvaluator { return null; } - /** - * @deprecated Use {@link #getExpressionInfoAtOffset(com.intellij.openapi.project.Project, com.intellij.openapi.editor.Document, int, boolean)} - * - * Return text range of expression which can be evaluated. - * - * @param project project - * @param document document - * @param offset offset - * @param sideEffectsAllowed if this parameter is false, the expression should not have any side effects when evaluated - * (such expressions are evaluated in quick popups) - * @return pair of text range of expression (to highlight as link) and actual expression to evaluate (optional, could be null) - */ - @Nullable - @Deprecated - public Pair getExpressionAtOffset(@NotNull Project project, @NotNull Document document, int offset, boolean sideEffectsAllowed) { - TextRange range = getExpressionRangeAtOffset(project, document, offset, sideEffectsAllowed); - if (range == null) { - return null; - } - else { - return Pair.create(range, null); - } - } - /** * @param project project * @param document document @@ -160,9 +132,8 @@ public abstract class XDebuggerEvaluator { */ @Nullable public ExpressionInfo getExpressionInfoAtOffset(@NotNull Project project, @NotNull Document document, int offset, boolean sideEffectsAllowed) { - @SuppressWarnings("deprecation") - Pair result = getExpressionAtOffset(project, document, offset, sideEffectsAllowed); - return result == null ? null : new ExpressionInfo(result.first, result.second); + TextRange range = getExpressionRangeAtOffset(project, document, offset, sideEffectsAllowed); + return range == null ? null : new ExpressionInfo(range); } /** diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineDebuggerDataCallback.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineDebuggerDataCallback.java index 1f6ce2d854bf..72d777757b71 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineDebuggerDataCallback.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineDebuggerDataCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -15,20 +15,8 @@ */ package com.intellij.xdebugger.frame; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; -import org.jetbrains.annotations.NotNull; public abstract class XInlineDebuggerDataCallback { - /** - * @deprecated use {@link #computed(XSourcePosition)} instead - */ - @Deprecated - public void computed(@NotNull VirtualFile file, @SuppressWarnings("UnusedParameters") @NotNull Document document, int line) { - computed(XDebuggerUtil.getInstance().createPosition(file, line)); - } - public abstract void computed(XSourcePosition position); } \ No newline at end of file diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineSourcePosition.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineSourcePosition.java deleted file mode 100644 index 2b4274ebd5d5..000000000000 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineSourcePosition.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.xdebugger.frame; - -/** - * @deprecated override {@link XValue#computeInlineDebuggerData(XInlineDebuggerDataCallback)} instead - * @author egor - */ -@Deprecated -public interface XInlineSourcePosition extends XNavigatable { -} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XNearestSourcePosition.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XNearestSourcePosition.java deleted file mode 100644 index 31545fbb05f4..000000000000 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XNearestSourcePosition.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.xdebugger.frame; - -/** - * @deprecated override {@link XValue#computeInlineDebuggerData(XInlineDebuggerDataCallback)} instead - * @author Konstantin Bulenkov - */ -@Deprecated -public interface XNearestSourcePosition extends XInlineSourcePosition { -} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java index 5d63f0beddb5..04fa10c74ed3 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -15,7 +15,6 @@ */ package com.intellij.xdebugger.frame; -import com.intellij.util.NotNullFunction; import com.intellij.xdebugger.Obsolescent; import com.intellij.xdebugger.frame.presentation.XValuePresentation; import org.jetbrains.annotations.NonNls; @@ -60,23 +59,6 @@ public interface XValueNode extends Obsolescent { */ void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @Nullable String value, boolean hasChildren); - /** - * The same as {@link #setPresentation(javax.swing.Icon, String, String, boolean)} but allows to change default processing of - * {@code value} parameter using custom {@code valuePresenter} function. By default only invisible characters like tabs or line separators - * are escaped in the value. {@code valuePresenter} function doesn't affect 'Copy Value' action. It can be used to escape additional - * characters and/or surround value by quotes. - * - * @deprecated use {@link #setPresentation(javax.swing.Icon, XValuePresentation, boolean)} - */ - void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value, - @Nullable NotNullFunction valuePresenter, boolean hasChildren); - - /** - * @deprecated use {@link #setPresentation(javax.swing.Icon, XValuePresentation, boolean)} - */ - void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String separator, @NonNls @NotNull String value, - @Nullable NotNullFunction valuePresenter, boolean hasChildren); - /** * If string representation of the value is too long to show in the tree pass truncated value to {@link #setPresentation(javax.swing.Icon, String, String, boolean)} * method and call this method to provide full value. diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 8e3126afe70f..71d847bcd69b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -607,11 +607,6 @@ public class XDebugSessionImpl implements XDebugSession { } } - @Override - public void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame) { - setCurrentStackFrame(myCurrentExecutionStack, frame, frame == executionStack.getTopFrame()); - } - @Override public void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame, boolean isTopFrame) { if (mySuspendContext == null) return; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index a90483d34203..d81ec228379e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -24,7 +24,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ColoredTextContainer; import com.intellij.ui.SimpleTextAttributes; -import com.intellij.util.NotNullFunction; import com.intellij.util.ThreeState; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.XDebugSession; @@ -95,30 +94,11 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu XValueNodePresentationConfigurator.setPresentation(icon, type, separator, value, hasChildren, this); } - @Override - public void setPresentation(@Nullable Icon icon, - @NonNls @Nullable String type, - @NonNls @NotNull String value, - @Nullable NotNullFunction valuePresenter, - boolean hasChildren) { - XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this); - } - @Override public void setPresentation(@Nullable Icon icon, @NotNull XValuePresentation presentation, boolean hasChildren) { XValueNodePresentationConfigurator.setPresentation(icon, presentation, hasChildren, this); } - @Override - public void setPresentation(@Nullable Icon icon, - @NonNls @Nullable String type, - @NonNls @NotNull String separator, - @NonNls @NotNull String value, - final @Nullable NotNullFunction valuePresenter, - boolean hasChildren) { - XValueNodePresentationConfigurator.setPresentation(icon, type, separator, valuePresenter, hasChildren, this); - } - @Override public void applyPresentation(@Nullable Icon icon, @NotNull XValuePresentation valuePresentation, boolean hasChildren) { // extra check for obsolete nodes - tree root was changed @@ -173,15 +153,12 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu }; if (getValueContainer().computeInlineDebuggerData(callback) == ThreeState.UNSURE) { - class ValueDeclaration implements XInlineSourcePosition { + getValueContainer().computeSourcePosition(new XNavigatable() { @Override public void setSourcePosition(@Nullable XSourcePosition sourcePosition) { callback.computed(sourcePosition); } - } - class NearestValuePosition extends ValueDeclaration implements XNearestSourcePosition {} - getValueContainer().computeSourcePosition(new ValueDeclaration()); - getValueContainer().computeSourcePosition(new NearestValuePosition()); + }); } } catch (Exception ignore) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java index 23a9c5b597f9..6a71db7e1e3b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodePresentationConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -48,29 +48,10 @@ public final class XValueNodePresentationConfigurator { XValueNodePresentationConfigurator.setPresentation(icon, type, separator, value, hasChildren, this); } - @Override - public void setPresentation(@Nullable Icon icon, - @NonNls @Nullable String type, - @NonNls @NotNull String value, - @Nullable NotNullFunction valuePresenter, - boolean hasChildren) { - XValueNodePresentationConfigurator.setPresentation(icon, type, value, valuePresenter, hasChildren, this); - } - @Override public void setPresentation(@Nullable Icon icon, @NotNull XValuePresentation presentation, boolean hasChildren) { XValueNodePresentationConfigurator.setPresentation(icon, presentation, hasChildren, this); } - - @Override - public void setPresentation(@Nullable Icon icon, - @NonNls @Nullable String type, - @NonNls @NotNull String separator, - @NonNls @NotNull String value, - final @Nullable NotNullFunction valuePresenter, - boolean hasChildren) { - XValueNodePresentationConfigurator.setPresentation(icon, type, separator, valuePresenter, hasChildren, this); - } } public static void setPresentation(@Nullable Icon icon, @NotNull XValuePresentation presentation, boolean hasChildren, From ec27f2c661b4d3d389d63f5cab71b7c920c7bb61 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Mon, 18 Jan 2016 15:29:48 +0300 Subject: [PATCH 186/825] maven: flex test repository excluded from base mirror --- .../src/test/java/org/jetbrains/idea/maven/MavenTestCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java index 23cff3c42524..68a44fcca6d9 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java @@ -334,7 +334,7 @@ public abstract class MavenTestCase extends UsefulTestCase { " " + " jb-central-proxy" + " " + mirror + "" + - " external:*" + + " external:*,!flex-repository" + " " + "" + ""; From e8fff3385aa2ee820e5b73e087ce8428d396fd5c Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 18 Jan 2016 15:43:24 +0300 Subject: [PATCH 187/825] compilation fix --- .../src/com/intellij/ide/projectWizard/ProjectTypeStep.java | 2 +- .../core-api/src/com/intellij/openapi/progress/Task.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java index d3abd0cf129d..462a8e49f44c 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java @@ -634,7 +634,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D } @Override - public void finished() { + public void onFinished() { myTemplatesList.setPaintBusy(false); chooseTemplateStep.getTemplateList().setPaintBusy(false); } diff --git a/platform/core-api/src/com/intellij/openapi/progress/Task.java b/platform/core-api/src/com/intellij/openapi/progress/Task.java index a8ce293589d1..ff6855c2e595 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/Task.java +++ b/platform/core-api/src/com/intellij/openapi/progress/Task.java @@ -63,17 +63,17 @@ public abstract class Task implements TaskInfo, Progressive { * This callback will be invoked on AWT dispatch thread. */ public void onCancel() { - finished(); + onFinished(); } /** * This callback will be invoked on AWT dispatch thread. */ public void onSuccess() { - finished(); + onFinished(); } - protected void finished() {} + protected void onFinished() {} public final Project getProject() { return myProject; From 445404fadacb8cb6c711fe50ed88c5f7f40fbcef Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Mon, 18 Jan 2016 15:55:29 +0300 Subject: [PATCH 188/825] IDEA-150547 [follow-up: add missing super call] --- .../src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java | 1 + .../com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java | 1 + 2 files changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index 7b8723838b52..518b2253211d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -1094,6 +1094,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra @Override public void setContentPane(Container contentPane) { + super.setContentPane(contentPane); if (contentPane != null) { contentPane.addMouseMotionListener(new MouseMotionAdapter() {}); // listen to mouse motino events for a11y } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index 19b169c2769e..c0148905109a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -737,6 +737,7 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc @Override public void setContentPane(Container contentPane) { + super.setContentPane(contentPane); if (contentPane != null) { contentPane.addMouseMotionListener(new MouseMotionAdapter() {}); // listen to mouse motion events for a11y } From 0edec4e9ae6f7eb2b880e163cb6a6157446189c0 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Mon, 18 Jan 2016 15:57:27 +0300 Subject: [PATCH 189/825] PY-18181 Folding: Folding doesn't work with 'with' statement --- python/src/com/jetbrains/python/PythonFoldingBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/PythonFoldingBuilder.java b/python/src/com/jetbrains/python/PythonFoldingBuilder.java index 1cf3c42d8d69..d78f3fded2d1 100644 --- a/python/src/com/jetbrains/python/PythonFoldingBuilder.java +++ b/python/src/com/jetbrains/python/PythonFoldingBuilder.java @@ -150,7 +150,7 @@ public class PythonFoldingBuilder extends CustomFoldingBuilder implements DumbAw } private static boolean ifFoldBlocks(ASTNode statementList, IElementType parentType) { - if (!PyElementTypes.PARTS.contains(parentType)) { + if (!PyElementTypes.PARTS.contains(parentType) && parentType != PyElementTypes.WITH_STATEMENT) { return false; } PsiElement element = statementList.getPsi(); From 19d53266f657f343e69ba44dce4c5926e9db6294 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 15 Jan 2016 15:00:54 +0300 Subject: [PATCH 190/825] JobScheduler service retired. makes no sense to maintain a service for empty interface --- .../src/com/intellij/concurrency/JobScheduler.java | 8 +------- .../src/com/intellij/concurrency/JobSchedulerImpl.java | 4 ++-- .../src/META-INF/PlatformExtensions.xml | 3 --- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/platform/core-api/src/com/intellij/concurrency/JobScheduler.java b/platform/core-api/src/com/intellij/concurrency/JobScheduler.java index 30d668088824..4596e68abd45 100644 --- a/platform/core-api/src/com/intellij/concurrency/JobScheduler.java +++ b/platform/core-api/src/com/intellij/concurrency/JobScheduler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -20,14 +20,12 @@ package com.intellij.concurrency; import com.intellij.Patches; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; - import java.lang.reflect.Method; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -89,10 +87,6 @@ public abstract class JobScheduler { } } - public static JobScheduler getInstance() { - return ServiceManager.getService(JobScheduler.class); - } - @NotNull public static ScheduledExecutorService getScheduler() { return ourScheduledExecutorService; diff --git a/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java b/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java index 4620657262bd..8e89ae815be9 100644 --- a/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java +++ b/platform/core-impl/src/com/intellij/concurrency/JobSchedulerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -19,6 +19,6 @@ */ package com.intellij.concurrency; -public class JobSchedulerImpl extends JobScheduler { +public class JobSchedulerImpl { public static final int CORES_COUNT = Runtime.getRuntime().availableProcessors(); } diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 6dcd3c4d7f21..b3756cce7999 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -25,9 +25,6 @@ - - Date: Fri, 15 Jan 2016 18:29:26 +0300 Subject: [PATCH 191/825] shutdownNow() should prevent from submitting tasks, shutdown() should allow submitted tasks to execute, just like the ExecutorService javadoc says --- .../psi/impl/DocumentCommitThread.java | 9 ++- .../concurrency/BoundedTaskExecutorTest.java | 79 +++++++++++++++++++ .../util/concurrency/BoundedTaskExecutor.java | 7 +- 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 5bb71ae24cf1..a08349f92344 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -50,7 +50,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; public class DocumentCommitThread extends DocumentCommitProcessor implements Runnable, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread"); @@ -137,8 +136,10 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run log("Enabled", null, false, reason); } - private Future wakeUpQueue() { - return executor.submit(this); + private void wakeUpQueue() { + if (!isDisposed) { + executor.execute(this); + } } private void cancel(@NonNls @NotNull Object reason) { diff --git a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java index 1f39d04bd016..ee6d1433c0d0 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java @@ -17,11 +17,15 @@ package com.intellij.util.concurrency; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.EmptyRunnable; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.TimeoutUtil; import com.intellij.util.ui.UIUtil; import junit.framework.TestCase; +import org.jetbrains.ide.PooledThreadExecutor; +import java.util.List; import java.util.Random; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -291,4 +295,79 @@ public class BoundedTaskExecutorTest extends TestCase { backendExecutor.shutdownNow(); assertTrue(backendExecutor.awaitTermination(1, TimeUnit.MINUTES)); } + + public void testShutdownNowMustCancel() throws ExecutionException, InterruptedException { + ExecutorService executor = new BoundedTaskExecutor(PooledThreadExecutor.INSTANCE, 1); + int N = 100000; + StringBuffer log = new StringBuffer(N*4); + + Future[] futures = new Future[N]; + for (int i = 0; i < N; i++) { + futures[i] = executor.submit(() -> log.append(" ")); + } + List runnables = executor.shutdownNow(); + assertTrue(executor.isShutdown()); + + Thread.sleep(1000); // wait for a rare chance of a task executing right now + assertEquals(N - log.length(), runnables.size()); + + try { + executor.submit(EmptyRunnable.getInstance()); + fail("Must reject"); + } + catch (RejectedExecutionException ignored) { + } + try { + executor.execute(EmptyRunnable.getInstance()); + fail("Must reject"); + } + catch (RejectedExecutionException ignored) { + } + + for (int i = 0; i < log.length(); i++) { + assertFalse(futures[i].isCancelled()); + assertTrue(futures[i].isDone()); + } + for (int i = log.length(); i < N; i++) { + assertTrue(futures[i].isCancelled()); + assertTrue(futures[i].isDone()); + } + + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + } + + public void testShutdownMustDisableSubmit() throws ExecutionException, InterruptedException { + ExecutorService executor = new BoundedTaskExecutor(PooledThreadExecutor.INSTANCE, 1); + int N = 100000; + StringBuffer log = new StringBuffer(N*4); + + Future[] futures = new Future[N]; + for (int i = 0; i < N; i++) { + futures[i] = executor.submit(() -> log.append(" ")); + } + executor.shutdown(); + assertTrue(executor.isShutdown()); + + try { + executor.submit(EmptyRunnable.getInstance()); + fail("Must reject"); + } + catch (RejectedExecutionException ignored) { + } + try { + executor.execute(EmptyRunnable.getInstance()); + fail("Must reject"); + } + catch (RejectedExecutionException ignored) { + } + + for (int i = 0; i < N; i++) { + assertFalse(futures[i].isCancelled()); + futures[i].get(); + } + + String logs = log.toString(); + assertEquals(StringUtil.repeat(" ",N), logs); + assertTrue(executor.awaitTermination(1, TimeUnit.SECONDS)); + } } diff --git a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java index 339a2f94e990..59c0a4c18556 100644 --- a/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java +++ b/platform/util/src/com/intellij/util/concurrency/BoundedTaskExecutor.java @@ -111,6 +111,9 @@ public class BoundedTaskExecutor extends AbstractExecutorService { @Override public void execute(@NotNull Runnable task) { + if (isShutdown()) { + throw new RejectedExecutionException("Already shutdown"); + } long status = myStatus.addAndGet(1 + (1L << 32)); // increment inProgress and queue stamp atomically if (tryToExecute(status, task)) { @@ -128,7 +131,7 @@ public class BoundedTaskExecutor extends AbstractExecutorService { assert inProgress > 0 : inProgress; Runnable next; - if (inProgress <= myMaxTasks && !isShutdown() && (next = myTaskQueue.poll()) != null) { + if (inProgress <= myMaxTasks && (next = myTaskQueue.poll()) != null) { tryToExecute(status, next); break; } @@ -144,7 +147,7 @@ public class BoundedTaskExecutor extends AbstractExecutorService { int inProgress = (int)status; assert inProgress > 0 : inProgress; - if (inProgress <= myMaxTasks && !isShutdown()) { + if (inProgress <= myMaxTasks) { try { myBackendExecutor.execute(wrap(task)); } From c8377562a44b896bfd8c63d668ee5aece00948e8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jan 2016 15:49:23 +0300 Subject: [PATCH 192/825] increase delay for the case of busy agent --- .../com/intellij/util/concurrency/BoundedTaskExecutorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java index ee6d1433c0d0..ff457283d240 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/concurrency/BoundedTaskExecutorTest.java @@ -90,7 +90,7 @@ public class BoundedTaskExecutorTest extends TestCase { ExecutorService backendExecutor = Executors.newCachedThreadPool(ConcurrencyUtil.newNamedThreadFactory(getName())); BoundedTaskExecutor executor = new BoundedTaskExecutor(backendExecutor, 1); - int delay = 500; + int delay = 1000; Future s1 = executor.submit((Runnable)() -> TimeoutUtil.sleep(delay)); Future f1 = executor.submit(() -> { run.set(true); From 60946dd3038b4c43f625be7d6c7c64c872f20e6d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jan 2016 15:51:03 +0300 Subject: [PATCH 193/825] cleanup: avoid "ambiguous charset" warning --- .../BytecodeAnalysisConverter.java | 15 +++++++------ .../generation/ui/GenerateEqualsWizard.java | 5 +++-- .../codeInsight/psi/ControlFlowTest.java | 18 ++++++++++++++- .../vfs/changes/PsiChangeTrackerTest.java | 22 ++++++++++++++++--- .../testSrc/com/intellij/psi/MiscPsiTest.java | 4 ++-- .../java/AbstractJavaFormatterTest.java | 4 ++-- .../intellij/psi/search/UpdateCacheTest.java | 9 ++++---- .../TemplateLanguageErrorFilter.java | 17 ++++---------- 8 files changed, 60 insertions(+), 34 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java index 7a59184693d5..bfb6b42a82e2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -18,6 +18,7 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.ThreadLocalCachedValue; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -28,8 +29,8 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; -import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG; import static com.intellij.codeInspection.bytecodeAnalysis.Direction.*; +import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG; /** * @author lambdamix @@ -121,9 +122,9 @@ public class BytecodeAnalysisConverter { */ @NotNull public static HKey asmKey(@NotNull Key key, @NotNull MessageDigest md) { - byte[] classDigest = md.digest(key.method.internalClassName.getBytes()); - md.update(key.method.methodName.getBytes()); - md.update(key.method.methodDesc.getBytes()); + byte[] classDigest = md.digest(key.method.internalClassName.getBytes(CharsetToolkit.UTF8_CHARSET)); + md.update(key.method.methodName.getBytes(CharsetToolkit.UTF8_CHARSET)); + md.update(key.method.methodDesc.getBytes(CharsetToolkit.UTF8_CHARSET)); byte[] sigDigest = md.digest(); byte[] digest = new byte[HASH_SIZE]; System.arraycopy(classDigest, 0, digest, 0, CLASS_HASH_SIZE); @@ -161,7 +162,7 @@ public class BytecodeAnalysisConverter { if (descriptor == null) { return null; } - return md.digest(descriptor.getBytes()); + return md.digest(descriptor.getBytes(CharsetToolkit.UTF8_CHARSET)); } @Nullable @@ -170,7 +171,7 @@ public class BytecodeAnalysisConverter { if (descriptor == null) { return null; } - return md.digest(descriptor.getBytes()); + return md.digest(descriptor.getBytes(CharsetToolkit.UTF8_CHARSET)); } @Nullable diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java index 7ee8fc9b3b74..0098905f8488 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -40,6 +40,7 @@ import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.ui.JBColor; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.NonFocusableCheckBox; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.java.generate.psi.PsiAdapter; @@ -429,7 +430,7 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard map = new HashMap(); for (String s : res.replace("\r\n", "\n").split("\n")) { if (!StringUtil.isEmptyOrSpaces(s)) { diff --git a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java index aa8a3c692896..a687beb135e3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -57,7 +57,7 @@ public class MiscPsiTest extends LightCodeInsightFixtureTestCase { PsiFile newFile = (PsiFile)dir.add(fileCopy); assertInstanceOf(newFile, PsiPlainTextFile.class); - assertEquals(text, new String(newFile.getVirtualFile().contentsToByteArray())); + assertEquals(text, LoadTextUtil.loadText(newFile.getVirtualFile())); assertEquals(newFile.getVirtualFile().getModificationStamp(), newFile.getViewProvider().getModificationStamp()); Document document = PsiDocumentManager.getInstance(getProject()).getDocument(newFile); assertEquals(newFile.getVirtualFile().getModificationStamp(), document.getModificationStamp()); diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java index 433cc27a6a66..d5a126627202 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -74,7 +74,7 @@ public abstract class AbstractJavaFormatterTest extends LightIdeaTestCase { if (line.length > 0 || shiftEmptyLines) { StringUtil.repeatSymbol(result, ' ', i); } - result.append(new String(line)); + result.append(new String(line, CharsetToolkit.UTF8_CHARSET)); } finally { first = false; diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java index 48c397e7075c..48b05f31cdb3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -108,7 +109,7 @@ public class UpdateCacheTest extends PsiTestCase { VirtualFile root = ProjectRootManager.getInstance(myProject).getContentRoots()[0]; String newFilePath = root.getPresentableUrl() + File.separatorChar + "New.java"; - FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes()); + FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes(CharsetToolkit.UTF8_CHARSET)); VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(newFilePath.replace(File.separatorChar, '/')); assertNotNull(file); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); @@ -165,7 +166,7 @@ public class UpdateCacheTest extends PsiTestCase { final File file = new File(root.getPath(), "1.java"); assertTrue(file.exists()); - FileUtil.writeToFile(file, "class A{ Object o;}".getBytes()); + FileUtil.writeToFile(file, "class A{ Object o;}".getBytes(CharsetToolkit.UTF8_CHARSET)); root.refresh(false, true); LocalFileSystem.getInstance().refresh(false); @@ -195,7 +196,7 @@ public class UpdateCacheTest extends PsiTestCase { String newFilePath = root.getPresentableUrl() + File.separatorChar + "dir" + File.separatorChar + "New.java"; LOG.assertTrue(new File(newFilePath).getParentFile().mkdir()); - FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes()); + FileUtil.writeToFile(new File(newFilePath), "class A{ Object o;}".getBytes(CharsetToolkit.UTF8_CHARSET)); VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(newFilePath.replace(File.separatorChar, '/')); assertNotNull(file); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java index 04c9bcf53569..d564a3a0f8f0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -37,18 +37,9 @@ public abstract class TemplateLanguageErrorFilter extends HighlightErrorFilter { private static final Key TEMPLATE_VIEW_PROVIDER_CLASS_KEY = Key.create("TEMPLATE_VIEW_PROVIDER_CLASS"); - protected TemplateLanguageErrorFilter( - @NotNull final TokenSet templateExpressionStartTokens, - @NotNull final Class templateFileViewProviderClass) - { - this(templateExpressionStartTokens, templateFileViewProviderClass, new String[0]); - } - - protected TemplateLanguageErrorFilter( - @NotNull final TokenSet templateExpressionStartTokens, - @NotNull final Class templateFileViewProviderClass, - @NotNull final String... knownSubLanguageNames) - { + protected TemplateLanguageErrorFilter(@NotNull final TokenSet templateExpressionStartTokens, + @NotNull final Class templateFileViewProviderClass, + @NotNull final String... knownSubLanguageNames) { myTemplateExpressionStartTokens = TokenSet.create(templateExpressionStartTokens.getTypes()); myTemplateFileViewProviderClass = templateFileViewProviderClass; From 8dfb1399e206d323ea0e85926c6a2e01929e949b Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 18 Jan 2016 16:17:39 +0300 Subject: [PATCH 194/825] Java-specific HighlightInfoType constants returned back as deprecated to keep the API --- .../daemon/impl/HighlightInfoType.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java index 826c8c512be4..d01778daa26b 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java @@ -66,6 +66,127 @@ public interface HighlightInfoType { CodeInsightColors.DEPRECATED_ATTRIBUTES); HighlightSeverity SYMBOL_TYPE_SEVERITY = new HighlightSeverity("SYMBOL_TYPE_SEVERITY", HighlightSeverity.INFORMATION.myVal-2); + + /** + * @deprecated For Java use JavaHighlightInfoTypes.LOCAL_VARIABLE or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.LOCAL_VARIABLE_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.INSTANCE_FIELD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType INSTANCE_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INSTANCE_FIELD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.INSTANCE_FINAL_FIELD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType INSTANCE_FINAL_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INSTANCE_FINAL_FIELD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.STATIC_FIELD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType STATIC_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_FIELD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.STATIC_FINAL_FIELD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType STATIC_FINAL_FIELD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_FINAL_FIELD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.PARAMETER or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.PARAMETER_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.METHOD_CALL or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType METHOD_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_CALL_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.METHOD_DECLARATION or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType METHOD_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.METHOD_DECLARATION_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.CONSTRUCTOR_CALL or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType CONSTRUCTOR_CALL = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.CONSTRUCTOR_DECLARATION or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType CONSTRUCTOR_DECLARATION = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CONSTRUCTOR_DECLARATION_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.STATIC_METHOD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType STATIC_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.STATIC_METHOD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ABSTRACT_METHOD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ABSTRACT_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ABSTRACT_METHOD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.INHERITED_METHOD or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType INHERITED_METHOD = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INHERITED_METHOD_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.CLASS_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.CLASS_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ANONYMOUS_CLASS_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ANONYMOUS_CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANONYMOUS_CLASS_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.INTERFACE_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType INTERFACE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.INTERFACE_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ENUM_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ENUM_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ENUM_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.TYPE_PARAMETER_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType TYPE_PARAMETER_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ABSTRACT_CLASS_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ABSTRACT_CLASS_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ABSTRACT_CLASS_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ANNOTATION_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ANNOTATION_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.ANNOTATION_ATTRIBUTE_NAME or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType ANNOTATION_ATTRIBUTE_NAME = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.REASSIGNED_LOCAL_VARIABLE or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType REASSIGNED_LOCAL_VARIABLE = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.REASSIGNED_PARAMETER or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType REASSIGNED_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.REASSIGNED_PARAMETER_ATTRIBUTES); + /** + * @deprecated For Java use JavaHighlightInfoTypes.IMPLICIT_ANONYMOUS_CLASS_PARAMETER or create a language-specific HighlightInfoType. + * The field will be removed in version 17. + */ + HighlightInfoType IMPLICIT_ANONYMOUS_CLASS_PARAMETER = new HighlightInfoTypeImpl(SYMBOL_TYPE_SEVERITY, CodeInsightColors.IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES); HighlightInfoType TODO = new HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, CodeInsightColors.TODO_DEFAULT_ATTRIBUTES, false); // these are default attributes, can be configured differently for specific patterns HighlightInfoType UNHANDLED_EXCEPTION = new HighlightInfoTypeImpl(HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES); From 8c4b00a811e48cd39a8caf7a72156c33f7b47e35 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jan 2016 17:03:09 +0300 Subject: [PATCH 195/825] @NotNull --- .../intellij/codeInsight/lookup/impl/LookupUi.java | 11 ++++------- .../src/com/intellij/openapi/ui/DialogWrapper.java | 3 ++- .../src/com/intellij/ide/SwingCleanuper.java | 4 ++-- .../com/intellij/testFramework/UsefulTestCase.java | 5 +++-- .../evaluate/quick/common/ValueLookupManager.java | 4 ++-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupUi.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupUi.java index cd1bcc9f2a5c..d9413ae318dd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupUi.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupUi.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -46,11 +46,7 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Alarm; import com.intellij.util.PlatformIcons; -import com.intellij.util.ui.AbstractLayoutManager; -import com.intellij.util.ui.AsyncProcessIcon; -import com.intellij.util.ui.ButtonlessScrollBarUI; -import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,6 +65,7 @@ import java.util.Collection; */ class LookupUi { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.lookup.impl.LookupUi"); + @NotNull private final LookupImpl myLookup; private final Advertiser myAdvertiser; private final JBList myList; @@ -86,7 +83,7 @@ class LookupUi { private int myMaximumHeight = Integer.MAX_VALUE; private Boolean myPositionedAbove = null; - LookupUi(LookupImpl lookup, Advertiser advertiser, JBList list, Project project) { + LookupUi(@NotNull LookupImpl lookup, Advertiser advertiser, JBList list, Project project) { myLookup = lookup; myAdvertiser = advertiser; myList = list; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index f5e5c8d1f87d..9a66d45345a9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -167,6 +167,7 @@ public abstract class DialogWrapper { protected JComponent myPreferredFocusedComponent; private Computable myInitialLocationCallback; + @NotNull protected final Disposable myDisposable = new Disposable() { @Override public String toString() { diff --git a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java index bd5761bfabc7..f3476cac3ef0 100644 --- a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java +++ b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -57,7 +57,7 @@ import java.util.EventListener; public final class SwingCleanuper implements ApplicationComponent{ private final Alarm myAlarm; - public SwingCleanuper(Application application, ProjectManager projectManager) { + public SwingCleanuper(@NotNull Application application, ProjectManager projectManager) { myAlarm = new Alarm(application); projectManager.addProjectManagerListener(new ProjectManagerAdapter(){ public void projectOpened(final Project project) { diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 6dcf1fd6c7a6..1f8b3703b835 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -24,7 +24,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.command.impl.StartMarkAction; -import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; @@ -94,6 +93,7 @@ public abstract class UsefulTestCase extends TestCase { public static Map TOTAL_SETUP_COST_MILLIS = new HashMap(); public static Map TOTAL_TEARDOWN_COST_MILLIS = new HashMap(); + @NotNull protected final Disposable myTestRootDisposable = new Disposable() { @Override public void dispose() { } @@ -311,6 +311,7 @@ public abstract class UsefulTestCase extends TestCase { return CodeStyleSettingsManager.getInstance().getCurrentSettings(); } + @NotNull public final Disposable getTestRootDisposable() { return myTestRootDisposable; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java index 7f49d407ead1..b8b22a35be39 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -49,7 +49,7 @@ public class ValueLookupManager extends EditorMouseAdapter implements EditorMous private final DebuggerSupport[] mySupports; private boolean myListening; - public ValueLookupManager(Project project) { + public ValueLookupManager(@NotNull Project project) { myProject = project; mySupports = DebuggerSupport.getDebuggerSupports(); myAlarm = new Alarm(project); From ddbfc410a3c796188335c2356826af61acecb9f6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jan 2016 17:19:29 +0300 Subject: [PATCH 196/825] restored ctr because extensions are unaware of varargs --- .../highlighting/TemplateLanguageErrorFilter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java index d564a3a0f8f0..90545941cbc4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/TemplateLanguageErrorFilter.java @@ -37,6 +37,14 @@ public abstract class TemplateLanguageErrorFilter extends HighlightErrorFilter { private static final Key TEMPLATE_VIEW_PROVIDER_CLASS_KEY = Key.create("TEMPLATE_VIEW_PROVIDER_CLASS"); + // this redundant ctr is here because ExtensionComponentAdapter.getComponentInstance() is not aware of varargs + protected TemplateLanguageErrorFilter( + @NotNull final TokenSet templateExpressionStartTokens, + @NotNull final Class templateFileViewProviderClass) + { + this(templateExpressionStartTokens, templateFileViewProviderClass, new String[0]); + } + protected TemplateLanguageErrorFilter(@NotNull final TokenSet templateExpressionStartTokens, @NotNull final Class templateFileViewProviderClass, @NotNull final String... knownSubLanguageNames) { From 9847f4d309add68e0acd6cb2bd31a11fdb9566de Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Mon, 18 Jan 2016 17:21:54 +0300 Subject: [PATCH 197/825] IDEA-150084 Typo in Gradle plugin description --- plugins/gradle/src/META-INF/plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index 0497b2b12a02..c58b642ad8bb 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -21,7 +21,7 @@ Gradle is a build and automation system. Gradle can automate the building, testing, publishing, deployment and etc. - of software packages or other types of projects. The Gradle versions 1.8 to 1.11 are supported. + of software packages or other types of projects. Gradle versions 1.8 to 2.+ are supported. This plugin provides Gradle integration. The following features are available: