From deddecae3c223e9ad0ff545560df17a0a0a11bc0 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 14 Nov 2014 01:46:48 +0300 Subject: [PATCH 01/75] svn: Refactored SvnFileSystemListenerWrapper - code simplified --- .../idea/svn/SvnFileSystemListener.java | 2 +- .../svn/SvnFileSystemListenerWrapper.java | 46 ++++++------------- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java index 06e3f3bcc8d0..7216268b1225 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java @@ -61,7 +61,7 @@ import java.io.File; import java.io.IOException; import java.util.*; -public class SvnFileSystemListener extends CommandAdapter implements LocalFileOperationsHandler { +public class SvnFileSystemListener implements LocalFileOperationsHandler { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFileSystemListener"); private final LocalFileSystem myLfs; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java index 8f23eeb8d0a8..a2889fc1e70e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java @@ -16,8 +16,8 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.Disposable; +import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; -import com.intellij.openapi.command.CommandListener; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectLocator; @@ -27,6 +27,7 @@ import com.intellij.openapi.vfs.LocalFileOperationsHandler; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ThrowableConsumer; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -34,19 +35,17 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; -import java.util.HashMap; import java.util.Map; public class SvnFileSystemListenerWrapper { private final LocalFileOperationsHandler myProxy; - private final CommandListener myListener; + private final MyCommandListener myListener; public SvnFileSystemListenerWrapper(final SvnFileSystemListener delegate) { - final MyCommandListener listener = new MyCommandListener(delegate); - myListener = listener; - final MyStorage storage = new MyStorage(listener); - myProxy = (LocalFileOperationsHandler) Proxy.newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(), - new Class[]{LocalFileOperationsHandler.class}, new MyInvoker(storage, delegate)); + myListener = new MyCommandListener(delegate); + myProxy = (LocalFileOperationsHandler)Proxy + .newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(), new Class[]{LocalFileOperationsHandler.class}, + new MyInvoker(new MyStorage(myListener), delegate)); } public void registerSelf() { @@ -59,7 +58,7 @@ public class SvnFileSystemListenerWrapper { CommandProcessor.getInstance().removeCommandListener(myListener); } - private static class MyCommandListener implements CommandListener, MyMarker { + private static class MyCommandListener extends CommandAdapter { private volatile boolean myInCommand; private final SvnFileSystemListener myDelegate; @@ -84,36 +83,19 @@ public class SvnFileSystemListenerWrapper { myDelegate.commandStarted(event); } - public void beforeCommandFinished(CommandEvent event) { - myDelegate.beforeCommandFinished(event); - } - public void commandFinished(CommandEvent event) { myInCommand = false; myDelegate.commandFinished(event); } - - public void undoTransparentActionStarted() { - myDelegate.undoTransparentActionStarted(); - } - - public void undoTransparentActionFinished() { - myDelegate.undoTransparentActionFinished(); - } - } - - private interface MyMarker { - void start(final Project project); - void finish(final Project project); } private static class MyStorage implements InvocationHandler { - private final MyMarker myMarker; + private final MyCommandListener myListener; private final Map> myStarted; - private MyStorage(final MyMarker marker) { - myMarker = marker; - myStarted = new HashMap>(); + private MyStorage(final MyCommandListener listener) { + myListener = listener; + myStarted = ContainerUtil.newHashMap(); } @Nullable @@ -131,7 +113,7 @@ public class SvnFileSystemListenerWrapper { if (project != null) { final Pair pair = myStarted.get(project); if (pair != null && method.getName().equals(pair.getFirst()) && Arrays.equals(args, pair.getSecond())) { - myMarker.finish(project); + myListener.finish(project); } } //dont return null for auto unboxing to not face NPE @@ -143,7 +125,7 @@ public class SvnFileSystemListenerWrapper { System.arraycopy(args, 0, newArr, 0, args.length); final Project project = getProject(args); if (project != null) { - myMarker.start(project); + myListener.start(project); myStarted.put(project, Pair.create(method.getName(), newArr)); Disposer.register(project, new Disposable() { public void dispose() { From 82b4848be16a176887aae373f6ddd33a631f39ab Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 14 Nov 2014 02:04:24 +0300 Subject: [PATCH 02/75] svn: Refactored SvnFileSystemListener - removed unused code, code simplified, warnings fixed --- .../idea/svn/SvnFileSystemListener.java | 131 +++++++----------- 1 file changed, 50 insertions(+), 81 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java index 7216268b1225..4f452515e430 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java @@ -19,7 +19,6 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.diagnostic.Logger; @@ -32,7 +31,6 @@ import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vfs.LocalFileOperationsHandler; @@ -44,6 +42,7 @@ import com.intellij.util.ThrowableConsumer; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import com.intellij.vcsUtil.ActionWithTempFile; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.Depth; @@ -113,12 +112,10 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { exceptionList.add(handleMoveException(e)); } - private VcsException handleMoveException(@NotNull Exception e) { + private static VcsException handleMoveException(@NotNull Exception e) { VcsException vcsException; - if (e instanceof SVNException && SVNErrorCode.ENTRY_EXISTS.equals(((SVNException)e).getErrorMessage().getErrorCode())) { - vcsException = createMoveTargetExistsError(e); - } - else if (e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.ENTRY_EXISTS)) { + if (e instanceof SVNException && SVNErrorCode.ENTRY_EXISTS.equals(((SVNException)e).getErrorMessage().getErrorCode()) || + e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.ENTRY_EXISTS)) { vcsException = createMoveTargetExistsError(e); } else if (e instanceof VcsException) { @@ -225,8 +222,6 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { final SvnVcs vcs = getVCS(toDir); final SvnVcs sourceVcs = getVCS(file); - if (vcs == null && sourceVcs == null) return false; - if (vcs == null) { return false; } @@ -237,13 +232,11 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } if (isPendingAdd(vcs.getProject(), toDir)) { - myMovedFiles.add(new MovedFileInfo(sourceVcs.getProject(), srcFile, dstFile)); return true; } else { - final VirtualFile oldParent = file.getParent(); - myFilesToRefresh.add(oldParent); + myFilesToRefresh.add(file.getParent()); myFilesToRefresh.add(toDir); return doMove(sourceVcs, srcFile, dstFile); } @@ -272,19 +265,10 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { final boolean is17OrLater = format.isOrGreater(WorkingCopyFormat.ONE_DOT_SEVEN); if (is17OrLater) { Status srcStatus = getFileStatus(vcs, src); - final File toDir = dst.getParentFile(); - Status dstStatus = getFileStatus(vcs, toDir); - final boolean srcUnversioned = srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED); - if (srcUnversioned && (dstStatus == null || dstStatus.is(StatusType.STATUS_UNVERSIONED))) { + if (isUnversioned(srcStatus) && (isUnversioned(vcs, dst.getParentFile()) || isUnversioned(vcs, dst)) || + for17move(vcs, src, dst, isUndo, srcStatus)) { return false; } - if (srcUnversioned) { - Status dstWasStatus = getFileStatus(vcs, dst); - if (dstWasStatus == null || dstWasStatus.is(StatusType.STATUS_UNVERSIONED)) { - return false; - } - } - if (for17move(vcs, src, dst, isUndo, srcStatus)) return false; } else { if (for16move(vcs, src, dst, isUndo)) return false; } @@ -301,9 +285,12 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { return true; } - private final static Set ourStatusesForUndoMove = new HashSet(); - static { - ourStatusesForUndoMove.add(StatusType.STATUS_ADDED); + private static boolean isUnversioned(@Nullable Status status) { + return status == null || status.is(StatusType.STATUS_UNVERSIONED); + } + + private static boolean isUnversioned(@NotNull SvnVcs vcs, @NotNull File file) { + return isUnversioned(getFileStatus(vcs, file)); } private boolean for17move(final SvnVcs vcs, final File src, final File dst, boolean undo, Status srcStatus) throws VcsException { @@ -314,7 +301,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { myUndoingMove = true; createRevertAction(vcs, dst, true).execute(); copyUnversionedMembersOfDirectory(src, dst); - if (srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED)) { + if (isUnversioned(srcStatus)) { FileUtil.delete(src); } else { createRevertAction(vcs, src, true).execute(); @@ -323,8 +310,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } else { if (doUsualMove(vcs, src)) return true; // check destination directory - final Status dstParentStatus = getFileStatus(vcs, dst.getParentFile()); - if (dstParentStatus == null || dstParentStatus.is(StatusType.STATUS_UNVERSIONED)) { + if (isUnversioned(vcs, dst.getParentFile())) { try { copyFileOrDir(src, dst); } @@ -348,7 +334,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { }.execute(); } - private void copyUnversionedMembersOfDirectory(final File src, final File dst) throws SvnBindException { + private static void copyUnversionedMembersOfDirectory(final File src, final File dst) throws SvnBindException { if (src.isDirectory()) { final SvnBindException[] exc = new SvnBindException[1]; FileUtil.processFilesRecursively(src, new Processor() { @@ -374,7 +360,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private void copyFileOrDir(File src, File dst) throws IOException { + private static void copyFileOrDir(File src, File dst) throws IOException { if (src.isDirectory()) { FileUtil.copyDir(src, dst); } else { @@ -382,45 +368,38 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private boolean doUsualMove(SvnVcs vcs, File src) { + private static boolean doUsualMove(SvnVcs vcs, File src) { // if src is not under version control, do usual move. Status srcStatus = getFileStatus(vcs, src); return srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED, StatusType.STATUS_OBSTRUCTED, StatusType.STATUS_MISSING, StatusType.STATUS_EXTERNAL); } - private boolean for16move(SvnVcs vcs, final File src, final File dst, boolean undo) throws VcsException { + private boolean for16move(SvnVcs vcs, final File src, final File dst, final boolean undo) throws VcsException { final SVNMoveClient mover = vcs.getSvnKitManager().createMoveClient(); if (undo) { myUndoingMove = true; restoreFromUndoStorage(dst); - new RepeatSvnActionThroughBusy() { - @Override - protected void executeImpl() throws VcsException { - try { + } + else if (doUsualMove(vcs, src)) return true; + + new RepeatSvnActionThroughBusy() { + @Override + protected void executeImpl() throws VcsException { + try { + if (undo) { mover.undoMove(src, dst); } - catch (SVNException e) { - throw new SvnBindException(e); - } - } - }.execute(); - } - else { - // if src is not under version control, do usual move. - if (doUsualMove(vcs, src)) return true; - new RepeatSvnActionThroughBusy() { - @Override - protected void executeImpl() throws VcsException { - try { + else { mover.doMove(src, dst); } - catch (SVNException e) { - throw new SvnBindException(e); - } } - }.execute(); - } + catch (SVNException e) { + throw new SvnBindException(e); + } + } + }.execute(); + return false; } @@ -482,10 +461,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false; final File ioFile = getIOFile(file); - if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) { - return false; - } - if (SvnUtil.isWorkingCopyRoot(ioFile)) { + if (!SvnUtil.isSvnVersioned(vcs, ioFile.getParentFile()) || SvnUtil.isWorkingCopyRoot(ioFile)) { return false; } @@ -503,7 +479,6 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { return true; } else { - if (vcs != null) { if (isAboveSourceOfCopyOrMove(vcs.getProject(), ioFile)) { myDeletedFiles.putValue(vcs.getProject(), ioFile); return true; @@ -521,13 +496,14 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { // packages deleted from disk should not be deleted from svn (IDEADEV-16066) if (file.isDirectory() || isUndo(vcs)) return true; } - } return false; } } @NotNull - private RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean recursive) { + private static RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, + @NotNull final File file, + final boolean recursive) { return new RepeatSvnActionThroughBusy() { @Override protected void executeImpl() throws VcsException { @@ -537,7 +513,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } @NotNull - private RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) { + private static RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) { return new RepeatSvnActionThroughBusy() { @Override protected void executeImpl() throws VcsException { @@ -597,7 +573,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } File ioDir = getIOFile(dir); boolean pendingAdd = isPendingAdd(vcs.getProject(), dir); - if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) { + if (!SvnUtil.isSvnVersioned(vcs, ioDir) && !pendingAdd) { return false; } final File targetFile = new File(ioDir, name); @@ -772,7 +748,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private void runInBackground(final Project project, final String name, final Runnable runnable) { + private static void runInBackground(final Project project, final String name, final Runnable runnable) { if (ApplicationManager.getApplication().isDispatchThread()) { ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, name, false, project); } else { @@ -780,7 +756,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private Runnable createAdditionRunnable(final Project project, + private static Runnable createAdditionRunnable(final Project project, final SvnVcs vcs, final Map copyFromMap, final Collection filesToProcess, @@ -828,7 +804,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { }; } - private Collection promptAboutAddition(SvnVcs vcs, + private static Collection promptAboutAddition(SvnVcs vcs, List addedVFiles, VcsShowConfirmationOption.Value value, AbstractVcsHelper vcsHelper) { @@ -900,7 +876,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { filesToProcess.addAll(confirmed); } } - if (filesToProcess != null && ! filesToProcess.isEmpty()) { + if (!filesToProcess.isEmpty()) { runInBackground(project, "Deleting files from Subversion", createDeleteRunnable(project, vcs, filesToProcess, exceptions)); } final List deletedFilesFiles = ObjectsConvertor.convert(deletedFiles, new Convertor, FilePath>() { @@ -915,9 +891,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { myFilesToRefresh.add(parent.getVirtualFile()); } } - if (filesToProcess != null) { - deletedFilesFiles.removeAll(filesToProcess); - } + deletedFilesFiles.removeAll(filesToProcess); for (FilePath file : deletedFilesFiles) { FileUtil.delete(file.getIOFile()); } @@ -930,7 +904,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private Runnable createDeleteRunnable(final Project project, + private static Runnable createDeleteRunnable(final Project project, final SvnVcs vcs, final Collection filesToProcess, final List exceptions) { @@ -957,7 +931,7 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { }; } - private Collection promptAboutDeletion(List> deletedFiles, + private static Collection promptAboutDeletion(List> deletedFiles, SvnVcs vcs, VcsShowConfirmationOption.Value value, AbstractVcsHelper vcsHelper) { @@ -1001,9 +975,9 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { myT = vcs.getFactory(file).createStatusClient().doStatus(file, false); } }.compute(); - boolean isAdded = StatusType.STATUS_ADDED.equals(status.getNodeStatus()); - final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file); - if (isAdded) { + + final FilePath filePath = VcsUtil.getFilePath(file); + if (StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { deleteAnyway.add(filePath); } else { deletedFiles.add(Pair.create(filePath, vcs.getWorkingCopyFormat(file))); @@ -1060,11 +1034,6 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } } - private static boolean isUndoOrRedo(@NotNull final Project project) { - final UndoManager undoManager = UndoManager.getInstance(project); - return undoManager.isUndoInProgress() || undoManager.isRedoInProgress(); - } - private static boolean isUndo(SvnVcs vcs) { if (vcs == null || vcs.getProject() == null) { return false; From add8e92d749775ec8f2509fab76ed8f0e8021317 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 14 Nov 2014 13:14:03 +0300 Subject: [PATCH 03/75] svn: Removed SvnFileSystemListenerWrapper - corresponding logic moved to SvnFileSystemListener --- .../idea/svn/SvnApplicationSettings.java | 8 +- .../idea/svn/SvnFileSystemListener.java | 56 +++++- .../svn/SvnFileSystemListenerWrapper.java | 169 ------------------ 3 files changed, 55 insertions(+), 178 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java index 72a1539efcf4..fb3bf081d8d5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -35,7 +36,7 @@ import java.util.List; )} ) public class SvnApplicationSettings implements PersistentStateComponent { - private SvnFileSystemListenerWrapper myVFSHandler; + private SvnFileSystemListener myVFSHandler; private int mySvnProjectCount; private LimitedStringsList myLimitedStringsList; @@ -90,8 +91,7 @@ public class SvnApplicationSettings implements PersistentStateComponent> myUndoStorageContents = new ArrayList>(); private boolean myUndoingMove = false; + private boolean myIsInCommand; + @Nullable private Project myGuessedProject; + public SvnFileSystemListener() { myLfs = LocalFileSystem.getInstance(); + + myLfs.registerAuxiliaryFileOperationsHandler(this); + CommandProcessor.getInstance().addCommandListener(this); + } + + @Override + public void dispose() { + myLfs.unregisterAuxiliaryFileOperationsHandler(this); + CommandProcessor.getInstance().removeCommandListener(this); } private void addToMoveExceptions(@NotNull final Project project, @NotNull final Exception e) { @@ -134,6 +150,8 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { @Nullable public File copy(final VirtualFile file, final VirtualFile toDir, final String copyName) throws IOException { + startOperation(file); + SvnVcs vcs = getVCS(toDir); if (vcs == null) { vcs = getVCS(file); @@ -217,6 +235,8 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } public boolean move(VirtualFile file, VirtualFile toDir) throws IOException { + startOperation(file); + File srcFile = getIOFile(file); File dstFile = new File(getIOFile(toDir), file.getName()); @@ -243,6 +263,8 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { } public boolean rename(VirtualFile file, String newName) throws IOException { + startOperation(file); + File srcFile = getIOFile(file); File dstFile = new File(srcFile.getParentFile(), newName); SvnVcs vcs = getVCS(file); @@ -430,10 +452,14 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { public boolean createFile(VirtualFile dir, String name) throws IOException { + startOperation(dir); + return createItem(dir, name, false, false); } public boolean createDirectory(VirtualFile dir, String name) throws IOException { + startOperation(dir); + return createItem(dir, name, true, false); } @@ -452,6 +478,8 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { * deleted: do nothing, return true (strange) */ public boolean delete(VirtualFile file) throws IOException { + startOperation(file); + final SvnVcs vcs = getVCS(file); if (vcs != null && SvnUtil.isAdminDirectory(file)) { return true; @@ -619,25 +647,29 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { return false; } - public void commandStarted(CommandEvent event) { + @Override + public void commandStarted(@NotNull CommandEvent event) { + myIsInCommand = true; myUndoingMove = false; final Project project = event.getProject(); if (project == null) return; commandStarted(project); } - void commandStarted(final Project project) { + void commandStarted(@NotNull Project project) { myUndoingMove = false; myMoveExceptions.remove(project); } - public void commandFinished(CommandEvent event) { + @Override + public void commandFinished(@NotNull CommandEvent event) { + myIsInCommand = false; final Project project = event.getProject(); if (project == null) return; commandFinished(project); } - void commandFinished(final Project project) { + void commandFinished(@NotNull Project project) { checkOverwrites(project); if (myAddedFiles.containsKey(project)) { processAddedFiles(project); @@ -1042,6 +1074,20 @@ public class SvnFileSystemListener implements LocalFileOperationsHandler { return UndoManager.getInstance(p).isUndoInProgress(); } + public void startOperation(@NotNull VirtualFile file) { + if (!myIsInCommand) { + // currently actions like "new project", "import project" (probably also others) are not performed under command + myGuessedProject = ProjectLocator.getInstance().guessProjectForFile(file); + if (myGuessedProject != null) { + commandStarted(myGuessedProject); + } + } + } + public void afterDone(final ThrowableConsumer invoker) { + if (!myIsInCommand && myGuessedProject != null) { + commandFinished(myGuessedProject); + myGuessedProject = null; + } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java deleted file mode 100644 index a2889fc1e70e..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListenerWrapper.java +++ /dev/null @@ -1,169 +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 org.jetbrains.idea.svn; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.command.CommandAdapter; -import com.intellij.openapi.command.CommandEvent; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectLocator; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vfs.LocalFileOperationsHandler; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ThrowableConsumer; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Map; - -public class SvnFileSystemListenerWrapper { - private final LocalFileOperationsHandler myProxy; - private final MyCommandListener myListener; - - public SvnFileSystemListenerWrapper(final SvnFileSystemListener delegate) { - myListener = new MyCommandListener(delegate); - myProxy = (LocalFileOperationsHandler)Proxy - .newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(), new Class[]{LocalFileOperationsHandler.class}, - new MyInvoker(new MyStorage(myListener), delegate)); - } - - public void registerSelf() { - LocalFileSystem.getInstance().registerAuxiliaryFileOperationsHandler(myProxy); - CommandProcessor.getInstance().addCommandListener(myListener); - } - - public void unregisterSelf() { - LocalFileSystem.getInstance().unregisterAuxiliaryFileOperationsHandler(myProxy); - CommandProcessor.getInstance().removeCommandListener(myListener); - } - - private static class MyCommandListener extends CommandAdapter { - private volatile boolean myInCommand; - private final SvnFileSystemListener myDelegate; - - public MyCommandListener(final SvnFileSystemListener delegate) { - myDelegate = delegate; - } - - public void start(final Project project) { - if (!myInCommand && project != null) { - myDelegate.commandStarted(project); - } - } - - public void finish(final Project project) { - if (! myInCommand && project != null) { - myDelegate.commandFinished(project); - } - } - - public void commandStarted(CommandEvent event) { - myInCommand = true; - myDelegate.commandStarted(event); - } - - public void commandFinished(CommandEvent event) { - myInCommand = false; - myDelegate.commandFinished(event); - } - } - - private static class MyStorage implements InvocationHandler { - private final MyCommandListener myListener; - private final Map> myStarted; - - private MyStorage(final MyCommandListener listener) { - myListener = listener; - myStarted = ContainerUtil.newHashMap(); - } - - @Nullable - private static Project getProject(Object[] args) { - for (Object arg : args) { - if (arg instanceof VirtualFile) { - return ProjectLocator.getInstance().guessProjectForFile((VirtualFile) arg); - } - } - return null; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - final Project project = getProject(args); - if (project != null) { - final Pair pair = myStarted.get(project); - if (pair != null && method.getName().equals(pair.getFirst()) && Arrays.equals(args, pair.getSecond())) { - myListener.finish(project); - } - } - //dont return null for auto unboxing to not face NPE - return "boolean".equals(method.getReturnType().getName()) ? Boolean.TRUE : null; - } - - private void register(final Method method, final Object[] args) { - final Object[] newArr = new Object[args.length]; - System.arraycopy(args, 0, newArr, 0, args.length); - final Project project = getProject(args); - if (project != null) { - myListener.start(project); - myStarted.put(project, Pair.create(method.getName(), newArr)); - Disposer.register(project, new Disposable() { - public void dispose() { - myStarted.remove(project); - } - }); - } - } - } - - private static class MyInvoker implements InvocationHandler { - private final Object myDelegate; - private final MyStorage myParent; - private final LocalFileOperationsHandler myParentProxy; - - private MyInvoker(final MyStorage parent, Object delegate) { - myParent = parent; - myDelegate = delegate; - myParentProxy = (LocalFileOperationsHandler) Proxy.newProxyInstance(LocalFileOperationsHandler.class.getClassLoader(), - new Class[]{LocalFileOperationsHandler.class}, myParent); - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if ("afterDone".equals(method.getName()) && args.length == 1) { - ((ThrowableConsumer)args[0]).consume(myParentProxy); - return null; - } - - if (LocalFileOperationsHandler.class.equals(method.getDeclaringClass())) { - myParent.register(method, args); - } - if ("equals".equals(method.getName())) { - return args[0].equals(this); - } - else if ("hashCode".equals(method.getName())) { - return 1; - } - return method.invoke(myDelegate, args); - } - } -} From ac6ba0c1dadf4937894cc114a4234214829adb0c Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 14 Nov 2014 17:41:02 +0300 Subject: [PATCH 04/75] svn: Use common "Jump to Source" action (instead of custom "Open" action) to open files from repository browser --- .../svn/dialogs/RepositoryBrowserDialog.java | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index 83d895b93ffc..6f386abf1fa6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -25,7 +25,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; -import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.progress.ProgressIndicator; @@ -192,6 +191,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { } protected JPopupMenu createPopup(boolean toolWindow) { + ActionManager actionManager = ActionManager.getInstance(); DefaultActionGroup group = new DefaultActionGroup(); DefaultActionGroup newGroup = new DefaultActionGroup("_New", true); final RepositoryBrowserComponent browser = getRepositoryBrowser(); @@ -200,7 +200,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { group.add(newGroup); group.addSeparator(); if (toolWindow) { - group.add(new OpenAction()); + group.add(actionManager.getAction(IdeActions.ACTION_EDIT_SOURCE)); group.add(new HistoryAction()); } group.add(new CheckoutAction()); @@ -218,7 +218,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { group.add(new RefreshAction(browser)); group.add(new EditLocationAction(browser)); group.add(new DiscardLocationAction(browser)); - ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(PLACE_MENU, group); + ActionPopupMenu menu = actionManager.createActionPopupMenu(PLACE_MENU, group); return menu.getComponent(); } @@ -928,23 +928,6 @@ public class RepositoryBrowserDialog extends DialogWrapper { } } - protected class OpenAction extends AnAction { - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(false); - if (myVCS == null) { - return; - } - e.getPresentation().setText("_Open", true); - e.getPresentation().setEnabled(getRepositoryBrowser().getSelectedVcsFile() != null); - } - public void actionPerformed(AnActionEvent e) { - VirtualFile vcsVF = getRepositoryBrowser().getSelectedVcsFile(); - if (vcsVF != null) { - FileEditorManager.getInstance(myVCS.getProject()).openFile(vcsVF, true); - } - } - } - protected class DetailsAction extends ToggleAction { private boolean myIsSelected; From 0d463f635d1926d218a181fceaffd23b790c43a8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 14 Nov 2014 19:18:18 +0300 Subject: [PATCH 05/75] IDEA-104113 Disable SelectInAction action for svn repository browser - provide custom Navigatable instance (instead of OpenFileDescriptor instance) --- .../svn/dialogs/RepositoryBrowserComponent.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java index f7e54a64f0ad..d6eaf61509bf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java @@ -18,13 +18,13 @@ package org.jetbrains.idea.svn.dialogs; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.vfs.VcsFileSystem; import com.intellij.openapi.vcs.vfs.VcsVirtualFile; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.NavigatableAdapter; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SpeedSearchComparator; import com.intellij.ui.TreeSpeedSearch; @@ -282,7 +282,18 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da return null; } final VirtualFile vcsFile = getSelectedVcsFile(); - return vcsFile != null ? new OpenFileDescriptor(project, vcsFile) : null; + + // do not return OpenFileDescriptor instance here as in that case SelectInAction will be enabled and its invocation (using keyboard) + // will raise error - see IDEA-104113 - because of the following operations inside SelectInAction.actionPerformed(): + // - at first VcsVirtualFile content will be loaded which for svn results in showing progress dialog + // - then DataContext from SelectInAction will still be accessed which results in error as current event count has already changed + // (because of progress dialog) + return vcsFile != null ? new NavigatableAdapter() { + @Override + public void navigate(boolean requestFocus) { + navigate(project, vcsFile, requestFocus); + } + } : null; } else if (CommonDataKeys.PROJECT.is(dataId)) { return myVCS.getProject(); } From 7a2e2cdbe871a3a12f0017385bb58fd69b3f0ff0 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 14:50:05 +0300 Subject: [PATCH 06/75] fixed PY-13531 Stop executing $world when it looks like a python binary. --- .../com/jetbrains/python/sdk/flavors/CPythonSdkFlavor.java | 3 +++ .../jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java | 6 +++--- .../jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java | 7 +++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/flavors/CPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/CPythonSdkFlavor.java index 62448004d574..da0f236205d0 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/CPythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/CPythonSdkFlavor.java @@ -17,10 +17,13 @@ package com.jetbrains.python.sdk.flavors; import org.jetbrains.annotations.NotNull; +import java.util.regex.Pattern; + /** * @author yole */ public abstract class CPythonSdkFlavor extends PythonSdkFlavor { + public final static Pattern PYTHON_RE = Pattern.compile("python-?(\\d\\.\\d)?|python-?(\\d)?"); @NotNull @Override public String getName() { diff --git a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java index cf18921e017c..a424614d1338 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java @@ -31,7 +31,7 @@ public class UnixPythonSdkFlavor extends CPythonSdkFlavor { private UnixPythonSdkFlavor() { } - private final static String[] NAMES = new String[]{"python", "jython", "pypy"}; + private final static String[] NAMES = new String[]{"jython", "pypy"}; public static UnixPythonSdkFlavor INSTANCE = new UnixPythonSdkFlavor(); @@ -52,9 +52,9 @@ public class UnixPythonSdkFlavor extends CPythonSdkFlavor { VirtualFile[] suspects = rootDir.getChildren(); for (VirtualFile child : suspects) { if (!child.isDirectory()) { - final String childName = child.getName(); + final String childName = child.getName().toLowerCase(); for (String name : NAMES) { - if (childName.startsWith(name)) { + if (childName.startsWith(name) || PYTHON_RE.matcher(childName).matches()) { String childPath = child.getPath(); if (FileSystemUtil.isSymLink(childPath)) { childPath = FileSystemUtil.resolveSymLink(childPath); diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java index 576a66279900..7918f63ff77d 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java @@ -41,8 +41,7 @@ import java.util.List; public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { private VirtualEnvSdkFlavor() { } - - private final static String[] NAMES = new String[]{"python", "jython", "pypy", "python.exe", "jython.bat", "pypy.exe"}; + private final static String[] NAMES = new String[]{"jython", "pypy", "python.exe", "jython.bat", "pypy.exe"}; public static VirtualEnvSdkFlavor INSTANCE = new VirtualEnvSdkFlavor(); @@ -107,7 +106,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { private static String findInterpreter(VirtualFile dir) { for (VirtualFile child : dir.getChildren()) { if (!child.isDirectory()) { - final String childName = child.getName(); + final String childName = child.getName().toLowerCase(); for (String name : NAMES) { if (SystemInfo.isWindows) { if (childName.equals(name)) { @@ -115,7 +114,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { } } else { - if (childName.startsWith(name)) { + if (childName.startsWith(name) || PYTHON_RE.matcher(childName).matches()) { if (!childName.endsWith("-config")) { return child.getPath(); } From a0bbeb1015de5ef8292491dc96442ac8b09bf55a Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 16:03:14 +0300 Subject: [PATCH 07/75] removed json text view from ipython notebook --- .../ipnb/editor/IpnbEditorProvider.java | 2 +- .../plugins/ipnb/editor/IpnbFileEditor.java | 60 ++++--------------- .../ipnb/editor/panels/IpnbFilePanel.java | 2 +- 3 files changed, 12 insertions(+), 52 deletions(-) diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbEditorProvider.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbEditorProvider.java index 6b17ce0c1bc7..5eae76c5509f 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbEditorProvider.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbEditorProvider.java @@ -67,6 +67,6 @@ public class IpnbEditorProvider implements FileEditorProvider, DumbAware { @NotNull @Override public FileEditorPolicy getPolicy() { - return FileEditorPolicy.PLACE_BEFORE_DEFAULT_EDITOR; + return FileEditorPolicy.HIDE_DEFAULT_EDITOR; } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbFileEditor.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbFileEditor.java index ad82df9d56b5..685ea9d27620 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbFileEditor.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/IpnbFileEditor.java @@ -6,19 +6,15 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.*; -import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.pom.Navigatable; import com.intellij.ui.JBColor; import com.intellij.ui.ScrollPaneFactory; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.ipnb.editor.actions.*; import org.jetbrains.plugins.ipnb.editor.panels.*; import org.jetbrains.plugins.ipnb.editor.panels.code.IpnbCodePanel; @@ -41,15 +37,15 @@ import java.util.List; /** * @author traff */ -public class IpnbFileEditor extends UserDataHolderBase implements FileEditor, TextEditor { +public class IpnbFileEditor extends UserDataHolderBase implements FileEditor { private final VirtualFile myFile; private final String myName; private final JComponent myEditorPanel; - private final TextEditor myEditor; private final IpnbFilePanel myIpnbFilePanel; + private final Document myDocument; private ComboBox myCellTypeCombo; private static final String codeCellType = "Code"; private static final String markdownCellType = "Markdown"; @@ -63,12 +59,14 @@ public class IpnbFileEditor extends UserDataHolderBase implements FileEditor, Te public IpnbFileEditor(Project project, final VirtualFile vFile) { + myDocument = FileDocumentManager.getInstance().getDocument(vFile); project.getMessageBus().connect(this).subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER, new FileEditorManagerListener.Before.Adapter() { @Override public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { if (!new File(file.getPath()).exists()) return; - final Document document = getEditor().getDocument(); - FileDocumentManager.getInstance().saveDocument(document); + + if (myDocument == null) return; + FileDocumentManager.getInstance().saveDocument(myDocument); IpnbParser.saveIpnbFile(myIpnbFilePanel); file.refresh(false, false); } @@ -78,8 +76,6 @@ public class IpnbFileEditor extends UserDataHolderBase implements FileEditor, Te myName = vFile.getName(); - myEditor = createEditor(project, vFile); - myEditorPanel = new JPanel(new BorderLayout()); myEditorPanel.setBackground(IpnbEditorUtil.getBackground()); @@ -94,6 +90,10 @@ public class IpnbFileEditor extends UserDataHolderBase implements FileEditor, Te registerHeadingActions(); } + public Document getDocument() { + return myDocument; + } + private void registerHeadingActions() { new IpnbHeading1CellAction().registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("ctrl shift 1")), myIpnbFilePanel); new IpnbHeading2CellAction().registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("ctrl shift 2")), myIpnbFilePanel); @@ -417,46 +417,6 @@ public class IpnbFileEditor extends UserDataHolderBase implements FileEditor, Te @Override public void dispose() { - Disposer.dispose(myEditor); - } - - @NotNull - @Override - public Editor getEditor() { - return myEditor.getEditor(); - } - - @Override - public boolean canNavigateTo(@NotNull Navigatable navigatable) { - return true; - } - - @Override - public void navigateTo(@NotNull Navigatable navigatable) { - } - - @Nullable - private static TextEditor createEditor(@NotNull Project project, @NotNull VirtualFile vFile) { - FileEditorProvider provider = getProvider(project, vFile); - - if (provider != null) { - FileEditor editor = provider.createEditor(project, vFile); - if (editor instanceof TextEditor) { - return (TextEditor)editor; - } - } - return null; - } - - @Nullable - private static FileEditorProvider getProvider(Project project, VirtualFile vFile) { - FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(project, vFile); - for (FileEditorProvider provider : providers) { - if (!(provider instanceof IpnbEditorProvider)) { - return provider; - } - } - return null; } public abstract static class CellSelectionListener { diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java index 5017073ebf15..0de2d5795688 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java @@ -78,7 +78,7 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D alarm.addRequest(new MySynchronizeRequest(), 10, ModalityState.stateForComponent(IpnbFilePanel.this)); } }; - myDocument = myParent.getEditor().getDocument(); + myDocument = myParent.getDocument(); myDocument.addDocumentListener(myDocumentListener); alarm.addRequest(new Runnable() { From db221f8f639c354f1844bb6242807c8280925507 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 17 Nov 2014 17:25:30 +0300 Subject: [PATCH 08/75] Fixed resolving nested class names in nested classes inside stubs (PY-13969) --- .../python/psi/impl/PyClassImpl.java | 63 ++++++++++++------- .../StubsOfNestedClasses/a.py | 10 +++ .../StubsOfNestedClasses/b.py | 8 +++ .../StubsOfNestedClasses/c.py | 4 ++ .../PyUnresolvedReferencesInspectionTest.java | 5 ++ 5 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/a.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/b.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/c.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 37cd12906b41..b9bf5d7c63d9 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -40,8 +40,10 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.documentation.DocStringUtil; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.resolve.PyResolveContext; import com.jetbrains.python.psi.resolve.PyResolveUtil; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; +import com.jetbrains.python.psi.resolve.RatedResolveResult; import com.jetbrains.python.psi.stubs.PropertyStubStorage; import com.jetbrains.python.psi.stubs.PyClassStub; import com.jetbrains.python.psi.stubs.PyFunctionStub; @@ -1174,11 +1176,10 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla final PyClassStub stub = getStub(); final List result = new ArrayList(); if (stub != null) { - final PsiElement parent = stub.getParentStub().getPsi(); - if (parent instanceof PyFile) { - final PyFile file = (PyFile)parent; + final PsiFile file = getContainingFile(); + if (file instanceof PyFile) { for (QualifiedName name : stub.getSuperClasses()) { - result.add(name != null ? classTypeFromQName(name, file, context) : null); + result.add(name != null ? classTypeFromQName(name, (PyFile)file, context) : null); } } } @@ -1315,47 +1316,67 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } @Nullable - private static PsiElement getElementQNamed(@NotNull NameDefiner nameDefiner, @NotNull QualifiedName qualifiedName) { + private static PsiElement getElementQNamed(@NotNull PyFile file, @NotNull QualifiedName qualifiedName, @NotNull TypeEvalContext context) { final int componentCount = qualifiedName.getComponentCount(); final String fullName = qualifiedName.toString(); + final PyType type = new PyModuleType(file); if (componentCount == 0) { return null; } else if (componentCount == 1) { - PsiElement element = nameDefiner.getElementNamed(fullName); + PsiElement element = resolveTypeMember(type, fullName, context); if (element == null) { - element = PyBuiltinCache.getInstance(nameDefiner).getByName(fullName); + element = PyBuiltinCache.getInstance(file).getByName(fullName); } return element; } else { final String name = qualifiedName.getLastComponent(); final QualifiedName containingQName = qualifiedName.removeLastComponent(); - NameDefiner definer = nameDefiner; + PyType currentType = type; for (String component : containingQName.getComponents()) { - PsiElement element = PyUtil.turnDirIntoInit(definer.getElementNamed(component)); - if (element instanceof PyImportElement) { - element = ((PyImportElement)element).resolve(); - } - if (element instanceof NameDefiner) { - definer = (NameDefiner)element; - } - else { - definer = null; - break; + currentType = getMemberType(currentType, component, context); + if (currentType == null) { + return null; } } - if (definer != null) { - return definer.getElementNamed(name); + if (name != null) { + return resolveTypeMember(currentType, name, context); } return null; } } + @Nullable + private static PyType getMemberType(@NotNull PyType type, @NotNull String name, @NotNull TypeEvalContext context) { + final PyType result; + PsiElement element = resolveTypeMember(type, name, context); + if (element instanceof PyImportedModule) { + result = new PyImportedModuleType((PyImportedModule)element); + } + else if (element instanceof PyTypedElement) { + result = context.getType((PyTypedElement)element); + } + else { + return null; + } + if (result instanceof PyClassLikeType) { + return ((PyClassLikeType)result).toInstance(); + } + return result; + } + + @Nullable + private static PsiElement resolveTypeMember(@NotNull PyType type, @NotNull String name, @NotNull TypeEvalContext context) { + final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context); + final List results = type.resolveMember(name, null, AccessDirection.READ, resolveContext); + return (results != null && !results.isEmpty()) ? results.get(0).getElement() : null; + } + @Nullable private static PyClassLikeType classTypeFromQName(@NotNull QualifiedName qualifiedName, @NotNull PyFile containingFile, @NotNull TypeEvalContext context) { - final PsiElement element = getElementQNamed(containingFile, qualifiedName); + final PsiElement element = getElementQNamed(containingFile, qualifiedName, context); if (element instanceof PyTypedElement) { final PyType type = context.getType((PyTypedElement)element); if (type instanceof PyClassLikeType) { diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/a.py new file mode 100644 index 000000000000..855d14972ed6 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/a.py @@ -0,0 +1,10 @@ +from b import Class2 + + +class Class3(Class2): + class SubClass3(Class2.SubClass2): + def __init__(self, foo): + Class2.SubClass2.__init__(self, foo) + + def test(self): + print(self.foo) diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/b.py b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/b.py new file mode 100644 index 000000000000..4c33b9e5f340 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/b.py @@ -0,0 +1,8 @@ +from c import Class1 + + +class Class2(Class1): + class SubClass2(Class1.SubClass1): + def __init__(self, foo): + Class1.SubClass1.__init__(self, foo) + diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/c.py b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/c.py new file mode 100644 index 000000000000..e771f0bcc970 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/StubsOfNestedClasses/c.py @@ -0,0 +1,4 @@ +class Class1(object): + class SubClass1(object): + def __init__(self, foo=None): + self.foo = foo diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 88b036bac86e..98c8674e1793 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -415,6 +415,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doMultiFileTest(); } + // PY-13969 + public void testStubsOfNestedClasses() { + doMultiFileTest(); + } + @NotNull @Override protected Class getInspectionClass() { From a6404312d55ebcf837686468609a9ec22fccf77b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 18:15:00 +0300 Subject: [PATCH 09/75] cross-cell resolve to function declaration --- .../ipnb/psi/IpnbFunctionElementType.java | 30 +++++++++++++ .../plugins/ipnb/psi/IpnbPyFunction.java | 44 +++++++++++++++++++ .../ipnb/psi/IpnbPyParsingContext.java | 18 ++++++++ .../ipnb/psi/IpnbPyTokenSetContributor.java | 7 +++ .../plugins/ipnb/psi/IpnbPyTokenTypes.java | 2 + 5 files changed, 101 insertions(+) create mode 100644 python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbFunctionElementType.java create mode 100644 python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyFunction.java diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbFunctionElementType.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbFunctionElementType.java new file mode 100644 index 000000000000..80723bdb1f95 --- /dev/null +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbFunctionElementType.java @@ -0,0 +1,30 @@ +package org.jetbrains.plugins.ipnb.psi; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.stubs.IStubElementType; +import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.psi.impl.stubs.PyFunctionElementType; +import com.jetbrains.python.psi.stubs.PyFunctionStub; +import org.jetbrains.annotations.NotNull; + +public class IpnbFunctionElementType extends PyFunctionElementType { + public IpnbFunctionElementType() { + super("IPNB_FUNCTION"); + } + + @Override + public PsiElement createElement(@NotNull ASTNode node) { + return new IpnbPyFunction(node); + } + + @Override + public PyFunction createPsi(@NotNull PyFunctionStub stub) { + return new IpnbPyFunction(stub); + } + + @Override + protected IStubElementType getStubElementType() { + return IpnbPyTokenTypes.IPNB_FUNCTION; + } +} diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyFunction.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyFunction.java new file mode 100644 index 000000000000..13589f65ec15 --- /dev/null +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyFunction.java @@ -0,0 +1,44 @@ +package org.jetbrains.plugins.ipnb.psi; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.stubs.IStubElementType; +import com.intellij.util.ui.UIUtil; +import com.jetbrains.python.psi.impl.PyFunctionImpl; +import com.jetbrains.python.psi.stubs.PyFunctionStub; +import org.jetbrains.plugins.ipnb.editor.IpnbFileEditor; +import org.jetbrains.plugins.ipnb.editor.panels.IpnbFilePanel; +import org.jetbrains.plugins.ipnb.editor.panels.code.IpnbCodePanel; +import org.jetbrains.plugins.ipnb.editor.panels.code.IpnbCodeSourcePanel; + +public class IpnbPyFunction extends PyFunctionImpl { + + public IpnbPyFunction(ASTNode astNode) { + super(astNode); + } + + public IpnbPyFunction(PyFunctionStub stub) { + super(stub); + } + + public IpnbPyFunction(PyFunctionStub stub, IStubElementType nodeType) { + super(stub, nodeType); + } + + @Override + public void navigate(boolean requestFocus) { + final IpnbCodeSourcePanel sourcePanel = ((IpnbPyFragment)getContainingFile()).getCodeSourcePanel(); + final Editor editor = sourcePanel.getEditor(); + + final IpnbCodePanel codePanel = sourcePanel.getIpnbCodePanel(); + final IpnbFileEditor fileEditor = codePanel.getFileEditor(); + final IpnbFilePanel filePanel = fileEditor.getIpnbFilePanel(); + codePanel.setEditing(true); + filePanel.setSelectedCell(codePanel); + super.navigate(false); + UIUtil.requestFocus(editor.getContentComponent()); + + } + +} + diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParsingContext.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParsingContext.java index 13d1196b510d..37e78b18e843 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParsingContext.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParsingContext.java @@ -4,6 +4,7 @@ import com.intellij.lang.PsiBuilder; import com.intellij.psi.tree.IElementType; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.parsing.ExpressionParsing; +import com.jetbrains.python.parsing.FunctionParsing; import com.jetbrains.python.parsing.ParsingContext; import com.jetbrains.python.parsing.StatementParsing; import com.jetbrains.python.psi.LanguageLevel; @@ -12,6 +13,7 @@ import org.jetbrains.annotations.Nullable; public class IpnbPyParsingContext extends ParsingContext { private final StatementParsing myStatementParser; private final ExpressionParsing myExpressionParser; + private final FunctionParsing myFunctionParser; public IpnbPyParsingContext(final PsiBuilder builder, LanguageLevel languageLevel, @@ -19,6 +21,7 @@ public class IpnbPyParsingContext extends ParsingContext { super(builder, languageLevel, futureFlag); myStatementParser = new IpnbPyStatementParsing(this, futureFlag); myExpressionParser = new IpnbPyExpressionParsing(this); + myFunctionParser = new IpnbPyFunctionParsing(this); } @Override @@ -31,6 +34,11 @@ public class IpnbPyParsingContext extends ParsingContext { return myStatementParser; } + @Override + public FunctionParsing getFunctionParser() { + return myFunctionParser; + } + private static class IpnbPyExpressionParsing extends ExpressionParsing { public IpnbPyExpressionParsing(ParsingContext context) { super(context); @@ -68,4 +76,14 @@ public class IpnbPyParsingContext extends ParsingContext { } } + private static class IpnbPyFunctionParsing extends FunctionParsing { + + public IpnbPyFunctionParsing(ParsingContext context) { + super(context); + } + protected IElementType getFunctionType() { + return IpnbPyTokenTypes.IPNB_FUNCTION; + } + + } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenSetContributor.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenSetContributor.java index d02bc3d02c1b..f06f31445b53 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenSetContributor.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenSetContributor.java @@ -18,4 +18,11 @@ public class IpnbPyTokenSetContributor extends PythonDialectsTokenSetContributor public TokenSet getReferenceExpressionTokens() { return IPNB_REFERENCE_EXPRESSIONS; } + + + @NotNull + @Override + public TokenSet getFunctionDeclarationTokens() { + return TokenSet.create(IpnbPyTokenTypes.IPNB_FUNCTION); + } } diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenTypes.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenTypes.java index a271089b784d..02f69b054f8f 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenTypes.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyTokenTypes.java @@ -1,10 +1,12 @@ package org.jetbrains.plugins.ipnb.psi; import com.jetbrains.python.psi.PyElementType; +import com.jetbrains.python.psi.impl.stubs.PyFunctionElementType; public class IpnbPyTokenTypes { public static final PyElementType IPNB_REFERENCE = new PyElementType("IPNB_REFERENCE", IpnbPyReferenceExpression.class); public static final PyElementType IPNB_TARGET = new PyElementType("IPNB_TARGET", IpnbPyTargetExpression.class); + public static final PyFunctionElementType IPNB_FUNCTION = new IpnbFunctionElementType(); private IpnbPyTokenTypes() { } From 2c754a77cc16d94e691911e28c49e9dc28293910 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 17 Nov 2014 18:45:14 +0300 Subject: [PATCH 10/75] following IDEA-CR-949 --- .../src/com/intellij/openapi/editor/impl/FoldRegionsTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java index b339d670989f..fa89bb14960a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java @@ -28,7 +28,7 @@ import java.util.*; * User: cdr */ abstract class FoldRegionsTree { - @NotNull private CachedData myCachedData = new CachedData(); + @NotNull private volatile CachedData myCachedData = new CachedData(); //sorted using RangeMarker.BY_START_OFFSET comparator //i.e., first by start offset, then, if start offsets are equal, by end offset From e9b765d0c2e8386dab8e0783e1dfc0f65a0259fb Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Mon, 17 Nov 2014 18:45:05 +0300 Subject: [PATCH 11/75] transparent editor scrollbar --- .../editor/impl/EditorMarkupModelImpl.java | 25 ++++++++++++++++--- .../util/resources/misc/registry.properties | 2 ++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index e4653693ac9c..a72366df3b1e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -46,6 +46,7 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; @@ -442,9 +443,10 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark errorIconBounds.y = (bounds.height - errorIconBounds.height) / 2 - 1; try { - g.setColor(getEditor().getColorsScheme().getDefaultBackground()); - g.fillRect(0, 0, bounds.width, bounds.height); - + if (!transparent()) { + g.setColor(getEditor().getColorsScheme().getDefaultBackground()); + g.fillRect(0, 0, bounds.width, bounds.height); + } if (myErrorStripeRenderer != null) { myErrorStripeRenderer.paint(this, g, errorIconBounds); } @@ -459,6 +461,10 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark return STRIPE_BUTTON_PREFERRED_SIZE; } } + + private boolean transparent() { + return Registry.is("editor.transparent.scrollbar", false); + } private class MyErrorPanel extends ButtonlessScrollBarUI implements MouseMotionListener, MouseListener, MouseWheelListener, UISettingsListener { private PopupHandler myHandler; @@ -478,7 +484,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark @Override public boolean alwaysShowTrack() { - if (scrollbar.getOrientation() == Adjustable.VERTICAL) return true; + if (scrollbar.getOrientation() == Adjustable.VERTICAL) return !transparent(); return super.alwaysShowTrack(); } @@ -568,6 +574,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark return super.getThickness() + myMinMarkHeight - 1 + fix; } + @Override + protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { + if (transparent()) { + doPaintTrack(g, c, trackBounds); + } + else { + super.paintTrack(g, c, trackBounds); + } + } + @Override protected void doPaintTrack(Graphics g, JComponent c, Rectangle bounds) { if (isMacScrollbarHiddenAndDistractionFreeEnabled()) { @@ -607,6 +623,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } private void paintTrackBasement(Graphics g, Rectangle bounds) { + if (transparent()) return; g.setColor(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground()); g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c719a74d55aa..be1f06ba103c 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -487,3 +487,5 @@ enable.recursive.document.changes.description=Enables performing document change editor.caret.width=2 editor.caret.width.description=Caret width editor.caret.width.restartRequired=true + +editor.transparent.scrollbar=false From c547479f6b55ed5321767289cd16a79198045538 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 17 Nov 2014 16:32:37 +0100 Subject: [PATCH 12/75] IDEA-133006 (Literal not found in annotation) --- .../strategies/ExprMatchingStrategy.java | 21 +++++++++++++++++++ .../StructuralSearchTest.java | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java index c892badb85be..a1bebac82a42 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java @@ -6,6 +6,27 @@ import com.intellij.psi.*; * Expression matching strategy */ public class ExprMatchingStrategy extends MatchingStrategyBase { + + @Override public void visitAnnotation(final PsiAnnotation annotation) { + result = true; + } + + @Override public void visitAnnotationParameterList(final PsiAnnotationParameterList list) { + result = true; + } + + @Override public void visitModifierList(final PsiModifierList list) { + result = true; + } + + @Override public void visitNameValuePair(final PsiNameValuePair pair) { + result = true; + } + + @Override public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) { + result = true; + } + @Override public void visitExpression(final PsiExpression expr) { result = true; } diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 603ae1cbcbe1..0bbeb81c4c79 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -592,6 +592,12 @@ public class StructuralSearchTest extends StructuralSearchTestCase { String pattern3 = "\"'String\""; assertEquals("String literal", 1, findMatchesCount(s, pattern3)); + + String pattern4 = "\"test\""; + String source = "@SuppressWarnings(\"test\") class A {" + + " @SuppressWarnings({\"other\", \"test\"}) String field;" + + "}"; + assertEquals("String literal in annotation", 2, findMatchesCount(source, pattern4)); } public void testCovariantArraySearch() { From e3b30964db4f4ddc4e3f0b554214ad5720a4bb95 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 17 Nov 2014 19:08:25 +0300 Subject: [PATCH 13/75] fixed "Dialog must be init in EDT only" --- .../impl/ui/tree/actions/XFetchValueActionBase.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java index 13121c7fda16..d27c65084296 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.AppUIUtil; import com.intellij.util.SmartList; import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.impl.ui.XValueTextProvider; @@ -116,9 +117,14 @@ public abstract class XFetchValueActionBase extends AnAction { return index; } - public void evaluationComplete(int index, @NotNull String value, Project project) { - values.set(index, value); - finish(project); + public void evaluationComplete(final int index, @NotNull final String value, final Project project) { + AppUIUtil.invokeOnEdt(new Runnable() { + @Override + public void run() { + values.set(index, value); + finish(project); + } + }); } } From 742977c5df1ed63a6555b15ef914333a032a677a Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 17 Nov 2014 19:15:30 +0300 Subject: [PATCH 14/75] IDEA-133007 We should allow null value for the dimension service key to disable bounds save/restore --- .../intellij/openapi/options/newEditor/SettingsDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java index 03ed0c82fd3b..9b91979fd22e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsDialog.java @@ -41,7 +41,7 @@ public final class SettingsDialog extends DialogWrapper implements DataProvider private boolean myApplyButtonNeeded; private boolean myResetButtonNeeded; - public SettingsDialog(Project project, @NotNull String key, @NotNull Configurable configurable, boolean showApplyButton) { + public SettingsDialog(Project project, String key, @NotNull Configurable configurable, boolean showApplyButton) { super(project, true); myDimensionServiceKey = key; myEditor = new ConfigurableEditor(myDisposable, configurable); @@ -49,7 +49,7 @@ public final class SettingsDialog extends DialogWrapper implements DataProvider init(configurable); } - public SettingsDialog(@NotNull Component parent, @NotNull String key, @NotNull Configurable configurable, boolean showApplyButton) { + public SettingsDialog(@NotNull Component parent, String key, @NotNull Configurable configurable, boolean showApplyButton) { super(parent, true); myDimensionServiceKey = key; myEditor = new ConfigurableEditor(myDisposable, configurable); From 98e1fdb33833be0fad3f1e12e95baaf75c99886c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 17 Nov 2014 17:23:42 +0100 Subject: [PATCH 15/75] fix project memory leak in tests --- .../compiler/server/BuildManager.java | 31 +++++++++---------- .../PreloadedProcessMessageHandler.java | 13 +------- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 411cc3d5720a..f53181ad8e54 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -387,9 +387,10 @@ public class BuildManager implements ApplicationComponent{ } public void clearState(Project project) { - cancelPreloadedBuilds(project); - final String projectPath = getProjectPath(project); + + cancelPreloadedBuilds(projectPath); + synchronized (myProjectDataMap) { final ProjectData data = myProjectDataMap.get(projectPath); if (data != null) { @@ -544,8 +545,7 @@ public class BuildManager implements ApplicationComponent{ return futures; } - private void cancelPreloadedBuilds(Project project) { - final String projectPath = getProjectPath(project); + private void cancelPreloadedBuilds(final String projectPath) { runCommand(new Runnable() { @Override public void run() { @@ -632,12 +632,7 @@ public class BuildManager implements ApplicationComponent{ sessionId = UUID.randomUUID(); } - final RequestFuture future = usingPreloadedProcess? preloadedFuture : new RequestFuture(handler, sessionId, new RequestFuture.CancelAction() { - @Override - public void cancel(RequestFuture future) throws Exception { - myMessageDispatcher.cancelSession(future.getRequestID()); - } - }); + final RequestFuture future = usingPreloadedProcess? preloadedFuture : new RequestFuture(handler, sessionId, new CancelBuildSessionAction()); _future.setDelegate(future); if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) { @@ -833,12 +828,7 @@ public class BuildManager implements ApplicationComponent{ // launching build process from projectTaskQueue ensures that no other build process for this project is currently running return projectTaskQueue.submit(new Callable, OSProcessHandler>>() { public Pair, OSProcessHandler> call() throws Exception { - final RequestFuture future = new RequestFuture(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction() { - @Override - public void cancel(RequestFuture future) throws Exception { - myMessageDispatcher.cancelSession(future.getRequestID()); - } - }); + final RequestFuture future = new RequestFuture(new PreloadedProcessMessageHandler(), UUID.randomUUID(), new CancelBuildSessionAction()); try { myMessageDispatcher.registerBuildMessageHandler(future, null); final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, future.getRequestID(), true); @@ -1349,6 +1339,7 @@ public class BuildManager implements ApplicationComponent{ Disposer.register(project, new Disposable() { @Override public void dispose() { + cancelPreloadedBuilds(projectPath); myProjectDataMap.remove(projectPath); } }); @@ -1368,7 +1359,7 @@ public class BuildManager implements ApplicationComponent{ @Override public void projectClosing(Project project) { - cancelPreloadedBuilds(project); + cancelPreloadedBuilds(getProjectPath(project)); for (TaskFuture future : cancelAutoMakeTasks(project)) { future.waitFor(500, TimeUnit.MILLISECONDS); } @@ -1613,4 +1604,10 @@ public class BuildManager implements ApplicationComponent{ } } + private class CancelBuildSessionAction implements RequestFuture.CancelAction { + @Override + public void cancel(RequestFuture future) throws Exception { + myMessageDispatcher.cancelSession(future.getRequestID()); + } + } } diff --git a/java/compiler/impl/src/com/intellij/compiler/server/PreloadedProcessMessageHandler.java b/java/compiler/impl/src/com/intellij/compiler/server/PreloadedProcessMessageHandler.java index 5a8c3e28a1c6..2a328caabe22 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/PreloadedProcessMessageHandler.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/PreloadedProcessMessageHandler.java @@ -15,25 +15,14 @@ */ package com.intellij.compiler.server; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - /** * @author Eugene Zhuravlev * Date: 20-Oct-14 */ class PreloadedProcessMessageHandler extends DelegatingMessageHandler { - @NotNull - private final Project myProject; private volatile BuilderMessageHandler myDelegateHandler; - public PreloadedProcessMessageHandler(@NotNull Project project) { - myProject = project; - } - - @NotNull - public Project getProject() { - return myProject; + public PreloadedProcessMessageHandler() { } @Override From 5256cdfc5f9363a38474e76e1e7e881d984643ca Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 17 Nov 2014 19:47:43 +0300 Subject: [PATCH 16/75] IDEA-132887 Wrong settings page for debugger settings displayed --- .../GenericDebuggerParametersRunnerConfigurable.java | 2 +- .../intellij/ide/actions/ShowSettingsUtilImpl.java | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerParametersRunnerConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerParametersRunnerConfigurable.java index 2d07226a7229..59073f3cd373 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerParametersRunnerConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerParametersRunnerConfigurable.java @@ -51,7 +51,7 @@ public class GenericDebuggerParametersRunnerConfigurable extends SettingsEditor< myDebuggerSettings.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - ShowSettingsUtil.getInstance().showSettingsDialog(project, DebuggerConfigurable.DISPLAY_NAME); + ShowSettingsUtil.getInstance().showSettingsDialog(project, DebuggerConfigurable.class); if (myIsLocal) { setTransport(DebuggerSettings.getInstance().DEBUGGER_TRANSPORT); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java index a8b9809cf65e..f7f14547e8aa 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java @@ -125,23 +125,13 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { ConfigurableGroup[] groups = getConfigurableGroups(project, true); - Configurable config = findByClass(getConfigurables(groups, true), configurableClass); + Configurable config = new ConfigurableVisitor.ByType(configurableClass).find(groups); assert config != null : "Cannot find configurable: " + configurableClass.getName(); getDialog(project, groups, config).show(); } - @Nullable - private static Configurable findByClass(Configurable[] configurables, Class configurableClass) { - for (Configurable configurable : configurables) { - if (configurableClass.isInstance(configurable)) { - return configurable; - } - } - return null; - } - @Override public void showSettingsDialog(@Nullable final Project project, @NotNull final String nameToSelect) { ConfigurableGroup[] groups = getConfigurableGroups(project, true); From a68f44ab97f966852cdd50eb09d658d6267e1760 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Mon, 17 Nov 2014 19:52:17 +0300 Subject: [PATCH 17/75] IDEA-121505 Breakpoint properties popup: More link does not work if over tool window splitter --- .../src/com/intellij/openapi/wm/IdeGlassPaneUtil.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java index 10d49e44ac48..d5985d9fe731 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java @@ -18,6 +18,7 @@ package com.intellij.openapi.wm; import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.Painter; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; import com.intellij.util.ui.update.Activatable; import com.intellij.util.ui.update.UiNotifyConnector; @@ -70,6 +71,10 @@ public class IdeGlassPaneUtil { public static boolean canBePreprocessed(MouseEvent e) { Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY()); + if (JBPopupFactory.getInstance().getParentBalloonFor(c) != null) { + return false; + } + if (c instanceof IdeGlassPane.TopComponent) { return ((IdeGlassPane.TopComponent)c).canBePreprocessed(e); } From a7d0e5c635ef1abe40a09d28253c5d5544f9de64 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 17 Nov 2014 17:41:46 +0300 Subject: [PATCH 18/75] PY-14384 Check that existing import is not relative when searching for duplicate imports --- .../codeInsight/imports/AddImportHelper.java | 2 +- .../after/src/nspkg/a.py | 3 +++ .../after/src/nssubpkg/b.py | 0 .../before/src/nspkg/a.py | 3 +++ .../before/src/nspkg/nssubpkg/b.py | 0 .../after/src/nspkg/__init__.py | 0 .../after/src/nspkg/a.py | 3 +++ .../after/src/nssubpkg/__init__.py | 0 .../after/src/nssubpkg/b.py | 0 .../before/src/nspkg/__init__.py | 0 .../before/src/nspkg/a.py | 3 +++ .../before/src/nspkg/nssubpkg/__init__.py | 0 .../before/src/nspkg/nssubpkg/b.py | 0 .../jetbrains/python/refactoring/PyMoveTest.java | 14 ++++++++++++++ 14 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nspkg/a.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nssubpkg/b.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/a.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/nssubpkg/b.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/a.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/b.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/a.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/b.py diff --git a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java index 753ed4b59dec..5ad10678d068 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java @@ -263,7 +263,7 @@ public class AddImportHelper { continue; } final QualifiedName qName = existingImport.getImportSourceQName(); - if (qName != null && qName.toString().equals(path)) { + if (qName != null && qName.toString().equals(path) && existingImport.getRelativeLevel() == 0) { for (PyImportElement el : existingImport.getImportElements()) { if (name.equals(el.getVisibleName())) { return false; diff --git a/python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nspkg/a.py b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nspkg/a.py new file mode 100644 index 000000000000..37fb8093807e --- /dev/null +++ b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nspkg/a.py @@ -0,0 +1,3 @@ +from nssubpkg import b + +print(b) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nssubpkg/b.py b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/after/src/nssubpkg/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/a.py b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/a.py new file mode 100644 index 000000000000..c6af594436cf --- /dev/null +++ b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/a.py @@ -0,0 +1,3 @@ +from .nssubpkg import b + +print(b) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/nssubpkg/b.py b/python/testData/refactoring/move/relativeImportInsideNamespacePackage/before/src/nspkg/nssubpkg/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/__init__.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/a.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/a.py new file mode 100644 index 000000000000..37fb8093807e --- /dev/null +++ b/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nspkg/a.py @@ -0,0 +1,3 @@ +from nssubpkg import b + +print(b) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/__init__.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/b.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/after/src/nssubpkg/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/__init__.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/a.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/a.py new file mode 100644 index 000000000000..c6af594436cf --- /dev/null +++ b/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/a.py @@ -0,0 +1,3 @@ +from .nssubpkg import b + +print(b) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/__init__.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/b.py b/python/testData/refactoring/move/relativeImportInsideNormalPackage/before/src/nspkg/nssubpkg/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index 0e1a673b3e7f..b3570c0ff47a 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -174,6 +174,20 @@ public class PyMoveTest extends PyTestCase { }); } + // PY-14384 + public void testRelativeImportInsideNamespacePackage() { + runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() { + @Override + public void run() { + doMoveFileTest("nspkg/nssubpkg", ""); + } + }); + } + + // PY-14384 + public void testRelativeImportInsideNormalPackage() { + doMoveFileTest("nspkg/nssubpkg", ""); + } private void doMoveFileTest(String fileName, String toDirName) { Project project = myFixture.getProject(); From 1d1348d8a67df3f071fcf9a5c1cda25b57218f5d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 17 Nov 2014 19:18:06 +0300 Subject: [PATCH 19/75] Remove dots before relative import source when replacing reference to moved package/module For now we strive to replace relative imports with absolute imports during "Move" refactoring. If we replace reference in specific import element like in "from ..pkg import moved" we substitute import statement altogether with "..pkg" part. However if reference was in source part of relative import, e.g. "from ..moved import smth", previously we'd only replaced corresponding reference expression ("moved") and left preceding dots untouched, and that was wrong. --- .../refactoring/move/PyMoveFileHandler.java | 19 +++++++++++++++++++ .../after/src/pkg/__init__.py | 0 .../after/src/pkg/subpkg1/__init__.py | 0 .../after/src/pkg/subpkg1/a.py | 3 +++ .../after/src/subpkg2/__init__.py | 1 + .../before/src/pkg/__init__.py | 0 .../before/src/pkg/subpkg1/__init__.py | 0 .../before/src/pkg/subpkg1/a.py | 3 +++ .../before/src/pkg/subpkg2/__init__.py | 1 + .../python/refactoring/PyMoveTest.java | 4 ++++ 10 files changed, 31 insertions(+) create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/a.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/subpkg2/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/__init__.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/a.py create mode 100644 python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg2/__init__.py diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java index eb72940388c1..bf4d2623b070 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java @@ -29,6 +29,7 @@ import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyNames; +import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.actions.CreatePackageAction; import com.jetbrains.python.codeInsight.imports.PyImportOptimizer; @@ -119,6 +120,7 @@ public class PyMoveFileHandler extends MoveFileHandler { continue; } final QualifiedName newElementName = QualifiedNameFinder.findCanonicalImportPath(newElement, element); + removeLeadingDots(element); replaceWithQualifiedExpression(element, newElementName); } else if (element instanceof PyReferenceExpression) { @@ -157,6 +159,23 @@ public class PyMoveFileHandler extends MoveFileHandler { return oldElement; } + private static void removeLeadingDots(@NotNull PsiElement element) { + PsiElement lastDot = null; + PsiElement firstDot = null; + for (PsiElement prev = element.getPrevSibling(); prev != null; prev = prev.getPrevSibling()) { + if (prev.getNode().getElementType() != PyTokenTypes.DOT) { + break; + } + if (lastDot == null) { + lastDot = prev; + } + firstDot = prev; + } + if (lastDot != null && firstDot != null) { + element.getParent().deleteChildRange(firstDot, lastDot); + } + } + @Override public void updateMovedFile(PsiFile file) throws IncorrectOperationException { } diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/a.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/a.py new file mode 100644 index 000000000000..a8a924147fe9 --- /dev/null +++ b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/pkg/subpkg1/a.py @@ -0,0 +1,3 @@ +from subpkg2 import VAR + +print(VAR) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/subpkg2/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/subpkg2/__init__.py new file mode 100644 index 000000000000..0f1e78e3db76 --- /dev/null +++ b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/after/src/subpkg2/__init__.py @@ -0,0 +1 @@ +VAR = 'spam' \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/a.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/a.py new file mode 100644 index 000000000000..82c613b49f17 --- /dev/null +++ b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg1/a.py @@ -0,0 +1,3 @@ +from ..subpkg2 import VAR + +print(VAR) \ No newline at end of file diff --git a/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg2/__init__.py b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg2/__init__.py new file mode 100644 index 000000000000..0f1e78e3db76 --- /dev/null +++ b/python/testData/refactoring/move/relativeImportOfNameFromInitPy/before/src/pkg/subpkg2/__init__.py @@ -0,0 +1 @@ +VAR = 'spam' \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index b3570c0ff47a..2622ccf8c6e8 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -189,6 +189,10 @@ public class PyMoveTest extends PyTestCase { doMoveFileTest("nspkg/nssubpkg", ""); } + public void testRelativeImportOfNameFromInitPy() { + doMoveFileTest("pkg/subpkg2", ""); + } + private void doMoveFileTest(String fileName, String toDirName) { Project project = myFixture.getProject(); PsiManager manager = PsiManager.getInstance(project); From 37b46a53ec2156f8c082070c21c88849b7f68861 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Mon, 17 Nov 2014 20:16:30 +0300 Subject: [PATCH 20/75] @Nullable --- .../com/intellij/openapi/fileEditor/impl/EditorComposite.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index 781a7c4e419d..ef62fecea783 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java @@ -43,6 +43,7 @@ import com.intellij.ui.tabs.UiDecorator; import com.intellij.util.SmartList; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -268,6 +269,7 @@ public abstract class EditorComposite implements Disposable { * @return preferred focused component inside myEditor composite. Composite uses FocusWatcher to * track focus movement inside the myEditor. */ + @Nullable public JComponent getPreferredFocusedComponent(){ if (mySelectedEditor == null) return null; From 9c9e10b7790a7a099304b176da32637f92718882 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Mon, 17 Nov 2014 20:20:24 +0300 Subject: [PATCH 21/75] IDEA-132749 IAE at com.intellij.openapi.fileEditor.impl.EditorWindow.requestFocus [^vasya] --- .../openapi/fileEditor/impl/EditorWindow.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 91dfb648e49b..0537781bde07 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -554,14 +554,11 @@ public class EditorWindow { public void requestFocus(boolean forced) { if (myTabbedPane != null) { myTabbedPane.requestFocus(forced); - } else { + } + else { EditorWithProviderComposite editor = getSelectedEditor(); - if (editor != null) { - JComponent toFocus = editor.getPreferredFocusedComponent(); - IdeFocusManager.findInstanceByComponent(toFocus).requestFocus(toFocus, forced); - } else { - IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myPanel, forced); - } + JComponent preferred = editor == null ? null : editor.getPreferredFocusedComponent(); + IdeFocusManager.findInstanceByComponent(preferred == null ? myPanel : preferred).requestFocus(myPanel, forced); } } From 717f745cc0a07d1fe005e23800ab77b1f18132c8 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 17 Nov 2014 20:25:55 +0300 Subject: [PATCH 22/75] IDEA-133002 1 sec delay to edit "do not step into classes" in settings > Build, Exec, Deploy > Debugger > Stepping --- .../debugger/settings/DebuggerSteppingConfigurable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java index 914df8b14a83..5ec0450b8db7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java @@ -63,6 +63,7 @@ class DebuggerSteppingConfigurable implements ConfigurableUi { @Override public void apply(@NotNull DebuggerSettings settings) { + mySteppingFilterEditor.stopEditing(); getSettingsTo(settings); } @@ -83,7 +84,6 @@ class DebuggerSteppingConfigurable implements ConfigurableUi { settings.EVALUATE_FINALLY_ON_POP_FRAME = DebuggerSettings.EVALUATE_FINALLY_ASK; } - mySteppingFilterEditor.stopEditing(); settings.setSteppingFilters(mySteppingFilterEditor.getFilters()); } From 077151f6b0ae0aaceac32c79dd06f1a107fa1720 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 20:27:34 +0300 Subject: [PATCH 23/75] fixed connection error in ipython v 4 --- .../plugins/ipnb/protocol/IpnbConnection.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/protocol/IpnbConnection.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/protocol/IpnbConnection.java index f10e88856ef1..b5e1b94250ea 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/protocol/IpnbConnection.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/protocol/IpnbConnection.java @@ -23,6 +23,8 @@ public class IpnbConnection { private static final String API_URL = "/api"; private static final String KERNELS_URL = API_URL + "/kernels"; private static final String HTTP_POST = "POST"; + // TODO: Serialize cookies for the authentication message + private static final String authMessage = "{\"header\":{\"msg_id\":\"\", \"msg_type\":\"connect_request\"}, \"parent_header\":\"\", \"metadata\":{}}"; public static final String HTTP_DELETE = "DELETE"; @NotNull private final URI myURI; @@ -45,8 +47,6 @@ public class IpnbConnection { myKernelId = startKernel(); final Draft draft = new Draft17WithOrigin(); - // TODO: Serialize cookies for the authentication message - final String authMessage = "identity:foo"; myShellClient = new WebSocketClient(getShellURI(), draft) { @Override @@ -92,7 +92,7 @@ public class IpnbConnection { final PyOutContent content = gson.fromJson(msg.getContent(), PyOutContent.class); addCellOutput(content, myOutput); } - else if ("pyerr".equals(messageType)) { + else if ("pyerr".equals(messageType) || "error".equals(messageType)) { final PyErrContent content = gson.fromJson(msg.getContent(), PyErrContent.class); addCellOutput(content, myOutput); } @@ -100,7 +100,7 @@ public class IpnbConnection { final PyStreamContent content = gson.fromJson(msg.getContent(), PyStreamContent.class); addCellOutput(content, myOutput); } - else if ("pyin".equals(messageType)) { + else if ("pyin".equals(messageType) || "execute_input".equals(messageType)) { final JsonElement executionCount = msg.getContent().get("execution_count"); if (executionCount != null) { myExecCount = executionCount.getAsInt(); @@ -396,11 +396,12 @@ public class IpnbConnection { @SuppressWarnings("UnusedDeclaration") private static class PyStreamContent implements PyContent { + private String text; private String data; private String name; public String getData() { - return data; + return data == null ? text : data; } public String getName() { From a8c9a9e65dcbec4bcb890466d221f630c23dbe9b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 20:52:01 +0300 Subject: [PATCH 24/75] added icon for remote python sdk --- python/gen/icons/PythonIcons.java | 1 + .../com/jetbrains/python/RemoteInterpreter.png | Bin 0 -> 729 bytes .../jetbrains/python/RemoteInterpreter@2x.png | Bin 0 -> 1283 bytes 3 files changed, 1 insertion(+) create mode 100644 python/resources/icons/com/jetbrains/python/RemoteInterpreter.png create mode 100644 python/resources/icons/com/jetbrains/python/RemoteInterpreter@2x.png diff --git a/python/gen/icons/PythonIcons.java b/python/gen/icons/PythonIcons.java index f98387fedc29..f18ef6dfab36 100644 --- a/python/gen/icons/PythonIcons.java +++ b/python/gen/icons/PythonIcons.java @@ -52,6 +52,7 @@ public class PythonIcons { public static final Icon PythonConsole = load("/icons/com/jetbrains/python/pythonConsole.png"); // 16x16 public static final Icon PythonConsoleToolWindow = load("/icons/com/jetbrains/python/pythonConsoleToolWindow.png"); // 13x13 public static final Icon PythonTests = load("/icons/com/jetbrains/python/pythonTests.png"); // 16x16 + public static final Icon RemoteInterpreter = load("/icons/com/jetbrains/python/RemoteInterpreter.png"); // 16x16 public static final Icon TemplateRoot = load("/icons/com/jetbrains/python/templateRoot.png"); // 16x16 public static final Icon Virtualenv = load("/icons/com/jetbrains/python/virtualenv.png"); // 16x16 diff --git a/python/resources/icons/com/jetbrains/python/RemoteInterpreter.png b/python/resources/icons/com/jetbrains/python/RemoteInterpreter.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce74f45ed775a8401967abdf486499dbf256421 GIT binary patch literal 729 zcmV;~0w(>5P)F7xv7)Xpy6y~QkEfF*}CYaws?EbhmjkuF1mPj-t&Ivea?B$`FsGt=YQ}@@Um6A zqx0IPWAodAU!Y~c*oC<%UXFUtKLybeO^%@003=SO1|Yr01ZmYYB$ajpeiQ#yU>{=n z#7aBl$rXK&Qia8}gK)la1Tq?iA+_cq@THxVWX)EX!mvxtzQ?XA^G@Wb3Sy)kGC^5y zRZ@9hRSHG7rJ*FfZV1j*n;>4MrBe??0p+MM}4>5ZLJaS=J6pux}IaAgH3AcM85eo&C15EBh z1y!_R3n9hu(ZU6fAQE?uE9rr_QaAjP?ytzRSh;bIq1ZUfFVr+U=0Zn4JwF13wHeMI z!6}IbVs07WbdernWV%Q8i7=(p%&|J323xUL3zC6kuFoD8tcM^f(n#PRd9ppO_zOBGM6tr(af8d2p z>*t!+`2oSE^J7lXaJfr`;|^p3SwePgBk+dowD}5(%{Txd?dX01^!jhd{3o8C00000 LNkvXXu0mjf8WCF_ literal 0 HcmV?d00001 diff --git a/python/resources/icons/com/jetbrains/python/RemoteInterpreter@2x.png b/python/resources/icons/com/jetbrains/python/RemoteInterpreter@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..26e7c26c2670d126f1aa6d9fdb9268d158ded0a8 GIT binary patch literal 1283 zcmV+e1^oJnP)gS6Ei1)Kq|D9qs|Qp2o46w=>(N*;xrSpqyfg49ToLuF;H=~IO9r*M2yrFO2^0usGjmAGddEe*i^L?KqH30yV z|B}i7CV-PLHvrv5j}YjwgxZj=Q3E&$^MYKW#echr3c&qv(Yi<E7Gi0>IKfM z0UW~5Mxp_vMnLSq>*bLk1K+PIzz+{04JQc1bMf{!wGfnfnZ*bDKkOGgixv=he}t4M zRA&I3Ec%s*9N7MOE;vT!fn!uY#p$2~T=9DCjF*CYd1sT_Q8CH(Qk2c#=l$hgHG zf%#&O0}z_YSIb?j08X(IYGNN;TEDNWz%Q-(iFhQI{;{AGyt>fs01HYosenS2yB(HT z0bGw3gE#J*PimD>>`agq&v)6!&Ue}YKB*7{RYt4;Zn(!JfH8O_%YRFi#Pa9v*-gyd zB@<$RE(Z!J6FOJG^Q3$|%jgEmUB?*|)^gQPFxzh1J=?~I*>*n6ci7XYI>ZX#f+yYM z_(gp>Leq2XXWHz-rtjEh=`(Z3_Pd$e{O0MOZPW;+Z}ahM?X^(#h!w#3P$9T~S;m%7 zHl8mH<4(2mIwpVOf&qjC_7~2!+p%ccGs8+v2*xeA0B;!B2uOBW3CR`P;-JfkXRA&jqL%tN@0enDjaml*Ze(NhKo=q)t`0>4np;AIZ{ zT44^oWu}yVeD9N+J?<8qN6)Zs!FmCDq%W-?P&INvb(Nqr~+3r3r;%nYDL<*Tcp zsoTTY76Vs6W~S;c+KOLm0V7wqFw(%I4P%+KVZVLo>EU{<0Gc!KJepsvBhME$6ktHX z`M9&-#T5kWAwjx|whHwe!u^c;$_)jeLey{~l*OiFosump2=u_MGTo;qz$VnPb}I}H tV5rr}bOj*nR?h{!75{bsBAwAL{|BtW8P}@e)i(eD002ovPDHLkV1gV_Sp)z8 literal 0 HcmV?d00001 From a8eb18ba5ad4999db0c7ddba185ad16d59de9563 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 17 Nov 2014 20:52:49 +0300 Subject: [PATCH 25/75] use icon for remote python sdk in cell renderer --- .../jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java index 05f7c28f849a..51c617f93f82 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java @@ -18,8 +18,10 @@ package com.jetbrains.python.sdk.flavors; import com.google.common.collect.Lists; import com.intellij.openapi.util.text.StringUtil; import com.intellij.remote.RemoteFile; +import icons.PythonIcons; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.Collection; /** @@ -59,4 +61,9 @@ public class PyRemoteSdkFlavor extends CPythonSdkFlavor { private static String getExecutableName(String path) { return RemoteFile.createRemoteFile(path).getName(); } + + @Override + public Icon getIcon() { + return PythonIcons.Python.RemoteInterpreter; + } } From 0fac3a17ff60085daaee9bfc18a5d7c2440bb206 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Mon, 17 Nov 2014 21:18:07 +0300 Subject: [PATCH 26/75] enable Inspect in debugger for long string attributes --- .../jetbrains/python/debugger/PyDebugValue.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java index 26f81dddf56a..66eee2fb8a91 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java @@ -15,7 +15,7 @@ import javax.swing.*; // todo: null modifier for modify modules, class objects etc. public class PyDebugValue extends XNamedValue { private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.pydev.PyDebugValue"); - public static final int MAX_VALUE = 512; + public static final int MAX_VALUE = 256; private String myTempName = null; private final String myType; @@ -134,12 +134,23 @@ public class PyDebugValue extends XNamedValue { return "__len__".equals(name); } + private String getFullName() { + String result = myName; + PyDebugValue parent = myParent; + while (parent != null) { + result = "." + result; + result = parent.getName() + result; + parent = parent.getParent(); + } + return result; + } + @Override public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) { String value = PyTypeHandler.format(this); if (value.length() >= MAX_VALUE) { - node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, myName)); + node.setFullValueEvaluator(new PyFullValueEvaluator(myFrameAccessor, getFullName())); value = value.substring(0, MAX_VALUE); } From 9d088ce88e6725d1439c7f4222f7b23e621b9b42 Mon Sep 17 00:00:00 2001 From: Sergey Savenko Date: Mon, 17 Nov 2014 20:02:04 +0300 Subject: [PATCH 27/75] XmlSerializerImpl: do not cache uninitialized bindings --- .../util/src/com/intellij/util/xmlb/XmlSerializerImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index d693b722b56b..e42a7a50a532 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -116,7 +116,12 @@ class XmlSerializerImpl { if (binding == null) { binding = _getNonCachedClassBinding(aClass, accessor, originalType); map.put(key, binding); - binding.init(); + try { + binding.init(); + } catch (XmlSerializationException e) { + map.remove(key); + throw e; + } } return binding; } From 94728b736ce6df2dbae6c827fd320569a658e14b Mon Sep 17 00:00:00 2001 From: Alexey Gopachenko Date: Mon, 17 Nov 2014 19:33:22 +0100 Subject: [PATCH 28/75] Faster leaf node search CR-IU-897 --- .../psi/impl/source/tree/CompositeElement.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index f8bfc611ce55..c0b7d3352bb4 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -163,21 +163,28 @@ public class CompositeElement extends TreeElement { startFind: while (true) { TreeElement child = element.getFirstChildNode(); + TreeElement lastChild = element.getLastChildNode(); + boolean fwd = lastChild == null || (lastChild.getStartOffset() + lastChild.getTextLength() - child.getStartOffset()) / 2 > offset; + if (!fwd) { + child = lastChild; + offset = element.getTextLength() - offset; + } while (child != null) { final int textLength = child.getTextLength(); - if (textLength > offset) { + if (textLength > offset || !fwd && textLength >= offset) { if (child instanceof LeafElement) { if (child instanceof ForeignLeafPsiElement) { - child = child.getTreeNext(); + child = fwd ? child.getTreeNext() : child.getTreePrev(); continue; } return (LeafElement)child; } + offset = fwd ? offset : child.getTextLength() - offset; element = child; continue startFind; } offset -= textLength; - child = child.getTreeNext(); + child = fwd ? child.getTreeNext() : child.getTreePrev(); } return null; } From 939f5702ba095252e93719a4ebbc48c4fca5243e Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 17 Nov 2014 21:35:37 +0300 Subject: [PATCH 29/75] IDEA-131773 Fix mac shortcuts handling on Ubuntu --- platform/util/src/com/intellij/util/ui/UIUtil.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 97352ca3ef1a..d483e1301aa2 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -515,11 +515,7 @@ public class UIUtil { char c = e.getKeyChar(); if (c < 0x20 || c == 0x7F) return false; - if (SystemInfo.isMac) { - return !e.isMetaDown() && !e.isControlDown(); - } - - return !e.isAltDown() && !e.isControlDown(); + return !e.isMetaDown() && !e.isAltDown() && !e.isControlDown(); } public static int getStringY(@NotNull final String string, @NotNull final Rectangle bounds, @NotNull final Graphics2D g) { From b2d8421c93a5f61f1be3b53b42aaf4aaa487ca87 Mon Sep 17 00:00:00 2001 From: Alexey Gopachenko Date: Mon, 17 Nov 2014 19:49:13 +0100 Subject: [PATCH 30/75] Reduce Injection-related passes overhead, esp. for big files with not much injections CR-IU-894 --- .../impl/InjectedGeneralHighlightingPass.java | 11 ++++++++--- .../codeInsight/daemon/impl/LineMarkersPass.java | 14 ++++++++++---- .../tree/injected/InjectedLanguageManagerImpl.java | 8 ++++++++ .../source/tree/injected/InjectedLanguageUtil.java | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java index fbab8ef759aa..a9b3cff485fc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java @@ -38,9 +38,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.injected.Place; import com.intellij.psi.tree.IElementType; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -80,6 +82,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp final List outside = new ArrayList(); List insideRanges = new ArrayList(); List outsideRanges = new ArrayList(); + //TODO: this thing is just called TWICE with same arguments eating CPU on huge files :( Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, insideRanges, outside, outsideRanges, false, FILE_FILTER); @@ -148,7 +151,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp final Set outInjected = new THashSet(); List injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile); - Collection hosts = new THashSet(elements1.size() + elements2.size() + injected.size()); + final Collection hosts = new THashSet(elements1.size() + elements2.size() + injected.size()); //rehighlight all injected PSI regardless the range, //since change in one place can lead to invalidation of injected PSI in (completely) other place. @@ -165,8 +168,10 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp hosts.add(context); } } - hosts.addAll(elements1); - hosts.addAll(elements2); + InjectedLanguageManagerImpl injectedLanguageManager = InjectedLanguageManagerImpl.getInstanceImpl(myProject); + Processor collectInjectableProcessor = new CommonProcessors.CollectProcessor(hosts); + injectedLanguageManager.processInjectableElements(elements1, collectInjectableProcessor); + injectedLanguageManager.processInjectableElements(elements2, collectInjectableProcessor); final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java index 19a247f4a4a1..530e979d1db0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java @@ -48,9 +48,11 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Function; import com.intellij.util.FunctionUtil; +import com.intellij.util.Processor; import gnu.trove.THashSet; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; @@ -201,7 +203,7 @@ public class LineMarkersPass extends TextEditorHighlightingPass implements LineM public static void collectLineMarkersForInjected(@NotNull final List result, @NotNull List elements, @NotNull final LineMarkersProcessor processor, - @NotNull PsiFile file, + @NotNull final PsiFile file, @NotNull final ProgressIndicator progress) { final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject()); final List injectedMarkers = new ArrayList(); @@ -213,9 +215,13 @@ public class LineMarkersPass extends TextEditorHighlightingPass implements LineM injectedFiles.add(injectedPsi); } }; - for (int i = 0, size = elements.size(); i < size; ++i) { - InjectedLanguageUtil.enumerate(elements.get(i), file, false, collectingVisitor); - } + InjectedLanguageManagerImpl.getInstanceImpl(file.getProject()).processInjectableElements(elements, new Processor() { + @Override + public boolean process(PsiElement element) { + InjectedLanguageUtil.enumerate(element, file, false, collectingVisitor); + return true; + } + }); for (PsiFile injectedPsi : injectedFiles) { final Project project = injectedPsi.getProject(); Document document = PsiDocumentManager.getInstance(project).getCachedDocument(injectedPsi); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java index 34b8f9b06ef8..b2c7d1411fdb 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java @@ -228,6 +228,14 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme private final Set myManualInjectors = Collections.synchronizedSet(new LinkedHashSet()); private volatile ClassMapCachingNulls cachedInjectors; + public void processInjectableElements(Collection in, Processor processor) { + ClassMapCachingNulls map = getInjectorMap(); + for (PsiElement element : in) { + if (map.get(element.getClass()) != null) + processor.process(element); + } + } + private ClassMapCachingNulls getInjectorMap() { ClassMapCachingNulls cached = cachedInjectors; if (cached != null) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 5ed96453c85e..96f318b3e72b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -307,7 +307,7 @@ public class InjectedLanguageUtil { MultiHostRegistrarImpl registrar = null; PsiElement current = element; nextParent: - while (current != null && current != hostPsiFile) { + while (current != null && current != hostPsiFile && !(current instanceof PsiDirectory)) { ProgressManager.checkCanceled(); if ("EL".equals(current.getLanguage().getID())) break; ParameterizedCachedValue data = current.getUserData(INJECTED_PSI); From bc2e9a17c27fec7e42a9a749ba44202e305fefbe Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 17 Nov 2014 17:54:12 +0100 Subject: [PATCH 31/75] external coverage: load vcs file content if local history is obsolete (IDEA-89576) --- plugins/coverage-common/coverage-common.iml | 4 +- .../intellij/coverage/SrcFileAnnotator.java | 53 ++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/plugins/coverage-common/coverage-common.iml b/plugins/coverage-common/coverage-common.iml index 389fc6b1bd7e..3217ead3d827 100644 --- a/plugins/coverage-common/coverage-common.iml +++ b/plugins/coverage-common/coverage-common.iml @@ -30,6 +30,6 @@ + - - + \ No newline at end of file diff --git a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java index c327d760e10d..8b79d0047e4d 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java +++ b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java @@ -34,6 +34,13 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.LineTokenizer; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.actions.VcsContextFactory; +import com.intellij.openapi.vcs.history.VcsFileRevision; +import com.intellij.openapi.vcs.history.VcsHistoryProvider; +import com.intellij.openapi.vcs.history.VcsHistorySession; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.reference.SoftReference; @@ -46,11 +53,13 @@ import com.intellij.util.Alarm; import com.intellij.util.Function; import com.intellij.util.diff.Diff; import com.intellij.util.diff.FilesTooBigForDiffException; +import com.intellij.vcsUtil.VcsUtil; import gnu.trove.TIntIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.util.*; /** @@ -194,11 +203,16 @@ public class SrcFileAnnotator implements Disposable { synchronized (LOCK) { if (myOldContent == null) { if (ApplicationManager.getApplication().isDispatchThread()) return null; - final byte[] byteContent = LocalHistory.getInstance().getByteContent(f, new FileRevisionTimestampComparator() { + final LocalHistory localHistory = LocalHistory.getInstance(); + byte[] byteContent = localHistory.getByteContent(f, new FileRevisionTimestampComparator() { public boolean isSuitable(long revisionTimestamp) { return revisionTimestamp < date; } }); + + if (byteContent == null && f.getTimeStamp() > date) { + byteContent = loadFromVersionControl(date, f); + } myOldContent = new SoftReference(byteContent); } oldContent = myOldContent.get(); @@ -211,7 +225,7 @@ public class SrcFileAnnotator implements Disposable { String[] oldLines = oldToNew ? coveredLines : currentLines; String[] newLines = oldToNew ? currentLines : coveredLines; - Diff.Change change = null; + Diff.Change change; try { change = Diff.buildChanges(oldLines, newLines); } @@ -222,6 +236,41 @@ public class SrcFileAnnotator implements Disposable { return new SoftReference(getCoverageVersionToCurrentLineMapping(change, oldLines.length)); } + @Nullable + private byte[] loadFromVersionControl(long date, VirtualFile f) { + try { + final AbstractVcs vcs = VcsUtil.getVcsFor(myProject, f); + if (vcs == null) return null; + + final VcsHistoryProvider historyProvider = vcs.getVcsHistoryProvider(); + if (historyProvider == null) return null; + + final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(f); + final VcsHistorySession session = historyProvider.createSessionFor(filePath); + if (session == null) return null; + + final List list = session.getRevisionList(); + + if (list != null) { + for (VcsFileRevision revision : list) { + final Date revisionDate = revision.getRevisionDate(); + if (revisionDate == null) { + return null; + } + + if (revisionDate.getTime() < date) { + return revision.loadContent(); + } + } + } + } + catch (Exception e) { + LOG.info(e); + return null; + } + return null; + } + public void showCoverageInformation(final CoverageSuitesBundle suite) { if (myEditor == null || myFile == null) return; final MarkupModel markupModel = DocumentMarkupModel.forDocument(myDocument, myProject, true); From 62a23236ba1579d40d1791b294cda8947c1b2873 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 17 Nov 2014 18:14:37 +0100 Subject: [PATCH 32/75] prefer project from current context over first opened project --- .../intellij/openapi/project/ProjectUtil.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java index cc01782b7541..0dac0d7d3b0c 100644 --- a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java @@ -115,16 +115,21 @@ public class ProjectUtil { } @NotNull - public static Project guessCurrentProject(JComponent component) { + public static Project guessCurrentProject(@Nullable JComponent component) { Project project = null; - Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); - if (openProjects.length > 0) project = openProjects[0]; - if (project == null) { - DataContext dataContext = component == null ? DataManager.getInstance().getDataContext() : DataManager.getInstance().getDataContext(component); - project = CommonDataKeys.PROJECT.getData(dataContext); + if (component != null) { + project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(component)); } if (project == null) { - project = ProjectManager.getInstance().getDefaultProject(); + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + if (openProjects.length > 0) project = openProjects[0]; + if (project == null) { + DataContext dataContext = DataManager.getInstance().getDataContext(); + project = CommonDataKeys.PROJECT.getData(dataContext); + } + if (project == null) { + project = ProjectManager.getInstance().getDefaultProject(); + } } return project; } From 44c89fb317a607b0e5b7322ab7c745ff127d3de5 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 17 Nov 2014 18:44:44 +0100 Subject: [PATCH 33/75] configure annotations button: guess project after creation (IDEA-132950) --- .../deadCode/UnusedDeclarationInspection.java | 19 ++----------------- .../ex/EntryPointsManagerImpl.java | 7 ++++++- .../UnusedParametersInspection.java | 5 ++--- .../codeInspection/ex/EntryPointsManager.java | 6 ++++++ 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java index ef5544775adb..b01ca0a8039b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java @@ -15,14 +15,11 @@ */ package com.intellij.codeInspection.deadCode; -import com.intellij.codeInspection.GlobalInspectionContext; import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.ex.EntryPointsManager; +import com.intellij.codeInspection.ex.EntryPointsManagerImpl; import com.intellij.codeInspection.reference.EntryPoint; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.ui.components.JBTabbedPane; import org.jetbrains.annotations.TestOnly; @@ -53,17 +50,6 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase return tabs; } - private Project guessProject() { - final GlobalInspectionContext context = getContext(); - Project project = context == null ? null : context.getProject(); - - if (project == null) { - Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); - project = openProjects.length == 0 ? ProjectManager.getInstance().getDefaultProject() : openProjects[0]; - } - return project; - } - private class OptionsPanel extends JPanel { private final JCheckBox myMainsCheckbox; private final JCheckBox myAppletToEntries; @@ -141,8 +127,7 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase gc.gridy++; add(myNonJavaCheckbox, gc); - Project project = guessProject(); - JButton configureAnnotations = EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(); + JButton configureAnnotations = EntryPointsManagerImpl.createConfigureAnnotationsButton(); gc.fill = GridBagConstraints.NONE; gc.gridy++; gc.insets.top = 10; diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java index 209f7ef827fb..2ef2dc12829b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java @@ -28,6 +28,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInspection.util.SpecialAnnotationsUtil; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.ui.DialogWrapper; import org.jdom.Element; @@ -73,11 +74,15 @@ public class EntryPointsManagerImpl extends EntryPointsManagerBase implements Pe @Override public JButton createConfigureAnnotationsBtn() { + return createConfigureAnnotationsButton(); + } + + public static JButton createConfigureAnnotationsButton() { final JButton configureAnnotations = new JButton("Configure annotations..."); configureAnnotations.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - configureAnnotations(); + getInstance(ProjectUtil.guessCurrentProject(configureAnnotations)).configureAnnotations(); } }); return configureAnnotations; diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java index bb97f5cd78d5..9e1f28254b65 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java @@ -29,10 +29,10 @@ import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.EntryPointsManager; +import com.intellij.codeInspection.ex.EntryPointsManagerImpl; import com.intellij.codeInspection.reference.*; import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.search.PsiReferenceProcessor; @@ -234,8 +234,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool { @Override public JComponent createOptionsPanel() { final JPanel panel = new JPanel(new GridBagLayout()); - Project project = ProjectUtil.guessCurrentProject(panel); - panel.add(EntryPointsManager.getInstance(project).createConfigureAnnotationsBtn(), + panel.add(EntryPointsManagerImpl.createConfigureAnnotationsButton(), new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); return panel; diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/EntryPointsManager.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/EntryPointsManager.java index 14a9002d109c..02f3f3cfac1a 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/ex/EntryPointsManager.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/EntryPointsManager.java @@ -29,6 +29,8 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public abstract class EntryPointsManager implements Disposable { public static EntryPointsManager getInstance(Project project) { @@ -50,6 +52,10 @@ public abstract class EntryPointsManager implements Disposable { public abstract void configureAnnotations(); + /** + * {@link com.intellij.codeInspection.ex.EntryPointsManagerImpl#createConfigureAnnotationsButton()} should be used instead + */ + @Deprecated public abstract JButton createConfigureAnnotationsBtn(); public abstract boolean isEntryPoint(@NotNull PsiElement element); From 10846bc7c47add60b03d9da73248e25dcca4d767 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 17 Nov 2014 19:47:17 +0100 Subject: [PATCH 34/75] field may be local: ignore all fields referenced by qualifier (IDEA-133017) --- .../FieldCanBeLocalInspectionBase.java | 15 +++++++++++++++ .../fieldReferencedFromAnotherObject/expected.xml | 9 +++++++++ .../src/Test.java | 15 +++++++++++++++ .../codeInspection/FieldCanBeLocalTest.java | 1 + 4 files changed, 40 insertions(+) create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/expected.xml create mode 100644 java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/src/Test.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java index e13f3e66a198..d2dfb1f5c6a8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspectionBase.java @@ -31,6 +31,8 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Processor; @@ -75,6 +77,19 @@ public class FieldCanBeLocalInspectionBase extends BaseJavaBatchLocalInspectionT for (final PsiField field : candidates) { if (usedFields.contains(field) && !hasImplicitReadOrWriteUsage(field, implicitUsageProviders)) { + if (!ReferencesSearch.search(field, new LocalSearchScope(aClass)).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + if (element instanceof PsiReferenceExpression) { + final PsiElement qualifier = ((PsiReferenceExpression)element).getQualifier(); + return qualifier == null || qualifier instanceof PsiThisExpression && ((PsiThisExpression)qualifier).getQualifier() == null; + } + return true; + } + })) { + continue; + } final String message = InspectionsBundle.message("inspection.field.can.be.local.problem.descriptor"); final ArrayList fixes = new ArrayList(); SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor() { diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/expected.xml b/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/expected.xml new file mode 100644 index 000000000000..28a09cdef54c --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/expected.xml @@ -0,0 +1,9 @@ + + + + Test.java + 3 + Field can be local + Field can be converted to a local variable + + diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/src/Test.java b/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/src/Test.java new file mode 100644 index 000000000000..3ea480d779c9 --- /dev/null +++ b/java/java-tests/testData/inspection/fieldCanBeLocal/fieldReferencedFromAnotherObject/src/Test.java @@ -0,0 +1,15 @@ +class G { + private G foo; + private int bar; + + public G(final G gFoo) { + foo = gFoo; + bar = 1; + System.out.println(this.bar); + + G g = this; + while (g.foo != null) { + g = g.foo; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java index db303c699ddc..3470669e2dfe 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java @@ -39,6 +39,7 @@ public class FieldCanBeLocalTest extends InspectionTestCase { public void testFieldWithImmutableType() throws Exception {doTest();} public void testFieldUsedForWritingInLambda() throws Exception {doTest();} public void testStaticQualifiedFieldAccessForWriting() throws Exception {doTest();} + public void testFieldReferencedFromAnotherObject() throws Exception {doTest();} public void testIgnoreAnnotated() throws Exception { final FieldCanBeLocalInspection inspection = new FieldCanBeLocalInspection(); doTestConfigured(inspection); From bdb37fdc9ab9245028ee0ac84a3a21d77c80f647 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 17 Nov 2014 19:55:36 +0100 Subject: [PATCH 35/75] Calculate icon under progress, cancellable with pending write action (IDEA-132991) --- .../src/com/intellij/ui/DeferredIconImpl.java | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java index 2cb330c71114..d01aa1c06faa 100644 --- a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java @@ -22,10 +22,15 @@ package com.intellij.ui; import com.intellij.concurrency.Job; import com.intellij.concurrency.JobLauncher; import com.intellij.ide.PowerSaveMode; +import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.IndexNotReadyException; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.tabs.impl.TabLabel; import com.intellij.util.Alarm; @@ -119,18 +124,43 @@ public class DeferredIconImpl implements DeferredIcon { final long startTime = System.currentTimeMillis(); if (myNeedReadAction) { - if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() { + final ProgressIndicatorBase progress = new ProgressIndicatorBase(); + final ApplicationAdapter listener = new ApplicationAdapter() { + @Override + public void beforeWriteActionStart(Object action) { + progress.cancel(); + } + }; + ApplicationManager.getApplication().invokeAndWait(new Runnable() { @Override public void run() { - IconDeferrerImpl.evaluateDeferred(evalRunnable); - if (myAutoUpdatable) { - myLastCalcTime = System.currentTimeMillis(); - myLastTimeSpent = myLastCalcTime - startTime; - } + ApplicationManager.getApplication().addApplicationListener(listener); } - })) { - myIsScheduled = false; - return; + }, ModalityState.any()); + try { + final Ref cancelled = new Ref(); + ProgressManager.getInstance().runProcess(new Runnable() { + @Override + public void run() { + if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() { + @Override + public void run() { + IconDeferrerImpl.evaluateDeferred(evalRunnable); + if (myAutoUpdatable) { + myLastCalcTime = System.currentTimeMillis(); + myLastTimeSpent = myLastCalcTime - startTime; + } + } + })) { + myIsScheduled = false; + cancelled.set(Boolean.TRUE); + } + } + }, progress); + if (cancelled.get() == Boolean.TRUE) return; + } catch(ProcessCanceledException e) {} + finally { + ApplicationManager.getApplication().removeApplicationListener(listener); } } else { From ee666e691d219f05382f1a76958501aa0eebfe1b Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 17 Nov 2014 20:57:46 +0300 Subject: [PATCH 36/75] Update display name and description of 'expand live template' action --- .../src/messages/ActionsBundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 138a5e3b60b5..ca93464c5653 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -523,8 +523,8 @@ action.ClassNameCompletion.description=Complete class name and add import for it action.InsertLiveTemplate.text=Insert Live _Template... action.InsertLiveTemplate.description=Show popup list of live templates starting with the specified prefix action.ExpandLiveTemplateByTab.text=Expand Live Template by Tab -action.ExpandLiveTemplateCustom.text=Expand Live Template -action.ExpandLiveTemplateCustom.description=Invoke the live template with the prefix typed in the editor +action.ExpandLiveTemplateCustom.text=Expand Live Template / Emmet Abbreviation +action.ExpandLiveTemplateCustom.description=Invoke the live template that bound to 'Custom shortcut' with the prefix typed in the editor action.SurroundWithLiveTemplate.text=Surround with Live Tem_plate... action.SurroundWithLiveTemplate.description=Surrounds the selection with one of the template action.CommentByLineComment.text=Comment with _Line Comment From 7b5a901c7ddd70956a7211035636485b91cf9314 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 17 Nov 2014 22:04:46 +0300 Subject: [PATCH 37/75] Weaken instanceof on delete it fixes the situation when ASTDelegatePsiElement is placed inside LazyParseableElement --- .../intellij/extapi/psi/ASTDelegatePsiElement.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java index fbcb7afc0731..6cbb68219ef2 100644 --- a/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java +++ b/platform/core-impl/src/com/intellij/extapi/psi/ASTDelegatePsiElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -32,7 +32,10 @@ import com.intellij.psi.impl.PsiElementBase; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; -import com.intellij.psi.impl.source.tree.*; +import com.intellij.psi.impl.source.tree.ChangeUtil; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.SharedImplUtil; +import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtilCore; @@ -334,9 +337,9 @@ public abstract class ASTDelegatePsiElement extends PsiElementBase { CheckUtil.checkWritable(this); ((ASTDelegatePsiElement)parent).deleteChildInternal(getNode()); } - else if (parent instanceof CompositePsiElement) { + else if (parent instanceof CompositeElement) { CheckUtil.checkWritable(this); - ((CompositePsiElement)parent).deleteChildInternal(getNode()); + ((CompositeElement)parent).deleteChildInternal(getNode()); } else if (parent instanceof PsiFile) { CheckUtil.checkWritable(this); From ba0cba456e7c9ec20645c96888306234cbcb11e4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 17 Nov 2014 20:14:42 +0100 Subject: [PATCH 38/75] invert if: stop at lambda level (IDEA-133023) --- .../intention/impl/InvertIfConditionAction.java | 3 ++- .../invertIfCondition/afterInsideLambda.java | 13 +++++++++++++ .../invertIfCondition/beforeInsideLambda.java | 11 +++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/invertIfCondition/afterInsideLambda.java create mode 100644 java/java-tests/testData/codeInsight/invertIfCondition/beforeInsideLambda.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java index 9815601a16c9..6815ca94c9df 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InvertIfConditionAction.java @@ -158,8 +158,9 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction { } private static PsiElement findCodeBlock(PsiIfStatement ifStatement) { - PsiElement e = PsiTreeUtil.getParentOfType(ifStatement, PsiMethod.class, PsiClassInitializer.class); + PsiElement e = PsiTreeUtil.getParentOfType(ifStatement, PsiMethod.class, PsiClassInitializer.class, PsiLambdaExpression.class); if (e instanceof PsiMethod) return ((PsiMethod) e).getBody(); + if (e instanceof PsiLambdaExpression) return ((PsiLambdaExpression)e).getBody(); if (e instanceof PsiClassInitializer) return ((PsiClassInitializer) e).getBody(); return null; } diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterInsideLambda.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterInsideLambda.java new file mode 100644 index 000000000000..0c58356b054b --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterInsideLambda.java @@ -0,0 +1,13 @@ +// "Invert If Condition" "true" +class A { + public void foo() { + Runnable r = () -> { + if (System.currentTimeMillis() <= 1) { + System.err.println("Elvis lives"); + } + else { + return; + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/beforeInsideLambda.java b/java/java-tests/testData/codeInsight/invertIfCondition/beforeInsideLambda.java new file mode 100644 index 000000000000..85aa03f9edac --- /dev/null +++ b/java/java-tests/testData/codeInsight/invertIfCondition/beforeInsideLambda.java @@ -0,0 +1,11 @@ +// "Invert If Condition" "true" +class A { + public void foo() { + Runnable r = () -> { + if (System.currentTimeMillis() > 1) { + return; + } + System.err.println("Elvis lives"); + }; + } +} \ No newline at end of file From 93c98d2e432d9b77c238ced975d721f64cd1b4e6 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 17 Nov 2014 19:26:57 +0100 Subject: [PATCH 39/75] don't decompile super classes when overriding their methods --- .../src/com/intellij/ide/util/MemberChooser.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java index 2ced07e8e3a6..2addc59170b4 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java +++ b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java @@ -27,6 +27,8 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiCompiledElement; +import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.ui.*; @@ -904,8 +906,11 @@ public class MemberChooser extends DialogWrapper implemen @Override public int compare(ElementNode n1, ElementNode n2) { if (n1.getDelegate() instanceof ClassMemberWithElement && n2.getDelegate() instanceof ClassMemberWithElement) { - return ((ClassMemberWithElement)n1.getDelegate()).getElement().getTextOffset() - - ((ClassMemberWithElement)n2.getDelegate()).getElement().getTextOffset(); + PsiElement element1 = ((ClassMemberWithElement)n1.getDelegate()).getElement(); + PsiElement element2 = ((ClassMemberWithElement)n2.getDelegate()).getElement(); + if (!(element1 instanceof PsiCompiledElement) && !(element2 instanceof PsiCompiledElement)) { + return element1.getTextOffset() - element2.getTextOffset(); + } } return n1.getOrder() - n2.getOrder(); } From 43774da42d8076e7e1e818e2d9e51b06f468a114 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 17 Nov 2014 19:39:11 +0100 Subject: [PATCH 40/75] fix UI leak after pressing Enter in a speed search --- .../openapi/wm/ex/ToolWindowManagerEx.java | 2 ++ .../wm/impl/ToolWindowHeadlessManagerImpl.java | 4 ++++ .../openapi/wm/impl/ToolWindowManagerImpl.java | 5 +++++ .../src/com/intellij/ui/SpeedSearchBase.java | 14 +++++++++----- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java index 2bff2a10d5cd..d8414ddc37ed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.wm.ex; +import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.wm.ToolWindowAnchor; @@ -35,6 +36,7 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager { } public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l); + public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable); public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l); /** diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java index 5fa360235cb2..24e04e100369 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java @@ -217,6 +217,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } + @Override + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { + } + @Override public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 8acebb5b5bfd..598d13fcb830 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -566,6 +566,11 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myDispatcher.addListener(l); } + @Override + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { + myDispatcher.addListener(l, parentDisposable); + } + @Override public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { myDispatcher.removeListener(l); diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index 76985ad77362..6f20a456c4c7 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -18,6 +18,7 @@ package com.intellij.ui; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; import com.intellij.ide.ui.UISettings; +import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -25,6 +26,7 @@ import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; @@ -65,6 +67,7 @@ public abstract class SpeedSearchBase extends SpeedSear private boolean myClearSearchOnNavigateNoMatch = false; @NonNls protected static final String ENTERED_PREFIX_PROPERTY_NAME = "enteredPrefix"; + private Disposable myListenerDisposable; public SpeedSearchBase(Comp component) { myComponent = component; @@ -522,10 +525,9 @@ public abstract class SpeedSearchBase extends SpeedSear myPopupLayeredPane.validate(); myPopupLayeredPane.repaint(); myPopupLayeredPane = null; - - if (project != null) { - ((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).removeToolWindowManagerListener(myWindowManagerListener); - } + + Disposer.dispose(myListenerDisposable); + myListenerDisposable = null; } else if (searchPopup != null) { FeatureUsageTracker.getInstance().triggerFeatureUsed("ui.tree.speedsearch"); @@ -543,7 +545,9 @@ public abstract class SpeedSearchBase extends SpeedSear if (mySearchPopup == null || !myComponent.isDisplayable()) return; if (project != null) { - ((ToolWindowManagerEx)ToolWindowManager.getInstance(project)).addToolWindowManagerListener(myWindowManagerListener); + myListenerDisposable = Disposer.newDisposable(); + ToolWindowManagerEx toolWindowManager = (ToolWindowManagerEx)ToolWindowManager.getInstance(project); + toolWindowManager.addToolWindowManagerListener(myWindowManagerListener, myListenerDisposable); } JRootPane rootPane = myComponent.getRootPane(); if (rootPane != null) { From 9ea0186933e7eb2ec7fd6a5966b52c1b222eeebd Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 17 Nov 2014 20:14:40 +0100 Subject: [PATCH 41/75] fix UI leak via contents of FrameWrapper that stayed forever in Window.allWindows --- .../platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java index c6e037e5d30e..0b1789faf66d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/FrameWrapper.java @@ -218,6 +218,8 @@ public class FrameWrapper implements Disposable, DataProvider { myStatusBar = null; } + frame.dispose(); + myDisposed = true; } From dede69b0ee3cf658cf24fceb329d6553dfb65962 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 17 Nov 2014 20:20:18 +0100 Subject: [PATCH 42/75] when possible, build method hierarchy only for specific names --- .../psi/impl/PsiSuperMethodImplUtil.java | 101 ++++++------------ 1 file changed, 30 insertions(+), 71 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 87a45bf8cdeb..e5ae3926e4ca 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -28,6 +28,8 @@ import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; import com.intellij.util.*; +import com.intellij.util.containers.ConcurrentFactoryMap; +import com.intellij.util.containers.FactoryMap; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; @@ -43,7 +45,20 @@ public class PsiSuperMethodImplUtil { @NotNull @Override public Map fun(PsiClass dom) { - return buildMethodHierarchy(dom, PsiSubstitutor.EMPTY, true, new THashSet(), false); + return buildMethodHierarchy(dom, null, PsiSubstitutor.EMPTY, true, new THashSet(), false); + } + }); + private static final PsiCacheKey>, PsiClass> SIGNATURES_BY_NAME_KEY = PsiCacheKey + .create("SIGNATURES_BY_NAME_KEY", new Function>>() { + @Override + public FactoryMap> fun(final PsiClass psiClass) { + return new ConcurrentFactoryMap>() { + @Nullable + @Override + protected Map create(String methodName) { + return buildMethodHierarchy(psiClass, methodName, PsiSubstitutor.EMPTY, true, new THashSet(), false); + } + }; } }); @@ -112,6 +127,7 @@ public class PsiSuperMethodImplUtil { @NotNull private static Map buildMethodHierarchy(@NotNull PsiClass aClass, + @Nullable String nameHint, @NotNull PsiSubstitutor substitutor, final boolean includePrivates, @NotNull final Set visited, @@ -144,7 +160,7 @@ public class PsiSuperMethodImplUtil { }); PsiMethod[] methods = aClass.getMethods(); - if (aClass instanceof PsiClassImpl) { + if ((nameHint == null || "values".equals(nameHint)) && aClass instanceof PsiClassImpl) { final PsiMethod valuesMethod = ((PsiClassImpl)aClass).getValuesMethod(); if (valuesMethod != null) { methods = ArrayUtil.append(methods, valuesMethod); @@ -155,6 +171,7 @@ public class PsiSuperMethodImplUtil { if (!method.isValid()) { throw new PsiInvalidElementAccessException(method, "class.valid=" + aClass.isValid() + "; name=" + method.getName()); } + if (nameHint != null && !nameHint.equals(method.getName())) continue; if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue; final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext); HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature); @@ -180,7 +197,7 @@ public class PsiSuperMethodImplUtil { PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext); final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0; - Map superResult = buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper); + Map superResult = buildMethodHierarchy(superClass, nameHint, finalSubstitutor, false, visited, isInRawContextSuper); visited.remove(superClass); List> flattened = new ArrayList>(); @@ -366,7 +383,7 @@ public class PsiSuperMethodImplUtil { PsiClass aClass = method.getContainingClass(); HierarchicalMethodSignature result = null; if (aClass != null) { - result = getSignaturesMap(aClass).get(method.getSignature(PsiSubstitutor.EMPTY)); + result = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName()).get(method.getSignature(PsiSubstitutor.EMPTY)); } if (result == null) { result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY)); @@ -395,40 +412,14 @@ public class PsiSuperMethodImplUtil { if (!canHaveSuperMethod(method, true, false)) return false; - Map cachedMap = SIGNATURES_FOR_CLASS_KEY.getCachedValueOrNull(aClass); - if (cachedMap != null) { - HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY)); - if (signature != null) { - List superSignatures = signature.getSuperSignatures(); - for (HierarchicalMethodSignature superSignature : superSignatures) { - if (!superMethodProcessor.process(superSignature.getMethod())) return false; - } - return true; + Map cachedMap = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName()); + HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY)); + if (signature != null) { + List superSignatures = signature.getSuperSignatures(); + for (HierarchicalMethodSignature superSignature : superSignatures) { + if (!superMethodProcessor.process(superSignature.getMethod())) return false; } } - - PsiClassType[] directSupers = aClass.getSuperTypes(); - for (PsiClassType directSuper : directSupers) { - PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics(); - if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) { - // generics - break; - } - PsiClass directSuperClass = resolveResult.getElement(); - if (directSuperClass == null) continue; - PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false); - for (PsiMethod candidate : candidates) { - if (PsiUtil.canBeOverriden(candidate)) { - if (!superMethodProcessor.process(candidate)) return false; - } - } - return true; - } - - List superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures(); - for (HierarchicalMethodSignature superSignature : superSignatures) { - if (!superMethodProcessor.process(superSignature.getMethod())) return false; - } return true; } @@ -444,42 +435,10 @@ public class PsiSuperMethodImplUtil { if (!canHaveSuperMethod(method, true, false)) return false; - PsiMethod[] superMethods = null; - Map cachedMap = SIGNATURES_FOR_CLASS_KEY.getCachedValueOrNull(aClass); - if (cachedMap != null) { - HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY)); - if (signature != null) { - superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures()); - } - } - if (superMethods == null) { - PsiClassType[] directSupers = aClass.getSuperTypes(); - List found = null; - boolean canceled = false; - for (PsiClassType directSuper : directSupers) { - PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics(); - if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) { - // generics - canceled = true; - break; - } - PsiClass directSuperClass = resolveResult.getElement(); - if (directSuperClass == null) continue; - PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false); - if (candidates.length != 0) { - if (found == null) found = new ArrayList(); - for (PsiMethod candidate : candidates) { - if (PsiUtil.canBeOverriden(candidate)) found.add(candidate); - } - } - } - superMethods = canceled ? null : found == null ? PsiMethod.EMPTY_ARRAY : found.toArray(new PsiMethod[found.size()]); - } - if (superMethods == null) { - superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(method.getHierarchicalMethodSignature().getSuperSignatures()); - } + Map cachedMap = SIGNATURES_BY_NAME_KEY.getValue(aClass).get(method.getName()); + HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY)); - for (PsiMethod superCandidate : superMethods) { + for (PsiMethod superCandidate : MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures())) { if (superMethod.equals(superCandidate) || isSuperMethodSmart(superCandidate, superMethod)) return true; } return false; From 0a411c19604852277ae8cd81cb6702c83081fcea Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 18 Nov 2014 01:02:36 +0300 Subject: [PATCH 43/75] PY-14365 Do not show object and __Classobj in AutoImportQuickFix Excluded them from the list of base classes that may be shown in description and list items in the quick fix UI. --- .../imports/ImportCandidateHolder.java | 20 +++++++++++-------- .../main.py | 1 + .../module.py | 2 ++ .../com/jetbrains/python/PyQuickFixTest.java | 10 ++++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/main.py create mode 100644 python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/module.py diff --git a/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java b/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java index e62910144b45..a5c9a10d0454 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java @@ -25,10 +25,14 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.util.QualifiedName; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * An immutable holder of information for one auto-import candidate. *

@@ -131,15 +135,15 @@ class ImportCandidateHolder implements Comparable { sb.append(((PyFunction)myImportable).getParameterList().getPresentableText(false)); } else if (myImportable instanceof PyClass) { - final PyClass[] supers = ((PyClass)myImportable).getSuperClasses(); - if (supers.length > 0) { + final List supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(), new Function() { + @Override + public String fun(PyClass cls) { + return PyUtil.isObjectClass(cls) ? null : cls.getName(); + } + }); + if (!supers.isEmpty()) { sb.append("("); - // ", ".join(x.getName() for x in getSuperClasses()) - final String[] superNames = new String[supers.length]; - for (int i = 0; i < supers.length; i += 1) { - superNames[i] = supers[i].getName(); - } - sb.append(StringUtil.join(superNames, ", ")); + StringUtil.join(supers, ", ", sb); sb.append(")"); } } diff --git a/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/main.py b/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/main.py new file mode 100644 index 000000000000..b5e5da256cfa --- /dev/null +++ b/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/main.py @@ -0,0 +1 @@ +MyOldStyleClass diff --git a/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/module.py b/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/module.py new file mode 100644 index 000000000000..4652e3d0f87e --- /dev/null +++ b/python/testData/inspections/objectBaseIsNotShownInAutoImportQuickfix/module.py @@ -0,0 +1,2 @@ +class MyOldStyleClass: + pass diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index 6cc2e578fb30..4b9b5ca42e0c 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -50,6 +50,16 @@ public class PyQuickFixTest extends PyTestCase { PyUnresolvedReferencesInspection.class, "Import 'importFromModule.foo.baz'", true, true); } + // PY-14365 + public void testObjectBaseIsNotShownInAutoImportQuickfix() { + myFixture.copyDirectoryToProject("objectBaseIsNotShownInAutoImportQuickfix", ""); + myFixture.configureByFile("main.py"); + myFixture.enableInspections(PyUnresolvedReferencesInspection.class); + final IntentionAction intention = myFixture.findSingleIntention("Import"); + assertNotNull(intention); + assertEquals("Import 'module.MyOldStyleClass'", intention.getText()); + } + public void testImportFromModuleStar() { // PY-6302 myFixture.enableInspections(PyUnresolvedReferencesInspection.class); myFixture.copyDirectoryToProject("importFromModuleStar", ""); From 99f4933e7087433bcf755260b2f2589e9a65c0ff Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 18 Nov 2014 01:18:16 +0300 Subject: [PATCH 44/75] PY-9209 Insert a space after '#' sign when using smart enter in comment --- .../PyCommentBreakerEnterProcessor.java | 10 +++++++--- python/testData/codeInsight/smartEnter/comment.py | 2 +- .../testData/codeInsight/smartEnter/comment_after.py | 4 ++-- .../smartEnter/spaceInsertedAfterHashSignInComment.py | 2 ++ .../spaceInsertedAfterHashSignInComment_after.py | 3 +++ .../testSrc/com/jetbrains/python/PySmartEnterTest.java | 5 +++++ 6 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment.py create mode 100644 python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment_after.py diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyCommentBreakerEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyCommentBreakerEnterProcessor.java index ee8394defe9e..0a6abd4b084b 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyCommentBreakerEnterProcessor.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyCommentBreakerEnterProcessor.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil; @@ -34,12 +35,15 @@ public class PyCommentBreakerEnterProcessor implements EnterProcessor { return false; } final CaretModel caretModel = editor.getCaretModel(); - final PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset()); + PsiElement atCaret = psiElement.getContainingFile().findElementAt(caretModel.getOffset()); + if (atCaret instanceof PsiWhiteSpace) { + atCaret = atCaret.getPrevSibling(); + } final PsiElement comment = PsiTreeUtil.getParentOfType(atCaret, PsiComment.class, false); if (comment != null) { SmartEnterUtil.plainEnter(editor); - editor.getDocument().insertString(caretModel.getOffset(), "#"); - caretModel.moveToOffset(caretModel.getOffset() + 1); + editor.getDocument().insertString(caretModel.getOffset(), "# "); + caretModel.moveToOffset(caretModel.getOffset() + 2); return true; } return false; diff --git a/python/testData/codeInsight/smartEnter/comment.py b/python/testData/codeInsight/smartEnter/comment.py index c776b2a05afb..edf9e80daaf9 100644 --- a/python/testData/codeInsight/smartEnter/comment.py +++ b/python/testData/codeInsight/smartEnter/comment.py @@ -1 +1 @@ -#comment \ No newline at end of file +# comment \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/comment_after.py b/python/testData/codeInsight/smartEnter/comment_after.py index 374c22d6a10a..129e53e20712 100644 --- a/python/testData/codeInsight/smartEnter/comment_after.py +++ b/python/testData/codeInsight/smartEnter/comment_after.py @@ -1,2 +1,2 @@ -#comment -# \ No newline at end of file +# comment +# \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment.py b/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment.py new file mode 100644 index 000000000000..d2f1f9bdb19d --- /dev/null +++ b/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment.py @@ -0,0 +1,2 @@ +# foo +pass \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment_after.py b/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment_after.py new file mode 100644 index 000000000000..9e0b9db075d8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/spaceInsertedAfterHashSignInComment_after.py @@ -0,0 +1,3 @@ +# foo +# +pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java index e58988010645..a4db79654658 100644 --- a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java +++ b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java @@ -189,4 +189,9 @@ public class PySmartEnterTest extends PyTestCase { public void testWithOnlyColonMissing() { doTest(); } + + // PY-9209 + public void testSpaceInsertedAfterHashSignInComment() { + doTest(); + } } From 2d1a05ffb153acf6bc5d67259aead24a13298e8a Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 18 Nov 2014 03:10:32 +0300 Subject: [PATCH 45/75] IDEA-131822 Fixed initializing repository root url in DirectoryEntry instances provided by BrowseClient for command line --- .../idea/svn/browse/CmdBrowseClient.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java index bceb516caef3..239e7b6ab225 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java @@ -29,6 +29,7 @@ import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.commandLine.SvnCommandName; +import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.lock.Lock; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -62,9 +63,10 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient { parameters.add("--xml"); CommandExecutor command = execute(myVcs, target, SvnCommandName.list, parameters, null); + Info info = myFactory.createInfoClient().doInfo(target.getURL(), target.getPegRevision(), revision); try { - parseOutput(target.getURL(), command, handler); + parseOutput(target.getURL(), command, handler, info != null ? info.getRepositoryRootURL() : null); } catch (SVNException e) { throw new SvnBindException(e); @@ -89,15 +91,18 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient { return listener.getCommittedRevision(); } - private static void parseOutput(@NotNull SVNURL url, @NotNull CommandExecutor command, @Nullable DirectoryEntryConsumer handler) - throws VcsException, SVNException { + private static void parseOutput(@NotNull SVNURL url, + @NotNull CommandExecutor command, + @Nullable DirectoryEntryConsumer handler, + @Nullable SVNURL repositoryUrl) + throws VcsException, SVNException { try { TargetLists lists = CommandUtil.parse(command.getOutput(), TargetLists.class); if (handler != null && lists != null) { for (TargetList list : lists.lists) { for (Entry entry : list.entries) { - handler.consume(entry.toDirectoryEntry(url)); + handler.consume(entry.toDirectoryEntry(url, repositoryUrl)); } } } @@ -140,9 +145,8 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient { public Lock.Builder lock; @NotNull - public DirectoryEntry toDirectoryEntry(@NotNull SVNURL url) throws SVNException { - // TODO: repository is not used for now - return new DirectoryEntry(url.appendPath(name, false), null, PathUtil.getFileName(name), kind, + public DirectoryEntry toDirectoryEntry(@NotNull SVNURL url, @Nullable SVNURL repositoryUrl) throws SVNException { + return new DirectoryEntry(url.appendPath(name, false), repositoryUrl, PathUtil.getFileName(name), kind, commit != null ? commit.build() : null, name); } } From 68e4b6a7932b404ef7b1daf0516c7284c725d9f0 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 18 Nov 2014 05:42:55 +0300 Subject: [PATCH 46/75] svn: Refactored BranchConfigurationDialog.configureBranches() - parameters inlined, code simplified --- .../src/org/jetbrains/idea/svn/SvnUtil.java | 9 ----- .../BranchConfigurationDialog.java | 40 ++++++------------- .../branchConfig/ConfigureBranchesAction.java | 2 +- .../branchConfig/CreateBranchOrTagDialog.java | 2 +- .../svn/branchConfig/SelectBranchPopup.java | 2 +- .../idea/svn/dialogs/CopiesPanel.java | 2 +- 6 files changed, 16 insertions(+), 41 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 5fc354cb614b..a955b7094d26 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -510,15 +510,6 @@ public class SvnUtil { } } - @Nullable - public static VirtualFile correctRoot(final Project project, final VirtualFile file) { - if (file.getPath().length() == 0) { - // project root - return project.getBaseDir(); - } - return file; - } - public static boolean checkRepositoryVersion15(@NotNull SvnVcs vcs, @NotNull String url) { // Merge info tracking is supported in repositories since svn 1.5 (June 2008) - see http://subversion.apache.org/docs/release-notes/. // But still some users use 1.4 repositories and currently we need to know if repository supports merge info for some code flows. diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java index 0e0fce947088..0714c6c04c50 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java @@ -24,6 +24,7 @@ import com.intellij.openapi.ui.MultiLineLabelUI; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.*; import com.intellij.ui.components.JBList; @@ -31,7 +32,10 @@ import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.RootUrlInfo; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; import org.tmatesoft.svn.core.SVNURL; @@ -42,7 +46,6 @@ import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; import java.util.ArrayList; import java.util.List; @@ -188,34 +191,19 @@ public class BranchConfigurationDialog extends DialogWrapper { return "Subversion.BranchConfigurationDialog"; } - public static void configureBranches(final Project project, final VirtualFile file) { - configureBranches(project, file, false); - } - - public static void configureBranches(final Project project, final VirtualFile file, final boolean isRoot) { - final VirtualFile vcsRoot = (isRoot) ? file : getRoot(project, file); - if (vcsRoot == null) { + public static void configureBranches(final Project project, @Nullable VirtualFile file) { + if (file == null) { return; } - final VirtualFile directory = SvnUtil.correctRoot(project, file); - if (directory == null) { - return; - } - final RootUrlInfo wcRoot = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(directory.getPath())); + final RootUrlInfo wcRoot = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(VfsUtilCore.virtualToIoFile(file)); if (wcRoot == null) { return; } - final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl(); - if (rootUrl == null) { - Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"), - SvnBundle.message("configure.branches.title")); - return; - } SvnBranchConfigurationNew configuration; try { - configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot); + configuration = SvnBranchConfigurationManager.getInstance(project).get(file); } catch (VcsException ex) { Messages.showErrorDialog(project, "Error loading branch configuration: " + ex.getMessage(), @@ -224,18 +212,14 @@ public class BranchConfigurationDialog extends DialogWrapper { } final SvnBranchConfigurationNew clonedConfiguration = configuration.copy(); - BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot, wcRoot.getUrl()); + BranchConfigurationDialog dlg = + new BranchConfigurationDialog(project, clonedConfiguration, wcRoot.getRepositoryUrlUrl(), file, wcRoot.getUrl()); dlg.show(); if (dlg.isOK()) { - SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration); + SvnBranchConfigurationManager.getInstance(project).setConfiguration(file, clonedConfiguration); } } - private static VirtualFile getRoot(Project project, VirtualFile file) { - RootUrlInfo path = SvnVcs.getInstance(project).getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath())); - return path == null ? null : path.getVirtualFile(); - } - private static class MyListModel extends AbstractListModel { private final SvnBranchConfigurationNew myConfiguration; private List myBranchUrls; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java index 3615c4b4792d..0d65165d05cf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java @@ -61,6 +61,6 @@ public class ConfigureBranchesAction extends AnAction implements DumbAware { return; } final SvnChangeList svnList = (SvnChangeList) cls[0]; - BranchConfigurationDialog.configureBranches(project, svnList.getRoot(), true); + BranchConfigurationDialog.configureBranches(project, svnList.getRoot()); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java index 95ae986dd72d..37cc859bfbf2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java @@ -184,7 +184,7 @@ public class CreateBranchOrTagDialog extends DialogWrapper { }); myBranchTagBaseComboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - BranchConfigurationDialog.configureBranches(project, mySrcVirtualFile, true); + BranchConfigurationDialog.configureBranches(project, mySrcVirtualFile); updateBranchTagBases(); updateControls(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java index 445ce4e9afe3..90b7c663da40 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java @@ -173,7 +173,7 @@ public class SelectBranchPopup { if (CONFIGURE_MESSAGE.equals(selectedValue)) { return doFinalStep(new Runnable() { public void run() { - BranchConfigurationDialog.configureBranches(myProject, myVcsRoot, true); + BranchConfigurationDialog.configureBranches(myProject, myVcsRoot); } }); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java index 1286c88ecb29..d06b67093aa6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java @@ -221,7 +221,7 @@ public class CopiesPanel { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (CONFIGURE_BRANCHES.equals(e.getDescription())) { if (! checkRoot(root, wcInfo.getPath(), " invoke Configure Branches")) return; - BranchConfigurationDialog.configureBranches(myProject, root, true); + BranchConfigurationDialog.configureBranches(myProject, root); } else if (FIX_DEPTH.equals(e.getDescription())) { final int result = Messages.showOkCancelDialog(myVcs.getProject(), "You are going to checkout into '" + wcInfo.getPath() + "' with 'infinity' depth.\n" + From dbaa1c3cf4928af37ecdf9a288b5634ef616a4cf Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 18 Nov 2014 06:40:00 +0300 Subject: [PATCH 47/75] svn: Refactored BranchConfigurationDialog - explicitly open repository browser for selecting "trunk" on currently used repository url instead of using entered "trunk" value and detecting repository url for it (as browse button is disabled anyway if entered "trunk" value is not child of current repository url) --- .../idea/svn/branchConfig/BranchConfigurationDialog.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java index 0714c6c04c50..dc197605ed5c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java @@ -81,9 +81,10 @@ public class BranchConfigurationDialog extends DialogWrapper { myTrunkLocationTextField.setText(configuration.getTrunkUrl()); myTrunkLocationTextField.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - final String selectedUrl = SelectLocationDialog.selectLocation(project, myTrunkLocationTextField.getText()); - if (selectedUrl != null) { - myTrunkLocationTextField.setText(selectedUrl); + Pair selectionData = SelectLocationDialog.selectLocation(project, rootUrl); + + if (selectionData != null && selectionData.getFirst() != null) { + myTrunkLocationTextField.setText(selectionData.getFirst()); } } }); From 5f123fe920a666d3c910de0c3c52da7e27976a87 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 18 Nov 2014 06:47:51 +0300 Subject: [PATCH 48/75] IDEA-103447 Made browse button for selecting "trunk" (during branches configuration) always enabled --- .../idea/svn/branchConfig/BranchConfigurationDialog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java index dc197605ed5c..d157fee66cbd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java @@ -158,7 +158,6 @@ public class BranchConfigurationDialog extends DialogWrapper { boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url); boolean areNotSame = isAncestor && !url.equals(myRootUrl); - myTrunkLocationTextField.getButton().setEnabled(isAncestor); if (areNotSame) { myConfiguration.setTrunkUrl(url.toDecodedString()); } From baf4d5ea3f0a9e15f444e0879c092d39ab1def55 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 18 Nov 2014 12:27:20 +0300 Subject: [PATCH 49/75] IDEA-24742 When execution point is highlighted using border style instead of color, an extra line is... - fix after review --- .../intellij/openapi/editor/impl/BorderEffect.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java index 8f578d2f1cf0..8f7e6ffa4d94 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java @@ -131,12 +131,13 @@ public class BorderEffect { int startX = startPoint.x; int startY = startPoint.y; int endX = endPoint.x; + int lineHeight = editor.getLineHeight(); if (height == 0) { int width = endX == startX ? 1 : endX - startX - 1; if (effectType == EffectType.ROUNDED_BOX) { - UIUtil.drawRectPickedOut((Graphics2D)g, startX, startY, width, editor.getLineHeight() - 1); + UIUtil.drawRectPickedOut((Graphics2D)g, startX, startY, width, lineHeight - 1); } else { - g.drawRect(startX, startY, width, editor.getLineHeight() - 1); + g.drawRect(startX, startY, width, lineHeight - 1); } return; } @@ -145,12 +146,12 @@ public class BorderEffect { border.verticalRel(height - 1); border.horizontalTo(endX); if (endX > 0) { - border.verticalRel(editor.getLineHeight()); + border.verticalRel(lineHeight); border.horizontalTo(0); border.verticalRel(-height + 1); } - else { - border.verticalTo(startY + editor.getLineHeight() - 1); + else if (height > lineHeight) { + border.verticalRel(-height + lineHeight + 1); } border.horizontalTo(startX); border.verticalTo(startY); From 89f31aabf388628df09a3d6cf9b94572354cdc0f Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 18 Nov 2014 12:54:33 +0300 Subject: [PATCH 50/75] remote python sdk flavour should be used for vagrant interpreter --- .../src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java index 51c617f93f82..4cd9326ddc78 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java @@ -42,7 +42,7 @@ public class PyRemoteSdkFlavor extends CPythonSdkFlavor { @Override public boolean isValidSdkHome(String path) { - return StringUtil.isNotEmpty(path) && path.startsWith("ssh:") && checkName(NAMES, getExecutableName(path)); + return StringUtil.isNotEmpty(path) && checkName(NAMES, getExecutableName(path)) && (path.startsWith("ssh:") || path.startsWith("vagrant:")); } private static boolean checkName(String[] names, @Nullable String name) { From c29b4bbdc67caa7885d2f2fc12d8299125866474 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 10:39:34 +0100 Subject: [PATCH 51/75] copyright plugin: don't hold psiFile in invokeLater runnable preventing it to be gc-ed in tests --- .../com/maddyhome/idea/copyright/CopyrightManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java index 0305c3764de3..e3828664403f 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java @@ -100,13 +100,13 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis if (module == null) return; if (!newFileTracker.poll(virtualFile)) return; if (!fileTypeUtil.isSupportedFile(virtualFile)) return; - final PsiFile file = psiManager.findFile(virtualFile); - if (file == null) return; + if (psiManager.findFile(virtualFile) == null) return; application.invokeLater(new Runnable() { @Override public void run() { - if (myProject.isDisposed()) return; - if (file.isValid() && file.isWritable()) { + if (!virtualFile.isValid()) return; + final PsiFile file = psiManager.findFile(virtualFile); + if (file != null && file.isWritable()) { final CopyrightProfile opts = getCopyrightOptions(file); if (opts != null) { new UpdateCopyrightProcessor(myProject, module, file).run(); From 5e3b801c04d89f3c20cb9daff8154cc10b5dde32 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 10:52:18 +0100 Subject: [PATCH 52/75] index consistency fixes * use last committed document stamp for unsaved/uncommitted documents * during psi commit, return psi mod stamp and not the document's one * during multi-tree psi commit, indices should use the main tree's AST content and not the semi-updated parallel trees * consider documents committed after changes in absence of PSI --- .../intellij/index/IndexGeneratedTest.groovy | 60 +++++++++++++++++++ .../testSrc/com/intellij/index/IndexTest.java | 12 +--- .../com/intellij/psi/PsiDocumentManager.java | 9 +++ .../psi/SingleRootFileViewProvider.java | 21 ++++++- .../psi/impl/PsiDocumentManagerBase.java | 23 ++++--- .../intellij/psi/impl/source/PsiFileImpl.java | 1 + .../util/indexing/FileBasedIndexImpl.java | 17 ++---- .../intellij/mock/MockPsiDocumentManager.java | 5 ++ 8 files changed, 115 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy diff --git a/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy b/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy new file mode 100644 index 000000000000..9bc126f39078 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.index +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiFile +import com.intellij.psi.impl.PsiManagerEx +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.PlatformTestUtil +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase +import com.intellij.util.TimeoutUtil + +class IndexGeneratedTest extends JavaCodeInsightFixtureTestCase { + protected void invokeTestRunnable(Runnable runnable) { + WriteCommandAction.runWriteCommandAction(project, runnable) + } + + public void "test changing a file without psi makes the document committed and updates index"() { + def psiFile = myFixture.addFileToProject("Foo.java", "class Foo {}") + def vFile = psiFile.virtualFile + def scope = GlobalSearchScope.allScope(project) + + FileDocumentManager.instance.getDocument(vFile).text = "import zoo.Zoo; class Foo1 {}" + assert PsiDocumentManager.getInstance(project).uncommittedDocuments + psiFile = null + + PlatformTestUtil.tryGcSoftlyReachableObjects() + + println 'sleeping' + TimeoutUtil.sleep(10000) + + assert !((PsiManagerEx) psiManager).fileManager.getCachedPsiFile(vFile) + + FileDocumentManager.instance.saveAllDocuments() + + VfsUtil.saveText(vFile, "class Foo3 {}") + + assert !PsiDocumentManager.getInstance(project).uncommittedDocuments + + assert JavaPsiFacade.getInstance(project).findClass("Foo3", scope) + } + + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.java b/java/java-tests/testSrc/com/intellij/index/IndexTest.java index 93130e085e91..9a0b50ff4871 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTest.java +++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.java @@ -36,7 +36,6 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.PsiTestUtil; -import com.intellij.testFramework.SkipSlowTestLocally; import com.intellij.util.indexing.MapIndexStorage; import com.intellij.util.indexing.StorageException; import com.intellij.util.io.*; @@ -52,7 +51,6 @@ import java.util.*; * @author Eugene Zhuravlev * Date: Dec 12, 2007 */ -@SkipSlowTestLocally public class IndexTest extends CodeInsightTestCase { public void testUpdate() throws StorageException, IOException { @@ -241,7 +239,7 @@ public class IndexTest extends CodeInsightTestCase { }); } - public void _testCollectedPsiWithDocumentChangedCommittedAndChangedAgain() throws IOException { + public void testCollectedPsiWithDocumentChangedCommittedAndChangedAgain() throws IOException { VirtualFile dir = getVirtualFile(createTempDirectory()); PsiTestUtil.addSourceContentToRoots(myModule, dir); @@ -267,13 +265,7 @@ public class IndexTest extends CodeInsightTestCase { assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile)); PsiClass foo = myJavaFacade.findClass("Foo", scope); - assertNotNull(foo); - assertTrue(foo.isValid()); - assertEquals("class Foo {}", foo.getText()); - assertTrue(foo.isValid()); - - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - assertNull(myJavaFacade.findClass("Foo", scope)); + assertNull(foo); } }); } diff --git a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java index d2a7a9aefdbc..d05b11e47de1 100644 --- a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java +++ b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java @@ -109,6 +109,15 @@ public abstract class PsiDocumentManager { @NotNull public abstract CharSequence getLastCommittedText(@NotNull Document document); + /** + * @return for uncommitted documents, the last stamp before the document change: the same stamp that current PSI should have. + * For committed documents, just their stamp. + * + * @see Document#getModificationStamp() + * @see FileViewProvider#getModificationStamp() + */ + public abstract long getLastCommittedStamp(@NotNull Document document); + /** * Returns the list of documents which have been modified but not committed. * diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 63a7f205c11c..6899460bf235 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -165,7 +165,6 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi @Override public void beforeContentsSynchronized() { - unsetPsiContent(); } @Override @@ -501,7 +500,20 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi @Override public long getModificationStamp() { - return getVirtualFile().getModificationStamp(); + final VirtualFile virtualFile = getVirtualFile(); + if (virtualFile instanceof LightVirtualFile) { + Document doc = getCachedDocument(); + if (doc != null) return getLastCommittedStamp(doc); + return virtualFile.getModificationStamp(); + } + + final Document document = getDocument(); + if (document == null) { + return virtualFile.getModificationStamp(); + } + else { + return getLastCommittedStamp(document); + } } @NonNls @@ -514,6 +526,9 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi private CharSequence getLastCommittedText(Document document) { return PsiDocumentManager.getInstance(myManager.getProject()).getLastCommittedText(document); } + private long getLastCommittedStamp(Document document) { + return PsiDocumentManager.getInstance(myManager.getProject()).getLastCommittedStamp(document); + } private class DocumentContent implements Content { @NonNls @@ -534,7 +549,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi @Override public long getModificationStamp() { Document document = com.intellij.reference.SoftReference.dereference(myDocument); - if (document != null) return document.getModificationStamp(); + if (document != null) return getLastCommittedStamp(document); return myVirtualFile.getModificationStamp(); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 9bd52662a5b3..bdc83f8098cb 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -34,6 +34,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -67,7 +68,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen private final PsiManager myPsiManager; private final DocumentCommitProcessor myDocumentCommitProcessor; protected final Set myUncommittedDocuments = ContainerUtil.newConcurrentSet(); - private final Map myLastCommittedTexts = ContainerUtil.newConcurrentMap(); + private final Map> myLastCommittedTexts = ContainerUtil.newConcurrentMap(); private volatile boolean myIsCommitInProgress; private final PsiToDocumentSynchronizer mySynchronizer; @@ -558,8 +559,14 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen @Override @NotNull public CharSequence getLastCommittedText(@NotNull Document document) { - CharSequence text = myLastCommittedTexts.get(document); - return text != null ? text : document.getImmutableCharSequence(); + Pair pair = myLastCommittedTexts.get(document); + return pair != null ? pair.first : document.getImmutableCharSequence(); + } + + @Override + public long getLastCommittedStamp(@NotNull Document document) { + Pair pair = myLastCommittedTexts.get(document); + return pair != null ? pair.second : document.getModificationStamp(); } @Override @@ -595,7 +602,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen public void beforeDocumentChange(@NotNull DocumentEvent event) { final Document document = event.getDocument(); if (!(document instanceof DocumentWindow) && !myLastCommittedTexts.containsKey(document)) { - myLastCommittedTexts.put(document, document.getImmutableCharSequence()); + myLastCommittedTexts.put(document, Pair.create(document.getImmutableCharSequence(), document.getModificationStamp())); } VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); @@ -713,14 +720,16 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen } public void handleCommitWithoutPsi(@NotNull Document document) { - final CharSequence prevText = myLastCommittedTexts.remove(document); - if (prevText == null) { + final Pair prevPair = myLastCommittedTexts.remove(document); + if (prevPair == null) { return; } if (!myProject.isInitialized() || myProject.isDisposed()) { return; } + + myUncommittedDocuments.remove(document); VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); if (virtualFile == null || !FileIndexFacade.getInstance(myProject).isInContent(virtualFile)) { @@ -738,7 +747,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen public void run() { psiFile.getViewProvider().beforeContentsSynchronized(); synchronized (PsiLock.LOCK) { - final int oldLength = prevText.length(); + final int oldLength = prevPair.first.length(); PsiManagerImpl manager = (PsiManagerImpl)psiFile.getManager(); BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, true); BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, false); diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index 12300a2bcf45..cc0be29ae7e3 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -389,6 +389,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF DebugUtil.finishPsiModification(); } } + myViewProvider.contentsSynchronized(); } private void clearStub(@NotNull String reason) { diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 989ff0b07105..d8dd50719cf6 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1349,9 +1349,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { boolean allDocsProcessed = true; try { for (Document document : documents) { - if (psiBasedIndex && project != null && PsiDocumentManager.getInstance(project).isUncommited(document)) { - continue; - } allDocsProcessed &= indexUnsavedDocument(document, indexId, project, filter, restrictedFile); ProgressManager.checkCanceled(); } @@ -1451,7 +1448,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { return false; } - final PsiFile dominantContentFile = findDominantPsiForDocument(document, project); + final PsiFile dominantContentFile = project == null ? null : findLatestKnownPsiForUncomittedDocument(document, project); final DocumentContent content; if (dominantContentFile != null && dominantContentFile.getViewProvider().getModificationStamp() != document.getModificationStamp()) { @@ -1461,7 +1458,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { content = new AuthenticContent(document); } - final long currentDocStamp = content.getModificationStamp(); + boolean psiBasedIndex = myPsiDependentIndices.contains(requestedIndexId); + + final long currentDocStamp = psiBasedIndex ? PsiDocumentManager.getInstance(project).getLastCommittedStamp(document) : content.getModificationStamp(); final long previousDocStamp = myLastIndexedDocStamps.getAndSet(document, requestedIndexId, currentDocStamp); if (currentDocStamp != previousDocStamp) { final CharSequence contentText = content.getText(); @@ -1509,14 +1508,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { private final TaskQueue myContentlessIndicesUpdateQueue = new TaskQueue(10000); - @Nullable - private PsiFile findDominantPsiForDocument(@NotNull Document document, @Nullable Project project) { - PsiFile psiFile = myTransactionMap.get(document); - if (psiFile != null) return psiFile; - - return project == null ? null : findLatestKnownPsiForUncomittedDocument(document, project); - } - private final StorageGuard myStorageLock = new StorageGuard(); private volatile boolean myPreviousDataBufferingState; private final Object myBufferingStateUpdateLock = new Object(); diff --git a/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java b/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java index 2881d4b4b238..1318032fdcb6 100644 --- a/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java +++ b/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java @@ -62,6 +62,11 @@ public class MockPsiDocumentManager extends PsiDocumentManager { return document.getImmutableCharSequence(); } + @Override + public long getLastCommittedStamp(@NotNull Document document) { + return document.getModificationStamp(); + } + @Override @NotNull public Document[] getUncommittedDocuments() { From 0ff7b0839912b27b2b4c0840de1c234d419d00b6 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 10:53:07 +0100 Subject: [PATCH 53/75] use less memory for storing parent commits in GraphCommitImpl --- .../vcs/log/graph/GraphCommitImpl.java | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/GraphCommitImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/GraphCommitImpl.java index 99a0337d969f..a8b3dcfc0027 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/GraphCommitImpl.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/GraphCommitImpl.java @@ -15,20 +15,29 @@ */ package com.intellij.vcs.log.graph; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ImmutableList; import org.jetbrains.annotations.NotNull; import java.util.List; -public class GraphCommitImpl implements GraphCommit { +public class GraphCommitImpl extends ImmutableList implements GraphCommit{ @NotNull private final CommitId myId; - @NotNull private final List myParents; + @NotNull private final Object myParents; private final long myTimestamp; public GraphCommitImpl(@NotNull CommitId id, @NotNull List parents, long timestamp) { myId = id; - myParents = parents; myTimestamp = timestamp; + if (parents.isEmpty()) { + myParents = ArrayUtil.EMPTY_OBJECT_ARRAY; + } else if (parents.size() == 1) { + myParents = parents.get(0); + assert !(myParents instanceof Object[]); + } else { + myParents = parents.toArray(); + } } @NotNull @@ -40,7 +49,28 @@ public class GraphCommitImpl implements GraphCommit { @NotNull @Override public List getParents() { - return myParents; + return this; + } + + @SuppressWarnings("unchecked") + @Override + public CommitId get(int index) { + if (myParents instanceof Object[]) { + Object[] array = (Object[])myParents; + if (index < 0 || index >= array.length) { + throw new ArrayIndexOutOfBoundsException(index); + } + return (CommitId)array[index]; + } + if (index != 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + return (CommitId)myParents; + } + + @Override + public int size() { + return myParents instanceof Object[] ? ((Object[])myParents).length : 1; } @Override From f83ca52d34b4ecc30a1bdf6b287a7cd7b6aaa5e8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 10:57:50 +0100 Subject: [PATCH 54/75] run gdsl scripts concurrently --- .../groovy/dsl/GroovyDslFileIndex.java | 81 +++++++------------ 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index d8a41b52bd86..991425131df9 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -16,18 +16,17 @@ package org.jetbrains.plugins.groovy.dsl; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.ModificationTracker; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -44,10 +43,9 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.reference.SoftReference; -import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.ExceptionUtil; import com.intellij.util.Function; import com.intellij.util.PathUtil; -import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ConcurrentMultiMap; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -68,10 +66,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import java.io.File; import java.io.IOException; import java.util.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.*; import java.util.regex.Pattern; /** @@ -89,10 +84,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { private static final MultiMap>> filesInProcessing = new ConcurrentMultiMap>>(); - private static final ThreadPoolExecutor ourPool = new ThreadPoolExecutor(0, 1, 10, TimeUnit.SECONDS, new LinkedBlockingQueue(), ConcurrencyUtil.newNamedThreadFactory("Groovy DSL File Index Executor")); - private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - private static final byte[] ENABLED_FLAG = new byte[]{(byte)239}; public GroovyDslFileIndex() { VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { @@ -296,6 +288,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { return SoftReference.dereference(ourStandardScripts); } + @Nullable private static List> getStandardScripts() { List> result = derefStandardScripts(); if (result != null) { @@ -303,28 +296,17 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { } final GroovyFrameworkConfigNotification[] extensions = GroovyFrameworkConfigNotification.EP_NAME.getExtensions(); - - final Semaphore semaphore = new Semaphore(); - semaphore.down(); - final AtomicReference>> ref = new AtomicReference>>(); - - if (ApplicationManager.getApplication().isWriteAccessAllowed()) { - // If this method is called with write lock acquired, then the background computation shouldn't acquire read lock. - // Otherwise, we'll get a deadlock: this method will wait for the result of the background computation holding the write lock - // and the background computation won't finish because of waiting for the read lock. - // Dirty workaround: currently the background computation acquires read lock to only initialize GroovyDslExecutor, - // so, preventive GroovyDslExecutor initialization should help - GroovyDslExecutor.getIdeaVersion(); - } - ourPool.execute(new Runnable() { - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") + Callable>> action = new Callable>>() { @Override - public void run() { + public List> call() throws Exception { + if (GdslUtil.ourGdslStopped) { + return null; + } + try { List> pairs = derefStandardScripts(); if (pairs != null) { - ref.set(pairs); - return; + return pairs; } Set classes = new HashSet(ContainerUtil.map2Set(extensions, new Function() { @@ -365,32 +347,31 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { } } } + //noinspection AssignmentToStaticFieldFromInstanceMethod ourStandardScripts = new SoftReference>>(executors); - ref.set(executors); + return executors; } catch (Throwable e) { - ref.set(new ArrayList>()); //noinspection InstanceofCatchParameter if (e instanceof Error) { GdslUtil.stopGdsl(); } LOG.error(e); - } - finally { - semaphore.up(); + return null; } } - }); + }; - while (true) { - ProgressManager.checkCanceled(); - - if (GdslUtil.ourGdslStopped) { - return Collections.emptyList(); - } - if (ref.get() != null || semaphore.waitFor(20)) { - return ref.get(); + try { + if (ApplicationManager.getApplication().isDispatchThread()) { + return action.call(); } + return ApplicationUtil.runWithCheckCanceled(action, new EmptyProgressIndicator()); + } + catch (Exception e) { + ExceptionUtil.rethrowUnchecked(e); + LOG.error(e); + return null; } } @@ -409,9 +390,10 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { List result = new ArrayList(); List> standardScripts = getStandardScripts(); - assert standardScripts != null; - for (Pair pair : standardScripts) { - result.add(new GroovyDslScript(project, null, pair.second, pair.first.getPath())); + if (standardScripts != null) { + for (Pair pair : standardScripts) { + result.add(new GroovyDslScript(project, null, pair.second, pair.first.getPath())); + } } final LinkedBlockingQueue> queue = @@ -521,8 +503,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { final boolean isNewRequest = !filesInProcessing.containsKey(fileUrl); filesInProcessing.putValue(fileUrl, queue); if (isNewRequest) { - ourPool.execute(parseScript); //todo bring back multi-threading when Groovy team fixes http://jira.codehaus.org/browse/GROOVY-4292 - //ApplicationManager.getApplication().executeOnPooledThread(parseScript); + ApplicationManager.getApplication().executeOnPooledThread(parseScript); } } } From 742c300d62d401ea5a4cf1e44fe843957bba9bcd Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 11:03:02 +0100 Subject: [PATCH 55/75] IndexGeneratedTest: no sleep, please --- .../testSrc/com/intellij/index/IndexGeneratedTest.groovy | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy b/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy index 9bc126f39078..8e06c9bdf5a4 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy +++ b/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy @@ -42,9 +42,6 @@ class IndexGeneratedTest extends JavaCodeInsightFixtureTestCase { PlatformTestUtil.tryGcSoftlyReachableObjects() - println 'sleeping' - TimeoutUtil.sleep(10000) - assert !((PsiManagerEx) psiManager).fileManager.getCachedPsiFile(vFile) FileDocumentManager.instance.saveAllDocuments() From 241779162390349ba3a32f6e46d703a7f3a94da4 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 17 Nov 2014 17:34:16 +0100 Subject: [PATCH 56/75] get file language from file type to make sure that JS dialects are using JS settings #WEB-14120 fixed --- .../dupLocator/treeHash/NodeSpecificHasherBase.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/treeHash/NodeSpecificHasherBase.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/treeHash/NodeSpecificHasherBase.java index ef2e92fad8be..7b7553e0293d 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/treeHash/NodeSpecificHasherBase.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/treeHash/NodeSpecificHasherBase.java @@ -7,8 +7,11 @@ import com.intellij.dupLocator.iterators.SiblingNodeIterator; import com.intellij.dupLocator.util.DuplocatorUtil; import com.intellij.dupLocator.util.NodeFilter; import com.intellij.lang.Language; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.impl.source.tree.LeafElement; import com.intellij.psi.tree.IElementType; @@ -131,7 +134,14 @@ public class NodeSpecificHasherBase extends NodeSpecificHasher { @Override public void visitNode(@NotNull PsiElement node) { - final Language language = node.getLanguage(); + Language language = null; + if (node instanceof PsiFile) { + FileType fileType = ((PsiFile)node).getFileType(); + if (fileType instanceof LanguageFileType) { + language = ((LanguageFileType)fileType).getLanguage(); + } + } + if (language == null) language = node.getLanguage(); if ((myForIndexing || mySettings.SELECTED_PROFILES.contains(language.getDisplayName())) && myDuplicatesProfile.isMyLanguage(language)) { From acfb8f31fae6591e21fcdf00453e15a0393ff948 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 17 Nov 2014 18:23:39 +0100 Subject: [PATCH 57/75] use namespace from tag, not empty one #WEB-14165 fixed --- .../html/impl/RelaxedHtmlFromSchemaElementDescriptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/xml-psi-impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java b/xml/xml-psi-impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java index 1de12639ca1a..c8cba3f84d0e 100644 --- a/xml/xml-psi-impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/html/impl/RelaxedHtmlFromSchemaElementDescriptor.java @@ -36,7 +36,7 @@ public class RelaxedHtmlFromSchemaElementDescriptor extends XmlElementDescriptor } public static XmlAttributeDescriptor[] getCommonAttributeDescriptors(XmlTag context) { - final XmlNSDescriptor nsDescriptor = context != null ? context.getNSDescriptor("", false) : null; + final XmlNSDescriptor nsDescriptor = context != null ? context.getNSDescriptor(context.getNamespace(), false) : null; if (nsDescriptor != null) { for (XmlElementDescriptor descriptor : nsDescriptor.getRootElementsDescriptors(null)) { final String name = descriptor.getName(); From e7eca438c5203048cbde51034cf2da05babf4bd1 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 17 Nov 2014 18:25:17 +0300 Subject: [PATCH 58/75] diagnostics --- .../ex/InspectionProfileImpl.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java index 70577a37ff24..9709dcd8592d 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java @@ -75,7 +75,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, @TestOnly public static boolean INIT_INSPECTIONS = false; private static Map ourMergers = null; - final InspectionToolRegistrar myRegistrar; + private final InspectionToolRegistrar myRegistrar; @NotNull private final Map myDeinstalledInspectionsSettings; private final ExternalInfo myExternalInfo = new ExternalInfo(); @@ -342,9 +342,9 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, inspectionElement.setAttribute(CLASS_TAG, toolName); toolList.writeExternal(inspectionElement); - if (areSettingsMerged(toolName, inspectionElement)) continue; - - element.addContent(inspectionElement); + if (!areSettingsMerged(toolName, inspectionElement)) { + element.addContent(inspectionElement); + } } else { element.addContent(toolElement.clone()); @@ -378,13 +378,12 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, if (mainToolId != null) { InspectionToolWrapper dependentEntryWrapper = getInspectionTool(mainToolId, project); - if (dependentEntryWrapper != null) { - if (!dependentEntries.add(dependentEntryWrapper)) { - collectDependentInspections(dependentEntryWrapper, dependentEntries, project); - } + if (dependentEntryWrapper == null) { + LOG.error("Can't find main tool: '" + mainToolId+"' which was specified in "+toolWrapper); + return; } - else { - LOG.error("Can't find main tool: " + mainToolId); + if (!dependentEntries.add(dependentEntryWrapper)) { + collectDependentInspections(dependentEntryWrapper, dependentEntries, project); } } } @@ -1015,6 +1014,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, } } + @Override @NotNull public String toString() { return mySource == null ? getName() : getName() + " (copy)"; From 2b99690747867498f6af3e61d091eaea09b77632 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 17 Nov 2014 18:37:28 +0300 Subject: [PATCH 59/75] EA-58415 --- .../ex/GlobalInspectionContextImpl.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 400127979dd5..6abcb85c8318 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -60,13 +60,13 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.content.*; +import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Processor; import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.TripleFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.UIUtil; -import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jdom.Document; import org.jdom.Element; @@ -78,7 +78,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.lang.reflect.Constructor; import java.util.*; +import java.util.concurrent.ConcurrentMap; public class GlobalInspectionContextImpl extends GlobalInspectionContextBase implements GlobalInspectionContext { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl"); @@ -592,7 +594,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp } } - private final Map myPresentationMap = new THashMap(); + private final ConcurrentMap myPresentationMap = ContainerUtil.newConcurrentMap(); @NotNull public InspectionToolPresentation getPresentation(@NotNull InspectionToolWrapper toolWrapper) { InspectionToolPresentation presentation = myPresentationMap.get(toolWrapper); @@ -601,12 +603,15 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp DefaultInspectionToolPresentation.class.getName()); try { - presentation = (InspectionToolPresentation)Class.forName(presentationClass).getConstructor(InspectionToolWrapper.class, GlobalInspectionContextImpl.class).newInstance(toolWrapper, this); + Constructor constructor = + Class.forName(presentationClass).getConstructor(InspectionToolWrapper.class, GlobalInspectionContextImpl.class); + presentation = (InspectionToolPresentation)constructor.newInstance(toolWrapper, this); } catch (Exception e) { LOG.error(e); + throw new RuntimeException(e); } - myPresentationMap.put(toolWrapper, presentation); + presentation = ConcurrencyUtil.cacheOrGet(myPresentationMap, toolWrapper, presentation); } return presentation; } From 93bff1331deec52a992bbdc707dd06dfb6fb0b5b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 17 Nov 2014 18:48:37 +0300 Subject: [PATCH 60/75] diagnostics --- .../intellij/openapi/components/impl/ComponentManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index df1bfa77a451..ef244898400d 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -277,7 +277,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements MutablePicoContainer container = myPicoContainer; if (container == null || myDisposeCompleted) { ProgressManager.checkCanceled(); - throw new AssertionError("Already disposed"); + throw new AssertionError("Already disposed: "+toString()); } return container; } From 0b6091ff71a3ece704dcf5ad5e74b00f76f779a0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 17 Nov 2014 19:08:27 +0300 Subject: [PATCH 61/75] file type test --- .../fileTypes/impl/FileTypeManagerImpl.java | 56 ++++++++++++++++--- ...EnforcedPlaintTextFileTypeManagerTest.java | 2 + .../openapi/fileTypes/impl/FileTypesTest.java | 16 ++++-- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index 9b1fd384dfa3..8ccfaf2faac3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -77,9 +77,11 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME private static final int VERSION = 11; private static final Key FILE_TYPE_KEY = Key.create("FILE_TYPE_KEY"); + // cached auto-detected file type. If the file was auto-detected as plain text or binary + // then the value is null and autoDetectedAsText, autoDetectedAsBinary and autoDetectWasRun sets are used instead. private static final Key DETECTED_FROM_CONTENT_FILE_TYPE_KEY = Key.create("DETECTED_FROM_CONTENT_FILE_TYPE_KEY"); private static final int DETECT_BUFFER_SIZE = 8192; // the number of bytes to read from the file to feed to the file type detector - private boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode(); + private static boolean RE_DETECT_ASYNC = !ApplicationManager.getApplication().isUnitTestMode(); private final Set myDefaultTypes = new THashSet(); private final List mySpecialFileTypes = new ArrayList(); @@ -257,6 +259,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME } }); files.remove(null); + if (toLog()) { + System.out.println("F: VFS events: " + events); + } if (!files.isEmpty() && RE_DETECT_ASYNC) { reDetectQueue.offer(files); } @@ -264,6 +269,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME }); } + private static boolean toLog() { + return RE_DETECT_ASYNC && ApplicationManager.getApplication().isUnitTestMode(); + } + private final TransferToPooledThreadQueue> reDetectQueue = new TransferToPooledThreadQueue>("File type re-detect", Conditions.alwaysFalse(), -1, new Processor>() { @Override public boolean process(Collection files) { @@ -284,12 +293,20 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME private void reDetect(@NotNull Collection files) { final List changed = new ArrayList(); for (VirtualFile file : files) { - if (wasAutoDetectedBefore(file) && isDetectable(file)) { + boolean shouldRedetect = wasAutoDetectedBefore(file) && isDetectable(file); + if (toLog()) { + System.out.println("F: Redetect file: " + file.getName() + "; shouldRedetect: " + shouldRedetect); + } + if (shouldRedetect) { FileType before = file.getFileType(); FileType after = detectFromContent(file); + if (toLog()) { + System.out.println("F: After redetect file: " + file.getName() + "; before: " + before.getName() + "; after: " + after.getName()+"; now getFileType()="+file.getFileType().getName()); + } + if (before != after) { changed.add(file); - LOG.debug(file+" type was re-detected. Was: "+before+"; now: "+after); + LOG.debug(file+" type was re-detected. Was: "+before.getName()+"; now: "+after.getName()); } } } @@ -392,6 +409,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME public static void cacheFileType(@NotNull VirtualFile file, @Nullable FileType fileType) { file.putUserData(FILE_TYPE_KEY, fileType); + if (toLog()) { + System.out.println("F: Cached file type for "+file.getName()+" to "+(fileType == null ? null : fileType.getName())); + } } @Override @@ -409,12 +429,20 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME for (int i = 0; i < mySpecialFileTypes.size(); i++) { FileTypeIdentifiableByVirtualFile type = mySpecialFileTypes.get(i); if (type.isMyFileType(file)) { + if (toLog()) { + System.out.println("F: Special file type for "+file.getName()+"; type: "+type.getName()); + } return type; } } fileType = getFileTypeByFileName(file.getNameSequence()); - if (fileType != UnknownFileType.INSTANCE) return fileType; + if (fileType != UnknownFileType.INSTANCE) { + if (toLog()) { + System.out.println("F: By name file type for "+file.getName()+"; type: "+fileType.getName()); + } + return fileType; + } if (!(file instanceof StubVirtualFile)) { fileType = getOrDetectFromContent(file); @@ -430,8 +458,13 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME int id = ((VirtualFileWithId)file).getId(); if (id < 0) return UnknownFileType.INSTANCE; if (autoDetectWasRun.get(id)) { - return autoDetectedAsText.get(id) ? FileTypes.PLAIN_TEXT : autoDetectedAsBinary.get(id) ? UnknownFileType.INSTANCE : - ObjectUtils.notNull(file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY), FileTypes.PLAIN_TEXT); + FileType type = autoDetectedAsText.get(id) ? FileTypes.PLAIN_TEXT : + autoDetectedAsBinary.get(id) ? UnknownFileType.INSTANCE : + ObjectUtils.notNull(file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY), FileTypes.PLAIN_TEXT); + if (toLog()) { + System.out.println("F: getFileType("+file.getName()+") = "+type.getName()); + } + return type; } boolean wasDetectedAsText = false; boolean wasDetectedAsBinary = false; @@ -465,6 +498,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME fileType = detectFromContent(file); } + if (toLog()) { + System.out.println("F: getFileType after detect run("+file.getName()+") = "+fileType.getName()); + } + return fileType; } @@ -501,6 +538,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME autoDetectedAsText.set(id, wasAutodetectedAsText); autoDetectedAsBinary.set(id, wasAutodetectedAsBinary); if (wasAutodetectedAsText || wasAutodetectedAsBinary) { + file.putUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY, null); return; } } @@ -535,9 +573,8 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME long start = System.currentTimeMillis(); try { final InputStream inputStream = ((FileSystemInterface)file.getFileSystem()).getInputStream(file); - final Ref result; + final Ref result = new Ref(UnknownFileType.INSTANCE); try { - result = new Ref(UnknownFileType.INSTANCE); FileUtil.processFirstBytes(inputStream, DETECT_BUFFER_SIZE, new Processor() { @Override public boolean process(ByteSequence byteSequence) { @@ -574,6 +611,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME inputStream.close(); } FileType fileType = result.get(); + if (toLog()) { + System.out.println("F: Redetect run for file: " + file.getName() + "; result: "+fileType.getName()); + } if (LOG.isDebugEnabled()) { LOG.debug(file + "; type=" + fileType.getDescription() + "; " + counterAutoDetect); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java index b7cefc60d1f6..70670acf3097 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeFactory; import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.ui.UIUtil; /** * @author Rustam Vishnyakov @@ -30,6 +31,7 @@ public class EnforcedPlaintTextFileTypeManagerTest extends LightPlatformCodeInsi FileType originalType = file.getFileType(); assertEquals("JAVA", originalType.getName()); manager.markAsPlainText(getProject(), file); + UIUtil.dispatchAllInvocationEvents(); // reparseFiles in invokeLater FileType changedType = file.getFileType(); assertEquals(EnforcedPlainTextFileTypeFactory.ENFORCED_PLAIN_TEXT, changedType.getName()); manager.resetOriginalFileType(getProject(), file); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java index df484cce9a83..2ac2dbe89422 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/impl/FileTypesTest.java @@ -278,14 +278,16 @@ public class FileTypesTest extends PlatformTestCase { } public void testReDetectOnContentsChange() throws IOException { - FileType fileType = FileTypeRegistry.getInstance().getFileTypeByFileName("x" + ModuleFileType.DOT_DEFAULT_EXTENSION); + final FileTypeRegistry fileTypeManager = FileTypeRegistry.getInstance(); + assertTrue(fileTypeManager.getClass().getName(), fileTypeManager instanceof FileTypeManagerImpl); + FileType fileType = fileTypeManager.getFileTypeByFileName("x" + ModuleFileType.DOT_DEFAULT_EXTENSION); assertTrue(fileType.toString(), fileType instanceof ModuleFileType); - fileType = FileTypeRegistry.getInstance().getFileTypeByFileName("x" + ProjectFileType.DOT_DEFAULT_EXTENSION); + fileType = fileTypeManager.getFileTypeByFileName("x" + ProjectFileType.DOT_DEFAULT_EXTENSION); assertTrue(fileType.toString(), fileType instanceof ProjectFileType); - FileType module = FileTypeRegistry.getInstance().findFileTypeByName("IDEA_MODULE"); + FileType module = fileTypeManager.findFileTypeByName("IDEA_MODULE"); assertNotNull(module); assertFalse(module.equals(PlainTextFileType.INSTANCE)); - FileType project = FileTypeRegistry.getInstance().findFileTypeByName("IDEA_PROJECT"); + FileType project = fileTypeManager.findFileTypeByName("IDEA_PROJECT"); assertNotNull(project); assertFalse(project.equals(PlainTextFileType.INSTANCE)); @@ -296,7 +298,7 @@ public class FileTypesTest extends PlatformTestCase { public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) { detectorCalled.add(file); String text = firstCharsIfText.toString(); - FileType result = text.startsWith("TYPE:") ? FileTypeRegistry.getInstance().findFileTypeByName(StringUtil.trimStart(text, "TYPE:")) : null; + FileType result = text.startsWith("TYPE:") ? fileTypeManager.findFileTypeByName(StringUtil.trimStart(text, "TYPE:")) : null; System.out.println("T: my detector run for "+file.getName()+"; result: "+(result == null ? null : result.getName())); return result; } @@ -308,6 +310,7 @@ public class FileTypesTest extends PlatformTestCase { }; Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).registerExtension(detector); try { + System.out.println("T: ------"); File d = createTempDirectory(); File f = new File(d, "xx.asfdasdfas"); FileUtil.writeToFile(f, "akjdhfksdjgf"); @@ -315,13 +318,16 @@ public class FileTypesTest extends PlatformTestCase { ensureRedetected(vFile, detectorCalled); assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof PlainTextFileType); + System.out.println("T: ------"); VfsUtil.saveText(vFile, "TYPE:IDEA_MODULE"); ensureRedetected(vFile, detectorCalled); assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ModuleFileType); + System.out.println("T: ------"); VfsUtil.saveText(vFile, "TYPE:IDEA_PROJECT"); ensureRedetected(vFile, detectorCalled); assertTrue(vFile.getFileType().toString(), vFile.getFileType() instanceof ProjectFileType); + System.out.println("T: ------"); } finally { Extensions.getRootArea().getExtensionPoint(FileTypeRegistry.FileTypeDetector.EP_NAME).unregisterExtension(detector); From 9c58cac7526cceb613eaf0e37bc3c4faf2bb0d6e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 18 Nov 2014 12:33:39 +0300 Subject: [PATCH 62/75] wrong usages of showAndGetOk() --- .../intellij/openapi/ui/DialogWrapper.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) 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 8273f9dd3463..d429f14c97d9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -1176,9 +1176,7 @@ public abstract class DialogWrapper { } protected void init() { - if (!SwingUtilities.isEventDispatchThread()) { - LOG.error("Dialog must be init in EDT only: "+Thread.currentThread()); - } + ensureEventDispatchThread(); myErrorText = new ErrorText(); myErrorText.setVisible(false); @@ -1197,7 +1195,7 @@ public abstract class DialogWrapper { final CustomShortcutSet sc = new CustomShortcutSet(SHOW_OPTION_KEYSTROKE); final AnAction toggleShowOptions = new AnAction() { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { expandNextOptionButton(); } }; @@ -1548,7 +1546,7 @@ public abstract class DialogWrapper { * @throws IllegalStateException if the dialog is invoked not on the event dispatch thread */ public void show() { - showAndGetOk(); + invokeShow(); } public boolean showAndGet() { @@ -1559,16 +1557,23 @@ public abstract class DialogWrapper { /** * You need this method ONLY for NON-MODAL dialogs. Otherwise, use {@link #show()} or {@link #showAndGet()}. * - * @return result callback + * @return result callback which set to "Done" on dialog close, and then its {@code getResult()} will contain {@code isOK()} */ @NotNull public AsyncResult showAndGetOk() { + if (isModal()) { + throw new IllegalStateException("The showAndGetOk() method is for modeless dialogs only"); + } + return invokeShow(); + } + + @NotNull + private AsyncResult invokeShow() { final AsyncResult result = new AsyncResult(); ensureEventDispatchThread(); registerKeyboardShortcuts(); - final Disposable uiParent = Disposer.get("ui"); if (uiParent != null) { // may be null if no app yet (license agreement) Disposer.register(uiParent, myDisposable); // ensure everything is disposed on app quit @@ -1600,7 +1605,6 @@ public abstract class DialogWrapper { } private void registerKeyboardShortcuts() { - final JRootPane rootPane = getRootPane(); if (rootPane == null) return; @@ -2010,7 +2014,7 @@ public abstract class DialogWrapper { */ private static void ensureEventDispatchThread() { if (!EventQueue.isDispatchThread()) { - throw new IllegalStateException("The DialogWrapper can be used only on event dispatch thread."); + throw new IllegalStateException("The DialogWrapper can be used only in event dispatch thread. Current thread: "+Thread.currentThread()); } } @@ -2121,7 +2125,7 @@ public abstract class DialogWrapper { return true; } - public void setValidationInfo(@Nullable ValidationInfo info) { + private void setValidationInfo(@Nullable ValidationInfo info) { myInfo = info; } } From 5bffb5198d7cab684e09a1125b104d61bde43a76 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 18 Nov 2014 12:55:19 +0300 Subject: [PATCH 63/75] IDEA-132931 ProgressManager does not cancel all threads running under same WrappedProgressIndicator indicator --- .../progress/impl/ProgressManagerImpl.java | 22 +++++++------- .../progress/impl/ProgressIndicatorTest.java | 29 +++++++++++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 878e60099b50..51f14f8e2bd9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -56,7 +56,7 @@ import java.util.concurrent.atomic.AtomicReference; public class ProgressManagerImpl extends ProgressManager implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl"); - public static final int CHECK_CANCELED_DELAY_MILLIS = 10; + static final int CHECK_CANCELED_DELAY_MILLIS = 10; private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0); private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0); @@ -321,19 +321,17 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable { Set threads = threadsUnderIndicator.get(indicator); if (threads != null) { for (Thread thread : threads) { - ProgressIndicator currentIndicator = getCurrentIndicator(thread); - boolean underCancelledIndicator = currentIndicator == indicator; - - if (!underCancelledIndicator && currentIndicator instanceof WrappedProgressIndicator) { - while(currentIndicator instanceof WrappedProgressIndicator) { - ProgressIndicator originalProgressIndicator = ((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator(); - if (originalProgressIndicator == indicator) { - underCancelledIndicator = true; - break; - } - currentIndicator = originalProgressIndicator; + boolean underCancelledIndicator = false; + for (ProgressIndicator currentIndicator = getCurrentIndicator(thread); + currentIndicator != null; + currentIndicator = currentIndicator instanceof WrappedProgressIndicator ? + ((WrappedProgressIndicator)currentIndicator).getOriginalProgressIndicator() : null) { + if (currentIndicator == indicator) { + underCancelledIndicator = true; + break; } } + if (underCancelledIndicator) { threadsUnderCanceledIndicator.add(thread); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java index f1884e98875b..5545d44c9d8a 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/progress/impl/ProgressIndicatorTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.progress.*; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.progress.util.ProgressIndicatorUtils; +import com.intellij.openapi.progress.util.ProgressWrapper; import com.intellij.openapi.progress.util.ReadTask; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; @@ -373,6 +374,34 @@ public class ProgressIndicatorTest extends LightPlatformTestCase { }).assertTiming(); } + public void testWrapperIndicatorGotCanceledTooWhenInnerIndicatorHas() { + final ProgressIndicator progress = new ProgressIndicatorBase(){ + @Override + protected boolean isCancelable() { + return true; + } + }; + try { + ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() { + @Override + public void run() { + assertFalse(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertTrue(!progress.isCanceled()); + progress.cancel(); + assertTrue(ProgressManagerImpl.threadsUnderCanceledIndicator.contains(Thread.currentThread())); + assertTrue(progress.isCanceled()); + while (true) { // wait for PCE + ProgressManager.checkCanceled(); + } + } + }, ProgressWrapper.wrap(progress)); + fail("PCE must have been thrown"); + } + catch (ProcessCanceledException ignored) { + + } + } + private static class ProgressIndicatorStub implements ProgressIndicatorEx { private volatile boolean myCanceled; From 854ad0fd986750fd340397175d7b2e0f70fcaf81 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 18 Nov 2014 12:55:32 +0300 Subject: [PATCH 64/75] cleanup --- .../file/exclude/EnforcedPlainTextFileTypeFactory.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java index 2729a15e40db..d70b45f60f2a 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java @@ -51,10 +51,7 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory { @Override public boolean isMyFileType(@NotNull VirtualFile file) { - if (isMarkedAsPlainText(file)) { - return true; - } - return false; + return isMarkedAsPlainText(file); } @NotNull From 3d7d10faf3f127254676442729a2c2c3685a6a01 Mon Sep 17 00:00:00 2001 From: Alexander Marchuk Date: Tue, 18 Nov 2014 13:47:27 +0300 Subject: [PATCH 65/75] use array Evaluation Expression (now works for dicts, tuples, etc. PY-14421) --- python/helpers/pydev/pydev_console_utils.py | 2 +- python/helpers/pydev/pydevd_comm.py | 6 +++--- .../console/PydevConsoleCommunication.java | 9 +-------- .../debugger/array/AsyncArrayTableModel.java | 2 +- .../debugger/array/NumpyArrayTable.java | 19 +++---------------- 5 files changed, 9 insertions(+), 29 deletions(-) diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py index d12419e19e57..043351587155 100644 --- a/python/helpers/pydev/pydev_console_utils.py +++ b/python/helpers/pydev/pydev_console_utils.py @@ -387,7 +387,7 @@ class BaseInterpreterInterface: def getArray(self, attr, roffset, coffset, rows, cols, format): xml = "" - name = ".".join(attr.split("\t")) + name = attr.split("\t")[-1] array = pydevd_vars.evalInContext(name, self.getNamespace(), self.getNamespace()) if rows == -1 and cols == -1: diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py index 8b7596d5818c..8f5fea6f0fb2 100644 --- a/python/helpers/pydev/pydevd_comm.py +++ b/python/helpers/pydev/pydevd_comm.py @@ -974,15 +974,15 @@ class InternalGetArray(InternalThreadCommand): self.thread_id = thread_id self.frame_id = frame_id self.scope = scope - self.name = ".".join(attrs.split("\t")) + self.name = attrs.split("\t")[-1] self.attrs = attrs self.roffset = int(roffset) self.coffset = int(coffset) self.rows = int(rows) self.cols = int(cols) self.format = format - if hasattr(self.format, 'decode'): - self.format = self.format.decode('utf-8') + if hasattr(self.format, 'encode'): + self.format = self.format.encode('utf-8') def doIt(self, dbg): try: diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java index 6d237301c293..71cef8164bcd 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java @@ -554,14 +554,7 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl throws PyDebuggerException { if (myClient != null) { try { - String fullName = var.getName(); - PyDebugValue child = var; - while (child.getParent() != null) { - child = child.getParent(); - fullName = child.getName() + "\t" + fullName; - } - - Object ret = myClient.execute(GET_ARRAY, new Object[]{fullName, rowOffset, colOffset, rows, cols, format}); + Object ret = myClient.execute(GET_ARRAY, new Object[]{var.getName(), rowOffset, colOffset, rows, cols, format}); if (ret instanceof String) { return ProtocolParser.parseArrayValues((String)ret, this); } diff --git a/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java b/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java index 3eb47155d316..c25ef27b6b17 100644 --- a/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java +++ b/python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java @@ -51,7 +51,7 @@ public class AsyncArrayTableModel extends AbstractTableModel { final PyDebugValue value = myProvider.getDebugValue(); final PyDebugValue slicedValue = new PyDebugValue(myProvider.getSliceText(), value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(), - value.getFrameAccessor()); + value.getParent(), value.getFrameAccessor()); ListenableFutureTask task = ListenableFutureTask.create(new Callable() { @Override diff --git a/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java b/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java index 6a2122e9b7f1..bab68147db79 100644 --- a/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java +++ b/python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java @@ -167,7 +167,7 @@ public class NumpyArrayTable { } public void init() { - init(myValue.getName(), false); + init(getDebugValue().getEvaluationExpression(), false); } public void init(final String slice, final boolean inPlace) { @@ -181,14 +181,8 @@ public class NumpyArrayTable { public void run() { final PyDebugValue value = getDebugValue(); PyDebugValue parent = value.getParent(); - String sl = slice; - - if (slice.contains(".")) { - sl = slice.substring(slice.lastIndexOf(".") + 1); - } - final PyDebugValue slicedValue = - new PyDebugValue(sl, value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(), + new PyDebugValue(slice, value.getType(), value.getValue(), value.isContainer(), value.isErrorOnEval(), parent, value.getFrameAccessor()); final String format = getFormat().isEmpty() ? "%" : getFormat(); @@ -433,14 +427,7 @@ public class NumpyArrayTable { } public String getNodeFullName() { - String fullName = getDebugValue().getName(); - PyDebugValue child = getDebugValue(); - while (child.getParent() != null) { - child = child.getParent(); - fullName = child.getName() + "." + fullName; - } - - return fullName; + return getDebugValue().getEvaluationExpression(); } public String getFormat() { From 4037ebe345aea5f69f317094a2e8a035b969d3b3 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 11:42:34 +0100 Subject: [PATCH 66/75] fixture-based IndexTest --- .../testSrc/com/intellij/index/IndexTest.java | 246 ++++++------------ .../JavaCodeInsightFixtureTestCase.java | 5 +- 2 files changed, 80 insertions(+), 171 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.java b/java/java-tests/testSrc/com/intellij/index/IndexTest.java index 9a0b50ff4871..e88f1692879e 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTest.java +++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.java @@ -15,7 +15,6 @@ */ package com.intellij.index; -import com.intellij.codeInsight.CodeInsightTestCase; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.impl.CurrentEditorProvider; import com.intellij.openapi.command.impl.UndoManagerImpl; @@ -27,15 +26,13 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry; import com.intellij.psi.*; -import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.testFramework.PlatformTestUtil; -import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.indexing.MapIndexStorage; import com.intellij.util.indexing.StorageException; import com.intellij.util.io.*; @@ -51,7 +48,15 @@ import java.util.*; * @author Eugene Zhuravlev * Date: Dec 12, 2007 */ -public class IndexTest extends CodeInsightTestCase { +public class IndexTest extends JavaCodeInsightFixtureTestCase { + @Override + protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception { + if ("testUndoToFileContentForUnsavedCommittedDocument".equals(getName())) { + super.invokeTestRunnable(runnable); + } else { + WriteCommandAction.runWriteCommandAction(getProject(), runnable); + } + } public void testUpdate() throws StorageException, IOException { final File storageFile = FileUtil.createTempFile("indextest", "storage"); @@ -115,7 +120,7 @@ public class IndexTest extends CodeInsightTestCase { } } - private PersistentHashMap> createMetaIndex(File metaIndexFile) throws IOException { + private static PersistentHashMap> createMetaIndex(File metaIndexFile) throws IOException { return new PersistentHashMap>(metaIndexFile, new EnumeratorIntegerDescriptor(), new DataExternalizer>() { @Override public void save(@NotNull DataOutput out, Collection value) throws IOException { @@ -137,233 +142,136 @@ public class IndexTest extends CodeInsightTestCase { }); } - /* - public void testStubIndexUnsavedDocumentsIndexing() throws IncorrectOperationException, IOException, StorageException { - IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new TextStubIndexExtension(), getTestRootDisposable()); - IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new ClassNameStubIndexExtension(), getTestRootDisposable()); - FileTypeManager.getInstance().registerFileType(TestFileType.INSTANCE, "fff"); - final FFFLangParserDefinition parserDefinition = new FFFLangParserDefinition(); - LanguageParserDefinitions.INSTANCE.addExplicitExtension(FFFLanguage.INSTANCE, parserDefinition); - - final TestStubElementType stubType = new TestStubElementType(); - SerializationManager.getInstance().registerSerializer(TestStubElement.class, stubType); - - final File fffFile = new File(FileUtil.createTempDirectory("testing", "stubindex"), "MyClass.fff"); - fffFile.createNewFile(); - - final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fffFile); - - assertNotNull(vFile); - assertEquals(TestFileType.INSTANCE, vFile.getFileType()); - - try { - final MockPsiFile psiFile = new MockPsiFile(vFile, MockPsiManager.getInstance(myProject)); - - final MockPsiClass cls = new MockPsiClass("com.company.MyClass"); - psiFile.add(cls); - - final MockPsiMethod aaaMethod = new MockPsiMethod("aaa"); - cls.addMethod(aaaMethod); - final MockPsiMethod bbbMethod = new MockPsiMethod("bbb"); - cls.addMethod(bbbMethod); - - final PsiFileStubImpl fileStub = new PsiFileStubImpl(psiFile); - final TestStubElement clsStub = stubType.createStub(cls, fileStub); - stubType.createStub(aaaMethod, clsStub); - stubType.createStub(bbbMethod, clsStub); - - final ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); - SerializationManager.getInstance().serialize(fileStub, new DataOutputStream(arrayStream)); - - final FileBasedIndex fbi = FileBasedIndex.getInstance(); - final UpdatableIndex stubUpdatingIndex = fbi.getIndex(StubUpdatingIndex.INDEX_ID); - final MemoryIndexStorage storage = (MemoryIndexStorage)((MapReduceIndex)stubUpdatingIndex).getStorage(); - - // initial - final int fileId = FileBasedIndex.getFileId(vFile); - final byte[] bytes = arrayStream.toByteArray(); - stubUpdatingIndex.update(fileId, new FileContent(vFile, bytes), null); - - final ValueContainer data = stubUpdatingIndex.getData(fileId); - final List trees = data.toValueList(); - - final SerializedStubTree tree = assertOneElement(trees); - - assertTrue(Comparing.equal(bytes, tree.getBytes())); - - final StubElement deserialized = tree.getStub(); - } - finally { - LanguageParserDefinitions.INSTANCE.removeExplicitExtension(FFFLanguage.INSTANCE, parserDefinition); - } - - } - */ - private static void assertDataEquals(List actual, T... expected) { assertTrue(new HashSet(Arrays.asList(expected)).equals(new HashSet(actual))); } public void testCollectedPsiWithChangedDocument() throws IOException { - VirtualFile dir = getVirtualFile(createTempDirectory()); - PsiTestUtil.addSourceContentToRoots(myModule, dir); + final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile(); - final VirtualFile vFile = createChildData(dir, "Foo.java"); - VfsUtil.saveText(vFile, "class Foo {}"); + assertNotNull(findClass("Foo")); + PsiFile psiFile = getPsiManager().findFile(vFile); + assertNotNull(psiFile); - final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); - assertNotNull(myJavaFacade.findClass("Foo", scope)); - WriteCommandAction.runWriteCommandAction(null, new Runnable() { - @Override - public void run() { - PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile); - assertNotNull(psiFile); + Document document = FileDocumentManager.getInstance().getDocument(vFile); + document.deleteString(0, document.getTextLength()); + assertNotNull(findClass("Foo")); - Document document = FileDocumentManager.getInstance().getDocument(vFile); - document.deleteString(0, document.getTextLength()); - assertNotNull(myJavaFacade.findClass("Foo", scope)); + psiFile = null; + PlatformTestUtil.tryGcSoftlyReachableObjects(); + assertNull(getPsiManager().getFileManager().getCachedPsiFile(vFile)); - psiFile = null; - PlatformTestUtil.tryGcSoftlyReachableObjects(); - assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile)); + PsiClass foo = findClass("Foo"); + assertNotNull(foo); + assertTrue(foo.isValid()); + assertEquals("class Foo {}", foo.getText()); + assertTrue(foo.isValid()); - PsiClass foo = myJavaFacade.findClass("Foo", scope); - assertNotNull(foo); - assertTrue(foo.isValid()); - assertEquals("class Foo {}", foo.getText()); - assertTrue(foo.isValid()); - - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - assertNull(myJavaFacade.findClass("Foo", scope)); - } - }); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + assertNull(findClass("Foo")); } public void testCollectedPsiWithDocumentChangedCommittedAndChangedAgain() throws IOException { - VirtualFile dir = getVirtualFile(createTempDirectory()); - PsiTestUtil.addSourceContentToRoots(myModule, dir); + final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile(); - final VirtualFile vFile = createChildData(dir, "Foo.java"); - VfsUtil.saveText(vFile, "class Foo {}"); + assertNotNull(findClass("Foo")); + PsiFile psiFile = getPsiManager().findFile(vFile); + assertNotNull(psiFile); - final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); - assertNotNull(myJavaFacade.findClass("Foo", scope)); - WriteCommandAction.runWriteCommandAction(null, new Runnable() { - @Override - public void run() { - PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile); - assertNotNull(psiFile); + Document document = FileDocumentManager.getInstance().getDocument(vFile); + document.deleteString(0, document.getTextLength()); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + document.insertString(0, " "); + //assertNotNull(myJavaFacade.findClass("Foo", scope)); - Document document = FileDocumentManager.getInstance().getDocument(vFile); - document.deleteString(0, document.getTextLength()); - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - document.insertString(0, " "); - //assertNotNull(myJavaFacade.findClass("Foo", scope)); + psiFile = null; + PlatformTestUtil.tryGcSoftlyReachableObjects(); + assertNull(getPsiManager().getFileManager().getCachedPsiFile(vFile)); - psiFile = null; - PlatformTestUtil.tryGcSoftlyReachableObjects(); - assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile)); + PsiClass foo = findClass("Foo"); + assertNull(foo); + } - PsiClass foo = myJavaFacade.findClass("Foo", scope); - assertNull(foo); - } - }); + private PsiClass findClass(String name) { + return JavaPsiFacade.getInstance(getProject()).findClass(name, GlobalSearchScope.allScope(getProject())); } public void testSavedUncommittedDocument() throws IOException { - VirtualFile dir = getVirtualFile(createTempDirectory()); - PsiTestUtil.addSourceContentToRoots(myModule, dir); + final VirtualFile vFile = myFixture.addFileToProject("Foo.java", "").getVirtualFile(); - final VirtualFile vFile = createChildData(dir, "Foo.java"); - VfsUtil.saveText(vFile, ""); + assertNull(findClass("Foo")); + PsiFile psiFile = getPsiManager().findFile(vFile); + assertNotNull(psiFile); - final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); - assertNull(myJavaFacade.findClass("Foo", scope)); - WriteCommandAction.runWriteCommandAction(null, new Runnable() { - @Override - public void run() { - PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile); - assertNotNull(psiFile); + long count = getPsiManager().getModificationTracker().getModificationCount(); - long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount(); + Document document = FileDocumentManager.getInstance().getDocument(vFile); + document.insertString(0, "class Foo {}"); + FileDocumentManager.getInstance().saveDocument(document); - Document document = FileDocumentManager.getInstance().getDocument(vFile); - document.insertString(0, "class Foo {}"); - FileDocumentManager.getInstance().saveDocument(document); + assertTrue(count == getPsiManager().getModificationTracker().getModificationCount()); + assertNull(findClass("Foo")); - assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount()); - assertNull(myJavaFacade.findClass("Foo", scope)); - - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - assertNotNull(myJavaFacade.findClass("Foo", scope)); - assertNotNull(myJavaFacade.findClass("Foo", scope).getText()); - // if Foo exists now, mod count should be different - assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount()); - } - }); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + assertNotNull(findClass("Foo")); + assertNotNull(findClass("Foo").getText()); + // if Foo exists now, mod count should be different + assertTrue(count != getPsiManager().getModificationTracker().getModificationCount()); } public void testSkipUnknownFileTypes() throws IOException { - VirtualFile dir = getVirtualFile(createTempDirectory()); - PsiTestUtil.addSourceContentToRoots(myModule, dir); - - final VirtualFile vFile = createChildData(dir, "Foo.test"); - VfsUtil.saveText(vFile, "Foo"); + final VirtualFile vFile = myFixture.addFileToProject("Foo.test", "Foo").getVirtualFile(); assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType()); - assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo")); + final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(getProject()); + assertOneElement(helper.findFilesWithPlainTextWords("Foo")); final Document document = FileDocumentManager.getInstance().getDocument(vFile); //todo should file type be changed silently without events? //assertEquals(UnknownFileType.INSTANCE, vFile.getFileType()); - final PsiFile file = getPsiFile(document); + final PsiFile file = PsiDocumentManager.getInstance(getProject()).getPsiFile(document); assertInstanceOf(file, PsiPlainTextFile.class); assertEquals("Foo", file.getText()); - assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo")); + assertOneElement(helper.findFilesWithPlainTextWords("Foo")); - WriteCommandAction.runWriteCommandAction(myProject, new Runnable() { + WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() { @Override public void run() { document.insertString(0, " "); assertEquals("Foo", file.getText()); - assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo")); + assertOneElement(helper.findFilesWithPlainTextWords("Foo")); FileDocumentManager.getInstance().saveDocument(document); assertEquals("Foo", file.getText()); - assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo")); + assertOneElement(helper.findFilesWithPlainTextWords("Foo")); - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); assertEquals(" Foo", file.getText()); - assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo")); + assertOneElement(helper.findFilesWithPlainTextWords("Foo")); } }); } public void testUndoToFileContentForUnsavedCommittedDocument() throws IOException { - VirtualFile dir = getVirtualFile(createTempDirectory()); - PsiTestUtil.addSourceContentToRoots(myModule, dir); - - final VirtualFile vFile = createChildData(dir, "Foo.java"); - VfsUtil.saveText(vFile, "class Foo {}"); + final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile(); ((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file final Document document = FileDocumentManager.getInstance().getDocument(vFile); assertTrue(document != null && document.getModificationStamp() == 0); - final GlobalSearchScope scope = GlobalSearchScope.projectScope(myProject); - assertNotNull(myJavaFacade.findClass("Foo", scope)); + assertNotNull(findClass("Foo")); - WriteCommandAction.runWriteCommandAction(myProject, new Runnable() { + WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() { @Override public void run() { document.insertString(0, "import Bar;\n"); - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); - assertNotNull(myJavaFacade.findClass("Foo", scope)); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + assertNotNull(findClass("Foo")); } }); final UndoManager undoManager = UndoManager.getInstance(getProject()); - final FileEditor selectedEditor = FileEditorManager.getInstance(myProject).openFile(vFile, false)[0]; + final FileEditor selectedEditor = FileEditorManager.getInstance(getProject()).openFile(vFile, false)[0]; ((UndoManagerImpl)undoManager).setEditorProvider(new CurrentEditorProvider() { @Override public FileEditor getCurrentEditor() { @@ -375,6 +283,6 @@ public class IndexTest extends CodeInsightTestCase { FileDocumentManager.getInstance().saveDocument(document); undoManager.undo(selectedEditor); - assertNotNull(myJavaFacade.findClass("Foo", scope)); + assertNotNull(findClass("Foo")); } } diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightFixtureTestCase.java b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightFixtureTestCase.java index 6262638088f6..22a514a3903a 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightFixtureTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightFixtureTestCase.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiManager; +import com.intellij.psi.impl.PsiManagerEx; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; @@ -105,8 +106,8 @@ public abstract class JavaCodeInsightFixtureTestCase extends UsefulTestCase{ return myFixture.getProject(); } - protected PsiManager getPsiManager() { - return PsiManager.getInstance(getProject()); + protected PsiManagerEx getPsiManager() { + return (PsiManagerEx)PsiManager.getInstance(getProject()); } public PsiElementFactory getElementFactory() { From 8cb24d9b5c9e05ae36124c94a3c11d39feb6277c Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 11:44:52 +0100 Subject: [PATCH 67/75] IndexTest -> groovy --- .../{IndexTest.java => IndexTest.groovy} | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) rename java/java-tests/testSrc/com/intellij/index/{IndexTest.java => IndexTest.groovy} (89%) diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.java b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy similarity index 89% rename from java/java-tests/testSrc/com/intellij/index/IndexTest.java rename to java/java-tests/testSrc/com/intellij/index/IndexTest.groovy index e88f1692879e..ed1efa093b33 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTest.java +++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy @@ -13,37 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.index; - -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.command.impl.CurrentEditorProvider; -import com.intellij.openapi.command.impl.UndoManagerImpl; -import com.intellij.openapi.command.undo.UndoManager; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileTypes.PlainTextFileType; -import com.intellij.openapi.util.Factory; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PsiSearchHelper; -import com.intellij.testFramework.PlatformTestUtil; -import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; -import com.intellij.util.indexing.MapIndexStorage; -import com.intellij.util.indexing.StorageException; -import com.intellij.util.io.*; -import org.jetbrains.annotations.NotNull; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.File; -import java.io.IOException; -import java.util.*; - +package com.intellij.index +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.command.impl.CurrentEditorProvider +import com.intellij.openapi.command.impl.UndoManagerImpl +import com.intellij.openapi.command.undo.UndoManager +import com.intellij.openapi.editor.Document +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.FileEditor +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileTypes.PlainTextFileType +import com.intellij.openapi.util.Factory +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry +import com.intellij.psi.* +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiSearchHelper +import com.intellij.testFramework.PlatformTestUtil +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase +import com.intellij.util.indexing.MapIndexStorage +import com.intellij.util.indexing.StorageException +import com.intellij.util.io.* +import org.jetbrains.annotations.NotNull /** * @author Eugene Zhuravlev * Date: Dec 12, 2007 @@ -131,11 +123,11 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase { } @Override - public Collection read(@NotNull DataInput in) throws IOException { - final int size = DataInputOutputUtil.readINT(in); + public Collection read(@NotNull DataInput _in) throws IOException { + final int size = DataInputOutputUtil.readINT(_in); final List list = new ArrayList(); for (int idx = 0; idx < size; idx++) { - list.add(in.readUTF()); + list.add(_in.readUTF()); } return list; } From 43dfc060abaeddcfdc42809eeaee0b88ae0a1848 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Nov 2014 11:47:49 +0100 Subject: [PATCH 68/75] merge IndexGeneratedTest into IndexTest --- .../intellij/index/IndexGeneratedTest.groovy | 57 ------------------- .../com/intellij/index/IndexTest.groovy | 25 ++++++++ .../intellij/index/IndexTestGenerator.scala | 7 ++- 3 files changed, 30 insertions(+), 59 deletions(-) delete mode 100644 java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy diff --git a/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy b/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy deleted file mode 100644 index 8e06c9bdf5a4..000000000000 --- a/java/java-tests/testSrc/com/intellij/index/IndexGeneratedTest.groovy +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.index -import com.intellij.openapi.command.WriteCommandAction -import com.intellij.openapi.fileEditor.FileDocumentManager -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiFile -import com.intellij.psi.impl.PsiManagerEx -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.testFramework.PlatformTestUtil -import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase -import com.intellij.util.TimeoutUtil - -class IndexGeneratedTest extends JavaCodeInsightFixtureTestCase { - protected void invokeTestRunnable(Runnable runnable) { - WriteCommandAction.runWriteCommandAction(project, runnable) - } - - public void "test changing a file without psi makes the document committed and updates index"() { - def psiFile = myFixture.addFileToProject("Foo.java", "class Foo {}") - def vFile = psiFile.virtualFile - def scope = GlobalSearchScope.allScope(project) - - FileDocumentManager.instance.getDocument(vFile).text = "import zoo.Zoo; class Foo1 {}" - assert PsiDocumentManager.getInstance(project).uncommittedDocuments - psiFile = null - - PlatformTestUtil.tryGcSoftlyReachableObjects() - - assert !((PsiManagerEx) psiManager).fileManager.getCachedPsiFile(vFile) - - FileDocumentManager.instance.saveAllDocuments() - - VfsUtil.saveText(vFile, "class Foo3 {}") - - assert !PsiDocumentManager.getInstance(project).uncommittedDocuments - - assert JavaPsiFacade.getInstance(project).findClass("Foo3", scope) - } - - -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy index ed1efa093b33..64492f94d62a 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy +++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy @@ -25,9 +25,11 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.util.Factory import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry import com.intellij.psi.* +import com.intellij.psi.impl.PsiManagerEx import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.PsiSearchHelper import com.intellij.testFramework.PlatformTestUtil @@ -277,4 +279,27 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase { assertNotNull(findClass("Foo")); } + + public void "test changing a file without psi makes the document committed and updates index"() { + def psiFile = myFixture.addFileToProject("Foo.java", "class Foo {}") + def vFile = psiFile.virtualFile + def scope = GlobalSearchScope.allScope(project) + + FileDocumentManager.instance.getDocument(vFile).text = "import zoo.Zoo; class Foo1 {}" + assert PsiDocumentManager.getInstance(project).uncommittedDocuments + psiFile = null + + PlatformTestUtil.tryGcSoftlyReachableObjects() + + assert !((PsiManagerEx) psiManager).fileManager.getCachedPsiFile(vFile) + + FileDocumentManager.instance.saveAllDocuments() + + VfsUtil.saveText(vFile, "class Foo3 {}") + + assert !PsiDocumentManager.getInstance(project).uncommittedDocuments + + assert JavaPsiFacade.getInstance(project).findClass("Foo3", scope) + } + } diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTestGenerator.scala b/java/java-tests/testSrc/com/intellij/index/IndexTestGenerator.scala index ae6727bd9928..98d0268adfba 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTestGenerator.scala +++ b/java/java-tests/testSrc/com/intellij/index/IndexTestGenerator.scala @@ -25,8 +25,11 @@ import org.scalacheck._ import scala.collection.JavaConversions._ /** - * Run this class to generate randomized tests for IDEA VFS/document/PSI/index subsystem interaction using ScalaCheck. - * When a test fails, a test method code (in Groovy) is printed which should be copied to a normal test class and debugged there. + * Run this class to generate randomized tests for IDEA VFS/document/PSI/index subsystem interaction using ScalaCheck.

+ * + * When a test fails, a test method code (in Groovy) is printed which should be copied to a normal test class (IndexTest) + * and debugged there.

+ * * The generated test may contain some excessive declarations and checks that should be corrected manually. * After the fix, that generated test should be renamed according to the underlying issue it found and committed to the repository. * From ea8a4bf27ffe18543119051c32b7c04b552522e1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 18 Nov 2014 14:00:17 +0300 Subject: [PATCH 69/75] IDEA-75013 Create "Duplicate" (Ctrl+D) action for watch expression --- .../impl/frame/XWatchesViewImpl.java | 3 ++ .../frame/actions/XDuplicateWatchAction.java | 45 +++++++++++++++++++ .../frame/actions/XWatchesTreeActionBase.java | 1 + 3 files changed, 49 insertions(+) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XDuplicateWatchAction.java diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java index 8b94e2c4858a..a1d9e1ef39aa 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -40,6 +40,7 @@ import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; +import com.intellij.xdebugger.impl.frame.actions.XDuplicateWatchAction; import com.intellij.xdebugger.impl.ui.XDebugSessionData; import com.intellij.xdebugger.impl.ui.XDebugSessionTab; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -88,6 +89,8 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree); + new XDuplicateWatchAction().registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_DUPLICATE).getShortcutSet(), tree); + DnDManager.getInstance().registerTarget(this, tree); myRootNode = new WatchesRootNode(tree, this, session.getSessionData().getWatchExpressions()); tree.setRoot(myRootNode, false); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XDuplicateWatchAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XDuplicateWatchAction.java new file mode 100644 index 000000000000..d29545d3deaf --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XDuplicateWatchAction.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.impl.frame.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.xdebugger.impl.frame.XWatchesView; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; +import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author 1 + */ +public class XDuplicateWatchAction extends XWatchesTreeActionBase { + + protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) { + return !getSelectedNodes(tree, WatchNode.class).isEmpty(); + } + + @Override + protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { + XDebuggerTreeNode root = tree.getRoot(); + List nodes = getSelectedNodes(tree, WatchNode.class); + for (WatchNode node : nodes) { + int index = root.getIndex(node); + watchesView.addWatchExpression(node.getExpression(), index + 1, true); + } + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java index e35ab54f1fe5..297d66a4f55a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java @@ -30,6 +30,7 @@ import java.util.List; * @author nik */ public abstract class XWatchesTreeActionBase extends AnAction { + @NotNull protected static List getSelectedNodes(final @NotNull XDebuggerTree tree, Class nodeClass) { List list = new ArrayList(); TreePath[] selectionPaths = tree.getSelectionPaths(); From 5a1e543910bee226db067fca021ac12e418a1366 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 18 Nov 2014 15:16:10 +0300 Subject: [PATCH 70/75] fix version info in remote debugger for comparison and warning message --- .../com/jetbrains/python/debugger/pydev/RemoteDebugger.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 11cc0d798e58..4459d2e7d4cc 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -109,7 +109,11 @@ public class RemoteDebugger implements ProcessDebugger { public String handshake() throws PyDebuggerException { final VersionCommand command = new VersionCommand(this, LOCAL_VERSION, SystemInfo.isUnix ? "UNIX" : "WIN"); command.execute(); - return command.getRemoteVersion(); + String version = command.getRemoteVersion(); + if (version != null) { + version = version.trim(); + } + return version; } @Override From 2a4ce79c5b141e0c345b3093439818afc5583f29 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 18 Nov 2014 15:34:57 +0300 Subject: [PATCH 71/75] IDEA-103464 Adding environment variables to a Tomcat server is a UX nightmare After-review changes --- .../src/com/intellij/ui/ToolbarDecorator.java | 10 +++++----- .../packaging/JavaFxArtifactPropertiesEditor.java | 2 +- .../tasks/generic/ManageTemplateVariablesDialog.java | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java index 853a9724d63d..6964d66d4ef0 100644 --- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java @@ -190,16 +190,16 @@ public abstract class ToolbarDecorator implements CommonActionsPanel.ListenerFac return setToolbarBorder(new CustomLineBorder(top, left, bottom, right)); } - public ToolbarDecorator addExtraAction(AnActionButton action) { - if (action != null) { - myExtraActions.add(action); - } + public ToolbarDecorator addExtraAction(@NotNull AnActionButton action) { + myExtraActions.add(action); return this; } public ToolbarDecorator addExtraActions(AnActionButton... actions) { for (AnActionButton action : actions) { - addExtraAction(action); + if (action != null) { + addExtraAction(action); + } } return this; } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java index e4a7b47b673c..da7ac9794849 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java @@ -317,7 +317,7 @@ public class JavaFxArtifactPropertiesEditor extends ArtifactPropertiesEditor { @Override protected boolean isEmpty(JavaFxManifestAttribute element) { - return element.getName().isEmpty() && element.getValue().isEmpty(); + return StringUtil.isEmpty(element.getName()) && StringUtil.isEmpty(element.getValue()); } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java index ebb8bd39997b..17d966b65d3e 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java @@ -2,6 +2,7 @@ package com.intellij.tasks.generic; import com.intellij.execution.util.ListTableWithButtons; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; @@ -208,7 +209,7 @@ public class ManageTemplateVariablesDialog extends DialogWrapper { @Override protected boolean isEmpty(TemplateVariable element) { - return element.getName().isEmpty() && element.getValue().isEmpty(); + return StringUtil.isEmpty(element.getName()) && StringUtil.isEmpty(element.getValue()); } @Override From ee299a720ad541ef8ddffd299e37407c1938f14b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 18 Nov 2014 15:49:24 +0300 Subject: [PATCH 72/75] fixed PY-14433 Fill Paragraph: Invalid range specified: (504,502); Throwable at com.intellij.openapi.util.TextRange.assertProperRange --- .../editorActions/fillParagraph/ParagraphFillHandler.java | 5 +++-- python/testData/fillParagraph/emptyMultilineString.py | 3 +++ python/testData/fillParagraph/emptyMultilineString_after.py | 3 +++ python/testSrc/com/jetbrains/python/PyFillParagraphTest.java | 5 ++++- 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 python/testData/fillParagraph/emptyMultilineString.py create mode 100644 python/testData/fillParagraph/emptyMultilineString_after.py diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java index 3aeefefd55ec..930148b05e5c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java @@ -4,6 +4,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.UnfairTextRange; import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -82,7 +83,7 @@ public class ParagraphFillHandler { private TextRange getTextRange(@NotNull final PsiElement element, @NotNull final Editor editor) { int startOffset = getStartOffset(element, editor); int endOffset = getEndOffset(element, editor); - return TextRange.create(startOffset, endOffset); + return new UnfairTextRange(startOffset, endOffset); } private int getStartOffset(@NotNull final PsiElement element, @NotNull final Editor editor) { @@ -105,7 +106,7 @@ public class ParagraphFillHandler { } lineNumber -= 1; } - final int lineStartOffset = document.getLineStartOffset(lineNumber); + final int lineStartOffset = lineNumber == document.getLineNumber(elementTextOffset) ? elementTextOffset : document.getLineStartOffset(lineNumber); final String lineText = document .getText(TextRange.create(lineStartOffset, document.getLineEndOffset(lineNumber))); int shift = StringUtil.findFirst(lineText, CharFilter.NOT_WHITESPACE_FILTER); diff --git a/python/testData/fillParagraph/emptyMultilineString.py b/python/testData/fillParagraph/emptyMultilineString.py new file mode 100644 index 000000000000..5180c20fbd92 --- /dev/null +++ b/python/testData/fillParagraph/emptyMultilineString.py @@ -0,0 +1,3 @@ +a = """ + +""" \ No newline at end of file diff --git a/python/testData/fillParagraph/emptyMultilineString_after.py b/python/testData/fillParagraph/emptyMultilineString_after.py new file mode 100644 index 000000000000..277257c94d71 --- /dev/null +++ b/python/testData/fillParagraph/emptyMultilineString_after.py @@ -0,0 +1,3 @@ +a = """ + +""" \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyFillParagraphTest.java b/python/testSrc/com/jetbrains/python/PyFillParagraphTest.java index 287c65f9e8a1..0fd99a9772b7 100644 --- a/python/testSrc/com/jetbrains/python/PyFillParagraphTest.java +++ b/python/testSrc/com/jetbrains/python/PyFillParagraphTest.java @@ -20,7 +20,6 @@ import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.jetbrains.python.fixtures.PyTestCase; @@ -62,6 +61,10 @@ public class PyFillParagraphTest extends PyTestCase { doTest(); } + public void testEmptyMultilineString() { + doTest(); + } + public void testEnter() { final CommonCodeStyleSettings settings = CodeStyleSettingsManager.getInstance(myFixture.getProject()).getCurrentSettings().getCommonSettings(PythonLanguage.getInstance()); From 611af8fc410d034e8ac0daa214e83ec53dfc509c Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 18 Nov 2014 15:53:17 +0300 Subject: [PATCH 73/75] IDEA-129333 Code folding and "Navigate" actions don't mix well --- .../com/intellij/openapi/editor/impl/CaretImpl.java | 7 ++++--- .../intellij/openapi/editor/impl/EditorImplTest.java | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index ca6de1b8c65f..344399ead910 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -525,10 +525,9 @@ public class CaretImpl extends UserDataHolderBase implements Caret { else { logicalPositionToUse = new LogicalPosition(line, column); } - setCurrentLogicalCaret(logicalPositionToUse); - final int offset = myEditor.logicalPositionToOffset(myLogicalCaret); + final int offset = myEditor.logicalPositionToOffset(logicalPositionToUse); if (debugBuffer != null) { - debugBuffer.append("Resulting logical position to use: ").append(myLogicalCaret).append(". It's mapped to offset ").append(offset).append("\n"); + debugBuffer.append("Resulting logical position to use: ").append(logicalPositionToUse).append(". It's mapped to offset ").append(offset).append("\n"); } FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset); @@ -554,8 +553,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret { finally { mySkipChangeRequests = false; } + logicalPositionToUse = logicalPositionToUse.visualPositionAware ? logicalPositionToUse.withoutVisualPositionInfo() : logicalPositionToUse; } + setCurrentLogicalCaret(logicalPositionToUse); setLastColumnNumber(myLogicalCaret.column); myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1; myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java index c999c6dfed37..ee1575e88dc7 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java @@ -111,6 +111,16 @@ public class EditorImplTest extends AbstractEditorTest { assertEquals(new VisualPosition(0, 5), myEditor.logicalToVisualPosition(new LogicalPosition(0, 3))); } + + public void testNavigationIntoFoldedRegionWithSoftWrapsEnabled() throws Exception { + init("something"); + addCollapsedFoldRegion(4, 8, "..."); + EditorTestUtil.configureSoftWraps(myEditor, 1000); + + myEditor.getCaretModel().moveToOffset(5); + + assertEquals(new VisualPosition(0, 5), myEditor.getCaretModel().getVisualPosition()); + } private void init(String text) throws IOException { configureFromFileText(getTestName(false) + ".txt", text); From 2fe7261fcaa61816834ac18afbbf7397d0c7c7f4 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 18 Nov 2014 15:53:46 +0300 Subject: [PATCH 74/75] cleanup --- .../src/com/intellij/openapi/editor/impl/CaretImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index 344399ead910..b66cd66eaf77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -749,8 +749,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret { } } - private void assertIsDispatchThread() { - myEditor.assertIsDispatchThread(); + private static void assertIsDispatchThread() { + EditorImpl.assertIsDispatchThread(); } private void validateCallContext() { From 02c233ab0110cc1968e55279844fa2b64af546ca Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 18 Nov 2014 15:59:20 +0300 Subject: [PATCH 75/75] IDEA-131435 Debugger: quick evaluate: array initializer is suggested, but reported invalid --- .../engine/evaluation/expression/EvaluatorBuilderImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index faf69aaee937..8115aac74c79 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -1249,6 +1249,11 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } } myResult = new ArrayInitializerEvaluator(evaluators); + if (!(expression.getParent() instanceof PsiNewExpression)) { + myResult = new NewArrayInstanceEvaluator(new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(type)), + null, + myResult); + } } @Nullable