From 5d4b6480f3a4fe9449ab301fd4345f143daf0312 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 13:43:39 +0100 Subject: [PATCH 01/49] IOOBE: do not position caret in another editor --- .../intellij/codeInsight/daemon/impl/quickfix/AddMethodFix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodFix.java index cb1ef9f2c3af..cabd88cbd5d6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodFix.java @@ -120,7 +120,7 @@ public class AddMethodFix extends LocalQuickFixAndIntentionActionOnPsiElement { } PsiMethod method = (PsiMethod)myClass.add(myMethodPrototype); method = (PsiMethod)method.replace(reformat(project, method)); - if (editor != null) { + if (editor != null && method.getContainingFile() == file) { GenerateMembersUtil.positionCaret(editor, method, true); } } From f005ef058feef54d6af942ac182e99763a213924 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 13:44:50 +0100 Subject: [PATCH 02/49] logging for EA-31078 - IAE: PsiIdentifierImpl.replace --- .../impl/quickfix/CreateConstructorMatchingSuperFix.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorMatchingSuperFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorMatchingSuperFix.java index 0a33347490cd..c512bd51934f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorMatchingSuperFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorMatchingSuperFix.java @@ -126,7 +126,9 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction { } } - derived.getNameIdentifier().replace(targetClass.getNameIdentifier()); + final PsiIdentifier identifier = targetClass.getNameIdentifier(); + LOG.assertTrue(identifier != null, targetClass); + derived.getNameIdentifier().replace(identifier); @NonNls StringBuffer buffer = new StringBuffer(); buffer.append("void foo () {\nsuper("); From d2ba465afa47c69604a79bbd2c28c8b58e934dc8 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 15:38:32 +0100 Subject: [PATCH 03/49] pluralize in upper case (IDEA-78999) --- .../util/src/com/intellij/openapi/util/text/StringUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 24a42c481a60..c71ed0094d4a 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -756,12 +756,12 @@ public class StringUtil { return suggestion + "ren"; } - if (endsWithChar(suggestion, 's') || endsWithChar(suggestion, 'x') || suggestion.endsWith("ch")) { + if (endsWithIgnoreCase(suggestion, "s") || endsWithIgnoreCase(suggestion, "x") || endsWithIgnoreCase(suggestion, "ch")) { return suggestion + "es"; } int len = suggestion.length(); - if (endsWithChar(suggestion, 'y') && len > 1 && !isVowel(suggestion.charAt(len - 2))) { + if (endsWithIgnoreCase(suggestion, "y") && len > 1 && !isVowel(toLowerCase(suggestion.charAt(len - 2)))) { return suggestion.substring(0, len - 1) + "ies"; } From 43e8f7a75d0bd5e814d2730a1fd2b7285f294184 Mon Sep 17 00:00:00 2001 From: Nikolay Matveev Date: Thu, 15 Dec 2011 18:51:57 +0400 Subject: [PATCH 04/49] PHP length of the usages group id should be less then 30 --- .../TemporaryRunConfigurationTypeUsagesCollector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/statistics/TemporaryRunConfigurationTypeUsagesCollector.java b/platform/lang-impl/src/com/intellij/execution/impl/statistics/TemporaryRunConfigurationTypeUsagesCollector.java index 1ab9ef586bc1..bc6efca0a00c 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/statistics/TemporaryRunConfigurationTypeUsagesCollector.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/statistics/TemporaryRunConfigurationTypeUsagesCollector.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull; */ public class TemporaryRunConfigurationTypeUsagesCollector extends AbstractRunConfigurationTypeUsagesCollector { - private static final GroupDescriptor GROUP_ID = GroupDescriptor.create("run-configuration-type-temporary"); + private static final GroupDescriptor GROUP_ID = GroupDescriptor.create("run-configuration-type-temp"); @NotNull @Override From 8792526875bc78a034fddda5470eccbc0aebe7c6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 19 Dec 2011 15:39:19 +0400 Subject: [PATCH 05/49] cleanup --- .../project/impl/ProjectManagerImpl.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 213c143323da..eb164b92e414 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -121,6 +121,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt MessageBus messageBus = app.getMessageBus(); MessageBusConnection connection = messageBus.connect(app); connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() { + @Override public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) { VirtualFile file = event.getFile(); LOG.debug("[RELOAD] Storage file changed: " + file.getPath()); @@ -133,10 +134,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt addProjectManagerListener( new ProjectManagerListener() { + @Override public void projectOpened(final Project project) { MessageBus messageBus = project.getMessageBus(); MessageBusConnection connection = messageBus.connect(project); connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() { + @Override public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) { VirtualFile file = event.getFile(); if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) { @@ -151,6 +154,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public void projectClosed(Project project) { busPublisher.projectClosed(project); for (ProjectManagerListener listener : getListeners(project)) { @@ -158,6 +162,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public boolean canCloseProject(Project project) { for (ProjectManagerListener listener : getListeners(project)) { if (!listener.canCloseProject(project)) { @@ -167,6 +172,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return true; } + @Override public void projectClosing(Project project) { busPublisher.projectClosing(project); for (ProjectManagerListener listener : getListeners(project)) { @@ -179,10 +185,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt registerExternalProjectFileListener(virtualFileManagerEx); } + @Override public void disposeComponent() { Disposer.dispose(myChangedFilesAlarm); if (myDefaultProject != null) { ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { Disposer.dispose(myDefaultProject); } @@ -193,9 +201,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public void initComponent() { } + @Override @Nullable public Project newProject(final String projectName, String filePath, boolean useDefaultProjectSettings, boolean isDummy) { filePath = canonicalize(filePath); @@ -283,8 +293,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt private static void scheduleDispose(final ProjectImpl project) { ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { if (!project.isDisposed()) { Disposer.dispose(project); @@ -295,6 +307,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt }); } + @Override @Nullable public Project loadProject(String filePath) throws IOException, JDOMException, InvalidDataException { try { @@ -333,6 +346,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt public synchronized boolean isDefaultProjectInitialized() { return myDefaultProject != null; } + @Override @NotNull public synchronized Project getDefaultProject() { LOG.assertTrue(!myDefaultProjectWasDisposed, "Default project has been already disposed!"); @@ -357,6 +371,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return myDefaultProjectRootElement; } + @Override @NotNull public Project[] getOpenProjects() { if (myOpenProjectsArrayCache.length != myOpenProjects.size()) { @@ -374,6 +389,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return myOpenProjectsArrayCache; } + @Override public boolean isProjectOpened(Project project) { if (ApplicationManager.getApplication().isUnitTestMode() && myCurrentTestProject != null) { return project == myCurrentTestProject || myOpenProjects.contains(project); @@ -381,6 +397,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return myOpenProjects.contains(project); } + @Override public boolean openProject(final Project project) { final Application application = ApplicationManager.getApplication(); @@ -403,6 +420,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final StartupManagerImpl startupManager = (StartupManagerImpl)StartupManager.getInstance(project); boolean ok = myProgressManager.runProcessWithProgressSynchronously(new Runnable() { + @Override public void run() { startupManager.runStartupActivities(); @@ -410,6 +428,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt // only when startCacheUpdate is called from UI thread, we can guarantee that // when the method returns, the application has entered dumb mode UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override public void run() { startupManager.startCacheUpdate(); } @@ -418,6 +437,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt startupManager.runPostStartupActivitiesFromExtensions(); UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override public void run() { startupManager.runPostStartupActivities(); } @@ -434,6 +454,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) { // should be invoked last StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { + @Override public void run() { final TrackingPathMacroSubstitutor macroSubstitutor = ((ProjectEx)project).getStateStore().getStateStorageManager().getMacroSubstitutor(); @@ -451,6 +472,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myOpenProjectsArrayCache = myOpenProjects.toArray(new Project[myOpenProjects.size()]); } + @Override public Project loadAndOpenProject(@NotNull final String filePath) throws IOException { final Project project = convertAndLoadProject(filePath); @@ -462,6 +484,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt if (!openProject(project)) { showWelcomeScreenIfNoProjectOpened(); ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { Disposer.dispose(project); } @@ -498,6 +521,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt if (!conversionResult.conversionNotNeeded()) { StartupManager.getInstance(project).registerPostStartupActivity(new Runnable() { + @Override public void run() { conversionResult.postStartupActivity(project); } @@ -519,6 +543,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final ProjectImpl project = createProject(null, canonicalize(filePath), false, false); try { myProgressManager.runProcessWithProgressSynchronously(new ThrowableComputable() { + @Override @Nullable public Project compute() throws IOException { doLoadProject(filePath, project); @@ -572,9 +597,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt private void registerExternalProjectFileListener(VirtualFileManagerEx virtualFileManager) { virtualFileManager.addVirtualFileManagerListener(new VirtualFileManagerListener() { + @Override public void beforeRefreshStart(boolean asynchonous) { } + @Override public void afterRefreshFinish(boolean asynchonous) { scheduleReloadApplicationAndProject(); } @@ -618,6 +645,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final LinkedHashSet components = new LinkedHashSet(); ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { try { reloadOk[0] = ((ApplicationImpl)app).getStateStore().reload(causes, components); @@ -684,6 +712,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final boolean[] reloadOk = {false}; ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { try { LOG.debug("[RELOAD] Reloading project/components..."); @@ -725,14 +754,17 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt Messages.getQuestionIcon()) == 0; } + @Override public boolean isFileSavedToBeReloaded(VirtualFile candidate) { return mySavedCopies.containsKey(candidate); } + @Override public void blockReloadingProjectOnExternalChanges() { myReloadBlockCount.incrementAndGet(); } + @Override public void unblockReloadingProjectOnExternalChanges() { if (myReloadBlockCount.decrementAndGet() == 0) scheduleReloadApplicationAndProject(); } @@ -748,6 +780,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt // public void run() { // IdeEventQueue.getInstance().removeIdleListener(this); ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { if (!tryToReloadApplication()) return; askToReloadProjectIfConfigFilesChangedExternally(); @@ -759,17 +792,20 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt //}, ModalityState.NON_MODAL); } + @Override public void setCurrentTestProject(@Nullable final Project project) { assert ApplicationManager.getApplication().isUnitTestMode(); myCurrentTestProject = project; } + @Override @Nullable public Project getCurrentTestProject() { assert ApplicationManager.getApplication().isUnitTestMode(); return myCurrentTestProject; } + @Override public void saveChangedProjectFile(final VirtualFile file, final Project project) { if (file.exists()) { copyToTemp(file); @@ -813,6 +849,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myChangedFilesAlarm.cancelAllRequests(); myChangedFilesAlarm.addRequest(new Runnable() { + @Override public void run() { LOG.debug("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount); if (myReloadBlockCount.get() == 0) { @@ -855,6 +892,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public void reloadProject(@NotNull final Project p) { reloadProjectImpl(p, true, false); } @@ -874,6 +912,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final Application application = ApplicationManager.getApplication(); application.invokeLater(new Runnable() { + @Override public void run() { LOG.debug("Reloading project."); ProjectImpl projectImpl = (ProjectImpl)project[0]; @@ -894,6 +933,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt if (project[0].isDisposed() || ProjectUtil.closeAndDispose(project[0])) { application.runWriteAction(new Runnable() { + @Override public void run() { for (final IFile originalFile : original) { restoreCopy(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(originalFile)); @@ -915,6 +955,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } */ + @Override public boolean closeProject(@NotNull final Project project) { return closeProject(project, true, false); } @@ -940,6 +981,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt fireProjectClosing(project); // somebody can start progress here, do not wrap in write action ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { myOpenProjects.remove(project); cacheOpenProjects(); @@ -982,6 +1024,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public void addProjectManagerListener(@NotNull ProjectManagerListener listener) { myListeners.add(listener); } @@ -997,11 +1040,13 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt }); } + @Override public void removeProjectManagerListener(@NotNull ProjectManagerListener listener) { boolean removed = myListeners.remove(listener); LOG.assertTrue(removed); } + @Override public void addProjectManagerListener(@NotNull Project project, @NotNull ProjectManagerListener listener) { List listeners = project.getUserData(LISTENERS_IN_PROJECT_KEY); if (listeners == null) { @@ -1010,6 +1055,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt listeners.add(listener); } + @Override public void removeProjectManagerListener(@NotNull Project project, @NotNull ProjectManagerListener listener) { List listeners = project.getUserData(LISTENERS_IN_PROJECT_KEY); if (listeners != null) { @@ -1051,6 +1097,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } + @Override public boolean canClose(Project project) { if (LOG.isDebugEnabled()) { LOG.debug("enter: canClose()"); @@ -1080,6 +1127,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt Messages.getWarningIcon()) == 0; } + @Override public void writeExternal(Element parentNode) throws WriteExternalException { if (myDefaultProject != null) { myDefaultProject.save(); @@ -1098,6 +1146,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myDefaultProjectRootElement = defaultProjectRootElement; } + @Override public void readExternal(Element parentNode) throws InvalidDataException { myDefaultProjectRootElement = parentNode.getChild(ELEMENT_DEFAULT_PROJECT); @@ -1108,20 +1157,24 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myDefaultProjectRootElement.detach(); } + @Override public String getExternalFileName() { return "project.default"; } + @Override @NotNull public String getComponentName() { return "ProjectManager"; } + @Override @NotNull public File[] getExportFiles() { return new File[]{PathManager.getOptionsFile(this)}; } + @Override @NotNull public String getPresentableName() { return ProjectBundle.message("project.default.settings"); From e69f7cbcda09b9a463dbaf912034481b70bca85b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 14:46:19 +0400 Subject: [PATCH 06/49] disabled check for leaked projects --- .../src/com/intellij/testFramework/PlatformTestCase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 4bc0414fae23..c7a3c088f4d3 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -41,7 +41,6 @@ import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.impl.ModuleManagerImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectManagerEx; -import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.project.impl.TooManyProjectLeakedException; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModifiableRootModel; @@ -68,7 +67,6 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; import com.intellij.util.PatchedWeakReference; -import com.intellij.util.Processor; import com.intellij.util.indexing.IndexableSetContributor; import com.intellij.util.indexing.IndexedRootsProvider; import com.intellij.util.ui.UIUtil; @@ -617,7 +615,8 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro throw IdeaLogger.ourErrorsOccurred; } - if (++LEAK_WALKS % 1000 == 0) { + /* + if (++LEAK_WALKS % 1 == 0) { LeakHunter.checkLeak(ApplicationManager.getApplication(), ProjectImpl.class, new Processor() { @Override public boolean process(ProjectImpl project) { @@ -625,6 +624,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro } }); } + */ } private static int LEAK_WALKS; From 7e4d04ec2955345a59d4db31af187f1b35f2f0a9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 16:50:26 +0400 Subject: [PATCH 07/49] cleanup --- .../actions/AbstractLayoutCodeProcessor.java | 11 +++++++++ .../openapi/vfs/newvfs/RefreshQueue.java | 10 ++++---- .../openapi/vfs/newvfs/RefreshSession.java | 2 +- .../application/impl/ModalityStateEx.java | 3 ++- .../openapi/vfs/newvfs/RefreshQueueImpl.java | 23 ++++++++++--------- .../vfs/newvfs/RefreshSessionImpl.java | 4 +++- .../ExternalChangesAndRefreshingTest.java | 2 +- 7 files changed, 36 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 1be1f4e83413..7dc21a333c96 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -194,6 +194,7 @@ public abstract class AbstractLayoutCodeProcessor { final Runnable[] resultRunnable = new Runnable[1]; Runnable readAction = new Runnable() { + @Override public void run() { if (!checkFileWritable(file)) return; try{ @@ -205,6 +206,7 @@ public abstract class AbstractLayoutCodeProcessor { } }; Runnable writeAction = new Runnable() { + @Override public void run() { if (resultRunnable[0] != null) { resultRunnable[0].run(); @@ -261,6 +263,7 @@ public abstract class AbstractLayoutCodeProcessor { } return new Runnable() { + @Override public void run() { SequentialModalProgressTask progressTask = new SequentialModalProgressTask(myProject, myCommandName); ReformatFilesTask reformatFilesTask = new ReformatFilesTask(tasks); @@ -277,11 +280,13 @@ public abstract class AbstractLayoutCodeProcessor { final Runnable[] resultRunnable = new Runnable[1]; runLayoutCodeProcess( new Runnable() { + @Override public void run() { resultRunnable[0] = preprocessFiles(new ArrayList(Arrays.asList(files))); } }, new Runnable() { + @Override public void run() { if (resultRunnable[0] != null){ resultRunnable[0].run(); @@ -352,10 +357,12 @@ public abstract class AbstractLayoutCodeProcessor { final Runnable[] resultRunnable = new Runnable[1]; runLayoutCodeProcess(new Runnable() { + @Override public void run() { resultRunnable[0] = preprocessFiles(array); } }, new Runnable() { + @Override public void run() { if (resultRunnable[0] != null) { resultRunnable[0].run(); @@ -450,12 +457,14 @@ public abstract class AbstractLayoutCodeProcessor { final ModalityState modalityState = ModalityState.current(); final Runnable process = new Runnable() { + @Override public void run() { ApplicationManager.getApplication().runReadAction(readAction); } }; Runnable runnable = new Runnable() { + @Override public void run() { try { //DaemonCodeAnalyzer.getInstance(myProject).setUpdateByTimerEnabled(false); @@ -474,8 +483,10 @@ public abstract class AbstractLayoutCodeProcessor { */ final Runnable writeRunnable = new Runnable() { + @Override public void run() { CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + @Override public void run() { if (globalAction) CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject); try { diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java index 9400ee24d539..aac90e5ebad1 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class RefreshQueue { @@ -34,22 +35,23 @@ public abstract class RefreshQueue { return createSession(async, recursive, finishRunnable, getDefaultModalityState()); } - public abstract RefreshSession createSession(boolean async, boolean recursive, @Nullable Runnable finishRunnable, ModalityState state); + public abstract RefreshSession createSession(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull ModalityState state); - public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, ModalityState state, VirtualFile... files) { + public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull ModalityState state, @NotNull VirtualFile... files) { RefreshSession session = createSession(async, recursive, finishRunnable, state); session.addAllFiles(files); session.launch(); } - public abstract void refreshLocalRoots(boolean async, @Nullable Runnable postAction, ModalityState modalityState); + public abstract void refreshLocalRoots(boolean async, @Nullable Runnable postAction, @NotNull ModalityState modalityState); - public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, VirtualFile... files) { + public final void refresh(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull VirtualFile... files) { refresh(async, recursive, finishRunnable, getDefaultModalityState(), files); } public abstract void processSingleEvent(VFileEvent event); + @NotNull protected ModalityState getDefaultModalityState() { return ModalityState.NON_MODAL; } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java index af0d5b847f47..b0b35be25f3f 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/RefreshSession.java @@ -31,7 +31,7 @@ public abstract class RefreshSession { public abstract void addFile(@NotNull VirtualFile file); public abstract void addAllFiles(Collection files); - public void addAllFiles(VirtualFile[] files) { + public void addAllFiles(@NotNull VirtualFile[] files) { addAllFiles(Arrays.asList(files)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityStateEx.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityStateEx.java index 85a6d7dbd304..682475183590 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityStateEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityStateEx.java @@ -32,7 +32,7 @@ public class ModalityStateEx extends ModalityState { this(EMPTY_REFS_ARRAY); } - public ModalityStateEx(Object[] modalEntities) { + public ModalityStateEx(@NotNull Object[] modalEntities) { if (modalEntities.length > 0) { myModalEntities = new WeakReference[modalEntities.length]; for (int i = 0; i < modalEntities.length; i++) { @@ -71,6 +71,7 @@ public class ModalityStateEx extends ModalityState { return false; } + @Override public boolean dominates(@NotNull ModalityState anotherState){ if (anotherState == ModalityState.any()) return false; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java index 39a9fc576a3d..d48ccf44b887 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java @@ -30,6 +30,7 @@ import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.io.storage.HeavyProcessLatch; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; @@ -41,22 +42,22 @@ public class RefreshQueueImpl extends RefreshQueue { private final ExecutorService myQueue = ConcurrencyUtil.newSingleThreadExecutor("FS Synchronizer"); private final ProgressIndicator myRefreshIndicator = new RefreshProgress(VfsBundle.message("file.synchronize.progress")); - public void execute(final RefreshSessionImpl session) { + public void execute(@NotNull RefreshSessionImpl session) { if (session.isAsynchronous()) { ModalityState state = session.getModalityState(); - queueSession(session, state != null ? state : ModalityState.NON_MODAL); + queueSession(session, state); } else { - final Application app = ApplicationManager.getApplication(); - boolean isEDT = app.isDispatchThread(); - final boolean hasWriteAction = app.isWriteAccessAllowed(); - if (isEDT || hasWriteAction) { + final Application application = ApplicationManager.getApplication(); + boolean isEDT = application.isDispatchThread(); + if (isEDT) { session.scan(); + final boolean hasWriteAction = application.isWriteAccessAllowed(); session.fireEvents(hasWriteAction); } else { - if (((ApplicationEx)app).holdsReadLock()) { - LOG.error("Do not call synchronous refresh from inside read action except for event dispatch thread. This will eventually cause deadlock if there are events to fire"); + if (((ApplicationEx)application).holdsReadLock()) { + LOG.error( "Do not call synchronous refresh from inside read action except for event dispatch thread. This will eventually cause deadlock if there are events to fire"); return; } @@ -66,7 +67,7 @@ public class RefreshQueueImpl extends RefreshQueue { } } - private void queueSession(final RefreshSessionImpl session, final ModalityState modality) { + private void queueSession(@NotNull final RefreshSessionImpl session, @NotNull final ModalityState modality) { myQueue.submit(new Runnable() { @Override public void run() { @@ -96,12 +97,12 @@ public class RefreshQueueImpl extends RefreshQueue { } @Override - public RefreshSession createSession(final boolean async, boolean recursively, @Nullable final Runnable finishRunnable, ModalityState state) { + public RefreshSession createSession(final boolean async, boolean recursively, @Nullable final Runnable finishRunnable, @NotNull ModalityState state) { return new RefreshSessionImpl(async, recursively, finishRunnable, state); } @Override - public void refreshLocalRoots(boolean async, Runnable postAction, ModalityState modalityState) { + public void refreshLocalRoots(boolean async, @Nullable Runnable postAction, @NotNull ModalityState modalityState) { RefreshQueue.getInstance().refresh(async, true, postAction, modalityState, ManagingFS.getInstance().getLocalRoots()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java index 5ba74f96360b..37f98293e00d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java @@ -47,7 +47,7 @@ public class RefreshSessionImpl extends RefreshSession { private final Semaphore mySemaphore = new Semaphore(); private volatile boolean iHaveEventsToFire; - private ModalityState myModalityState; + private final ModalityState myModalityState; public RefreshSessionImpl(final boolean isAsync, final boolean recursively, final Runnable finishRunnable) { this(isAsync, recursively, finishRunnable, ModalityState.NON_MODAL); @@ -65,6 +65,7 @@ public class RefreshSessionImpl extends RefreshSession { myIsRecursive = false; myFinishRunnable = null; myEvents = new ArrayList(events); + myModalityState = ModalityState.NON_MODAL; } @Override @@ -167,6 +168,7 @@ public class RefreshSessionImpl extends RefreshSession { return events; } + @NotNull public ModalityState getModalityState() { return myModalityState; } diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/ExternalChangesAndRefreshingTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/ExternalChangesAndRefreshingTest.java index 3a4ea2075bee..63aef3a1008d 100644 --- a/platform/platform-tests/testSrc/com/intellij/history/integration/ExternalChangesAndRefreshingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/history/integration/ExternalChangesAndRefreshingTest.java @@ -86,7 +86,7 @@ public class ExternalChangesAndRefreshingTest extends IntegrationTestCase { @Override protected void runBareRunnable(Runnable r) throws Throwable { if (getName().equals("testRefreshingAsynchronously")) { - // this methods waits for another thread to finish, that leds + // this method waits for another thread to finish, that leads // to deadlock in swing-thread. Therefore we have to run this test // outside of swing-thread r.run(); From 534b2b3668581184b252eea20b8150db2a1e8278 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 17:13:41 +0400 Subject: [PATCH 08/49] read action --- .../OptimizeImportsRefactoringHelper.java | 46 +++++++++++-------- .../completion/JavaAutoPopupTest.groovy | 19 ++++++-- .../impl/JavaCodeInsightTestFixtureImpl.java | 18 ++++++-- .../integration/IntegrationTestCase.java | 9 +++- .../impl/HeavyIdeaTestFixtureImpl.java | 7 ++- ...roovyImportOptimizerRefactoringHelper.java | 13 ++++-- 6 files changed, 79 insertions(+), 33 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java b/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java index 4987f54cc5e8..85d27192acb5 100644 --- a/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java +++ b/java/java-impl/src/com/intellij/refactoring/OptimizeImportsRefactoringHelper.java @@ -34,6 +34,7 @@ import java.util.Set; public class OptimizeImportsRefactoringHelper implements RefactoringHelper> { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.OptimizeImportsRefactoringHelper"); + @Override public Set prepareOperation(final UsageInfo[] usages) { Set javaFiles = new HashSet(); for (UsageInfo usage : usages) { @@ -49,8 +50,10 @@ public class OptimizeImportsRefactoringHelper implements RefactoringHelper javaFiles) { CodeStyleManager.getInstance(project).performActionWithFormatterDisabled(new Runnable() { + @Override public void run() { PsiDocumentManager.getInstance(project).commitAllDocuments(); } @@ -58,35 +61,42 @@ public class OptimizeImportsRefactoringHelper implements RefactoringHelper> redundants = new HashSet>(); final Runnable findRedundantImports = new Runnable() { + @Override public void run() { - final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); - final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); - final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project); - int i = 0; - final int fileCount = javaFiles.size(); - for (PsiJavaFile file : javaFiles) { - if (file.isValid()) { - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - if (progressIndicator != null) { - progressIndicator.setText2(virtualFile.getPresentableUrl()); - progressIndicator.setFraction((double)i++/fileCount); - } - final Collection perFile = styleManager.findRedundantImports(file); - if (perFile != null) { - for (PsiImportStatementBase redundant : perFile) { - redundants.add(pointerManager.createSmartPsiElementPointer(redundant)); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); + final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project); + int i = 0; + final int fileCount = javaFiles.size(); + for (PsiJavaFile file : javaFiles) { + if (file.isValid()) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile != null) { + if (progressIndicator != null) { + progressIndicator.setText2(virtualFile.getPresentableUrl()); + progressIndicator.setFraction((double)i++ / fileCount); + } + final Collection perFile = styleManager.findRedundantImports(file); + if (perFile != null) { + for (PsiImportStatementBase redundant : perFile) { + redundants.add(pointerManager.createSmartPsiElementPointer(redundant)); + } + } } } } } - } + }); } }; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(findRedundantImports, "Removing redundant imports", false, project)) return; ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { try { for (final SmartPsiElementPointer pointer : redundants) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 2c4f96beb193..5bc206a5d3ce 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -43,6 +43,8 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.psi.PsiFile import com.intellij.util.Consumer import com.intellij.openapi.editor.LogicalPosition +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.util.Computable /** * @author peter @@ -949,9 +951,15 @@ public class Bar { myFixture.completeBasic() } myFixture.checkResult 'class Foo {pr}' - lookup.items.each { - lookup.list.cellRenderer.getListCellRendererComponent(lookup.list, it, 0, false, false) - } + + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + void run() { + getLookup().items.each { + getLookup().list.cellRenderer.getListCellRendererComponent(getLookup().list, it, 0, false, false) + } + } + }); assert myFixture.lookupElementStrings.containsAll(['private', 'protected']) } @@ -1098,7 +1106,10 @@ class Foo {{ t; t; }}""" - def caret = myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset) + def caret = ApplicationManager.getApplication().runReadAction(new Computable() { + public LogicalPosition compute() { + return myFixture.editor.offsetToLogicalPosition(myFixture.editor.caretModel.offset) + }}); edt { myFixture.editor.selectionModel.setBlockSelection(caret, new LogicalPosition(caret.line + 1, caret.column + 1)) } type 'toStr' assert lookup diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java index 70acaf8d9018..16e2d690a670 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java @@ -15,8 +15,10 @@ */ package com.intellij.testFramework.fixtures.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.PsiModificationTrackerImpl; @@ -51,17 +53,25 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i } private PsiClass addClass(@NonNls final String rootPath, @NotNull @NonNls final String classText) { - final PsiClass aClass = ((PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.java", classText)).getClasses()[0]; - final String qName = aClass.getQualifiedName(); + final String qName = + ApplicationManager.getApplication().runReadAction(new Computable() { + public String compute() { + final PsiClass aClass = ((PsiJavaFile)PsiFileFactory.getInstance(getProject()).createFileFromText("a.java", classText)).getClasses()[0]; + return aClass.getQualifiedName(); + } + }); assert qName != null; - final PsiFile psiFile = new WriteCommandAction(getProject()) { @Override protected void run(Result result) throws Throwable { result.setResult(addFileToProject(rootPath, qName.replace('.', '/') + ".java", classText)); } }.execute().getResultObject(); - return ((PsiJavaFile)psiFile).getClasses()[0]; + return ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass compute() { + return ((PsiJavaFile)psiFile).getClasses()[0]; + } + }); } @Override diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java b/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java index bb8d7a36e1b1..a767f01a0c06 100644 --- a/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java +++ b/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Clock; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.*; import com.intellij.testFramework.PlatformTestCase; @@ -143,8 +144,12 @@ public abstract class IntegrationTestCase extends PlatformTestCase { return getRevisionsFor(f, null); } - protected List getRevisionsFor(VirtualFile f, String pattern) { - return LocalHistoryTestCase.collectRevisions(getVcs(), getRootEntry(), f.getPath(), myProject.getLocationHash(), pattern); + protected List getRevisionsFor(final VirtualFile f, final String pattern) { + return ApplicationManager.getApplication().runReadAction(new Computable>() { + public List compute() { + return LocalHistoryTestCase.collectRevisions(getVcs(), getRootEntry(), f.getPath(), myProject.getLocationHash(), pattern); + } + }); } protected RootEntry getRootEntry() { diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java index 83840dd3971f..f611f6ddc00e 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -236,6 +237,10 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu VfsUtil.saveText(virtualFile[0], fileText); } }.execute(); - return PsiManager.getInstance(getProject()).findFile(virtualFile[0]); + return ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiFile compute() { + return PsiManager.getInstance(getProject()).findFile(virtualFile[0]); + } + }); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyImportOptimizerRefactoringHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyImportOptimizerRefactoringHelper.java index ccf9aa25f751..3a89965ba129 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyImportOptimizerRefactoringHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyImportOptimizerRefactoringHelper.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring; import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -78,10 +79,14 @@ public class GroovyImportOptimizerRefactoringHelper implements RefactoringHelper progressIndicator.setFraction((double)i++/total); } final Set usedImports = new HashSet(); - final List perFile = optimizer.findUnusedImports(file, usedImports); - if (perFile != null) { - redundants.put(file, Pair.create(perFile, usedImports)); - } + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + final List perFile = optimizer.findUnusedImports(file, usedImports); + if (perFile != null) { + redundants.put(file, Pair.create(perFile, usedImports)); + } + } + }); } } }; From 5a6aa5e2a93782746b898bc7d5de8486be963d6c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 17:32:50 +0400 Subject: [PATCH 09/49] reverted: do not commit under modal progress --- .../daemon/impl/DaemonCodeAnalyzerImpl.java | 15 ++++----------- .../intellij/psi/impl/DocumentCommitThread.java | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index 0f67da0a5728..08e2b90a61c7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -31,7 +31,6 @@ import com.intellij.ide.PowerSaveMode; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -696,16 +695,10 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx // we'll restart when write action finish return; } - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); - if (documentManager.hasUncommitedDocuments()) { - if (ModalityState.current() == ModalityState.NON_MODAL) { - ((PsiDocumentManagerImpl)documentManager).cancelAndRunWhenAllCommitted("restart daemon when all committed", this); - return; - } - else { - // when modal dialog is open, DocumentCommitThread is not able to commit in background, so force commit here - documentManager.commitAllDocuments(); - } + if (PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments()) { + ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject)).cancelAndRunWhenAllCommitted( + "restart daemon when all committed", this); + return; } Map passes = new THashMap(activeEditors.size()); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 7533c674ee76..c7872b9d3ae1 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -18,7 +18,6 @@ package com.intellij.psi.impl; import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -54,6 +53,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.SmartList; import com.intellij.util.containers.Queue; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -318,7 +318,7 @@ public class DocumentCommitThread implements Runnable, Disposable { } if (success) { assert !ApplicationManager.getApplication().isDispatchThread(); - ApplicationManager.getApplication().invokeLater(finishRunnable, ModalityState.NON_MODAL); // do not commit while modal progress is running + UIUtil.invokeLaterIfNeeded(finishRunnable); log("Invoked later finishRunnable", document, false, success, finishRunnable, indicator); } } From b8f33ed16087877b8be707f6660445c85e69c975 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 17:33:13 +0400 Subject: [PATCH 10/49] read action --- .../org/jetbrains/idea/maven/MavenImportingTestCase.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java index b720bc572866..8f4550408c9b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java @@ -33,6 +33,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TestDialog; import com.intellij.openapi.util.AsyncResult; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; @@ -289,8 +290,12 @@ public abstract class MavenImportingTestCase extends MavenTestCase { } } - protected Module getModule(String name) { - Module m = ModuleManager.getInstance(myProject).findModuleByName(name); + protected Module getModule(final String name) { + Module m = ApplicationManager.getApplication().runReadAction(new Computable() { + public Module compute() { + return ModuleManager.getInstance(myProject).findModuleByName(name); + } + }); assertNotNull("Module " + name + " not found", m); return m; } From a5062c09550ba7fa33d6cf62f82a7b8ac6431efe Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 18:50:25 +0400 Subject: [PATCH 11/49] leaks in debugger tests --- .../src/com/intellij/debugger/impl/InvokeThread.java | 9 +++++---- .../com/intellij/debugger/ui/impl/DebuggerTreeBase.java | 4 ++-- .../plugins/groovy/compiler/GroovyDebuggerTest.groovy | 5 ++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java b/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java index d06d0febaed8..b3ddf3a90ed2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/InvokeThread.java @@ -18,6 +18,7 @@ package com.intellij.debugger.impl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.sun.jdi.VMDisconnectedException; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.concurrent.*; @@ -65,14 +66,14 @@ public abstract class InvokeThread { public boolean isInterrupted() { assert myRequestFuture != null; - return myRequestFuture.isCancelled(); + return myRequestFuture.isCancelled() || myRequestFuture.isDone(); } public void join() throws InterruptedException, ExecutionException { assert myRequestFuture != null; try { myRequestFuture.get(); - } + } catch(CancellationException ignored) { } } @@ -101,7 +102,7 @@ public abstract class InvokeThread { public boolean isDone() { assert myRequestFuture != null; - return myRequestFuture.isDone(); + return myRequestFuture.isDone() && ourWorkerRequest.get() == null; } } @@ -122,7 +123,7 @@ public abstract class InvokeThread { workerRequest.setRequestFuture( ApplicationManager.getApplication().executeOnPooledThread(workerRequest) ); } - public void run(WorkerThreadRequest threadRequest) { + private void run(@NotNull WorkerThreadRequest threadRequest) { while(true) { try { if(threadRequest.isInterrupted()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java index 7e81ee69ff54..3c2f626eb0df 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java @@ -75,6 +75,8 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable { } }); + Disposer.register(this, myTipManager); + UIUtil.setLineStyleAngled(this); setRootVisible(false); setShowsRootHandles(true); @@ -388,7 +390,5 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable { } myCurrentTooltip = null; myCurrentTooltipNode = null; - Disposer.dispose(myTipManager); } - } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy index 186e7c9b77d4..094be1d8d787 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy @@ -39,6 +39,7 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.util.Computable import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile @@ -205,7 +206,9 @@ cl.parseClass('''$mcText''', 'MyClass.groovy').foo(2) waitForBreakpoint() SourcePosition position = managed { EvaluationContextImpl context = evaluationContext() - ContextUtil.getSourcePosition(context) + Computable a = { ContextUtil.getSourcePosition(context) } as Computable + SourcePosition pos = ApplicationManager.getApplication().runReadAction (a) + pos } assert myClass == position.file.virtualFile eval 'a', '2' From efffab516f93a48cb65467dad44906ed4a706803 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 18:51:45 +0400 Subject: [PATCH 12/49] cleanup --- .../daemon/impl/analysis/HighlightMethodUtil.java | 2 +- .../daemon/impl/quickfix/SideEffectWarningDialog.java | 6 ++---- .../refactoring/typeMigration/TypeMigrationProcessor.java | 3 ++- .../src/com/intellij/util/indexing/FileBasedIndex.java | 6 ------ .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 8 +++----- .../plugins/intelliLang/InjectionsSettingsUI.java | 4 +--- plugins/devkit/src/projectRoots/IdeaJdk.java | 3 --- .../impl/analysis/encoding/XmlEncodingReference.java | 1 + 8 files changed, 10 insertions(+), 23 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index e9fa6d015363..90ffa0ab8fcf 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -544,7 +544,7 @@ public class HighlightMethodUtil { PsiMethod method = methodCandidate.getElement(); PsiParameter[] parameters = method.getParameterList().getParameters(); PsiSubstitutor substitutor = methodCandidate.getSubstitutor(); - @NonNls String ms = "" + method.getName() + ""; + @NonNls @Language("HTML") String ms = "" + method.getName() + ""; for (int j = 0; j < parameters.length; j++) { PsiParameter parameter = parameters[j]; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java index e9717b6eb412..8da93c134c2b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java @@ -36,7 +36,6 @@ public class SideEffectWarningDialog extends DialogWrapper { private final String myBeforeText; private final String myAfterText; private final boolean myCanCopeWithSideEffects; - private AbstractAction myMakeStmtAction; private AbstractAction myRemoveAllAction; private AbstractAction myCancelAllAction; public static final int MAKE_STATEMENT = 1; @@ -71,7 +70,7 @@ public class SideEffectWarningDialog extends DialogWrapper { }; actions.add(myRemoveAllAction); if (myCanCopeWithSideEffects) { - myMakeStmtAction = new AbstractAction() { + AbstractAction makeStmtAction = new AbstractAction() { { UIUtil.setActionNameAndMnemonic(QuickFixBundle.message("side.effect.action.transform"), this); } @@ -80,9 +79,8 @@ public class SideEffectWarningDialog extends DialogWrapper { public void actionPerformed(ActionEvent e) { close(MAKE_STATEMENT); } - }; - actions.add(myMakeStmtAction); + actions.add(makeStmtAction); } myCancelAllAction = new AbstractAction() { { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java index e75178e77f0c..d0848887c4f4 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java @@ -37,6 +37,7 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class TypeMigrationProcessor extends BaseRefactoringProcessor { @@ -132,7 +133,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor { text = "method \'" + ((PsiMethod)myRoot[0]).getName() + "\' return"; } else { - text = myRoot.toString(); + text = Arrays.toString(myRoot); } Content content = UsageViewManager.getInstance(myProject) .addContent("Migrate Type of " + diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index 2a9a33c142df..9b39245a44a6 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -499,9 +499,6 @@ public class FileBasedIndex implements ApplicationComponent { keyDescriptor.save(out, key); } } - catch (IOException e) { - throw e; - } catch (IllegalArgumentException e) { throw new IOException("Error saving data for index " + indexId, e); } @@ -517,9 +514,6 @@ public class FileBasedIndex implements ApplicationComponent { } return list; } - catch (IOException e) { - throw e; - } catch (IllegalArgumentException e) { throw new IOException("Error reading data for index " + indexId, e); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 6ae7e4c2ec0a..5ad9c5efe6d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -192,8 +192,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private static final int MOUSE_SELECTION_STATE_WORD_SELECTED = 1; private static final int MOUSE_SELECTION_STATE_LINE_SELECTED = 2; - private final MarkupModelListener myMarkupModelListener; - private EditorHighlighter myHighlighter; private final TextDrawingCallback myTextDrawingCallback = new MyTextDrawingCallback(); @@ -306,7 +304,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } myMouseMotionListeners = ContainerUtil.createEmptyCOWList(); - myMarkupModelListener = new MarkupModelListener() { + MarkupModelListener markupModelListener = new MarkupModelListener() { @Override public void afterAdded(@NotNull RangeHighlighterEx highlighter) { attributesChanged(highlighter); @@ -341,8 +339,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } }; - ((MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true)).addMarkupModelListener(myCaretModel, myMarkupModelListener); - ((MarkupModelEx)getMarkupModel()).addMarkupModelListener(myCaretModel, myMarkupModelListener); + ((MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true)).addMarkupModelListener(myCaretModel, markupModelListener); + ((MarkupModelEx)getMarkupModel()).addMarkupModelListener(myCaretModel, markupModelListener); myDocument.addDocumentListener(myFoldingModel,myCaretModel); myDocument.addDocumentListener(myCaretModel,myCaretModel); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java index 14b31a450adc..7d36e83559bc 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java @@ -930,9 +930,7 @@ public class InjectionsSettingsUI implements SearchableConfigurable.Parent, NonD @Override public boolean equals(final BaseInjection o1, final BaseInjection o2) { - if (!o1.sameLanguageParameters(o2)) return false; - if (!o1.getInjectionPlaces().equals(o2.getInjectionPlaces())) return false; - return true; + return o1.sameLanguageParameters(o2) && Arrays.equals(o1.getInjectionPlaces(), o2.getInjectionPlaces()); } } diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java index 0f6c318daede..7dad1832aa84 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/src/projectRoots/IdeaJdk.java @@ -156,9 +156,6 @@ public class IdeaJdk extends SdkType implements JavaSdkType { else if (new File(sdkHome, "lib/webide.jar").exists()) { productName = "WebStorm/PhpStorm "; } - else if (new File(sdkHome, "lib/webide.jar").exists()) { - productName = "WebStorm/PhpStorm "; - } else { productName = "IDEA "; } diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java index d077d49a2087..5de454c9b173 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/encoding/XmlEncodingReference.java @@ -66,6 +66,7 @@ public class XmlEncodingReference implements PsiReference, EmptyResolveMessagePr } public String getUnresolvedMessagePattern() { + //noinspection UnresolvedPropertyKey return XmlErrorMessages.message("unknown.encoding.0"); } From 3bd52486ea70698080e0258898bd7383c4cd412c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Dec 2011 16:29:11 +0400 Subject: [PATCH 13/49] use actual size of combo label for popup minimum size --- .../intellij/openapi/wm/impl/content/ComboContentLayout.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ComboContentLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ComboContentLayout.java index 22dfd22b7dfd..e8045e84cfed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ComboContentLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ComboContentLayout.java @@ -145,7 +145,7 @@ class ComboContentLayout extends ContentLayout { @Override public void showContentPopup(ListPopup listPopup) { - listPopup.setMinimumSize(new Dimension(myComboLabel.getPreferredSize().width, 0)); + listPopup.setMinimumSize(new Dimension(myComboLabel.getSize().width, 0)); listPopup.showUnderneathOf(myComboLabel); } From bcd9f23b7dc504e6f39732e18e84d50db0fff30e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Dec 2011 16:29:48 +0400 Subject: [PATCH 14/49] use tab name when specified in popup --- .../intellij/openapi/wm/impl/content/ToolWindowContentUi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java index f04b7c799974..29431e6c8294 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java @@ -425,7 +425,7 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh @NotNull @Override public String getTextFor(Content value) { - final String displayName = value.getDisplayName(); + final String displayName = value.getTabName(); return displayName != null ? displayName : ""; } From 1abebaaab74dc9bcf05e48f1697a1207f1ffab88 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Dec 2011 16:52:24 +0100 Subject: [PATCH 15/49] couple more pieces of JavaCoreEnvironment --- .../impl/file/JavaDirectoryServiceImpl.java | 23 +--- .../core/CoreJavaDirectoryService.java | 110 ++++++++++++++++++ .../intellij/core/CoreJavaFileManager.java | 13 +++ .../intellij/core/JavaCoreEnvironment.java | 7 +- 4 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 java/java-psi-impl/src/com/intellij/core/CoreJavaDirectoryService.java diff --git a/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java index 9444f9fce512..dd2b6f2bb9e3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java @@ -19,6 +19,7 @@ */ package com.intellij.psi.impl.file; +import com.intellij.core.CoreJavaDirectoryService; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.FileTemplateUtil; @@ -39,14 +40,11 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; import java.util.Properties; -public class JavaDirectoryServiceImpl extends JavaDirectoryService { +public class JavaDirectoryServiceImpl extends CoreJavaDirectoryService { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.JavaDirectoryServiceImpl"); @Override @@ -57,23 +55,6 @@ public class JavaDirectoryServiceImpl extends JavaDirectoryService { return JavaPsiFacade.getInstance(dir.getProject()).findPackage(packageName); } - @Override - @NotNull - public PsiClass[] getClasses(@NotNull PsiDirectory dir) { - LOG.assertTrue(dir.isValid()); - - List classes = null; - for (PsiFile file : dir.getFiles()) { - if (file instanceof PsiClassOwner && file.getViewProvider().getLanguages().size() == 1) { - PsiClass[] psiClasses = ((PsiClassOwner)file).getClasses(); - if (psiClasses.length == 0) continue; - if (classes == null) classes = new ArrayList(); - ContainerUtil.addAll(classes, psiClasses); - } - } - return classes == null ? PsiClass.EMPTY_ARRAY : classes.toArray(new PsiClass[classes.size()]); - } - @Override @NotNull public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaDirectoryService.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaDirectoryService.java new file mode 100644 index 000000000000..23ce0c9ce054 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaDirectoryService.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.core; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.*; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yole + */ +public class CoreJavaDirectoryService extends JavaDirectoryService { + private static final Logger LOG = Logger.getInstance("#com.intellij.core.CoreJavaDirectoryService"); + + @Override + public PsiPackage getPackage(@NotNull PsiDirectory dir) { + return ServiceManager.getService(dir.getProject(), CoreJavaFileManager.class).getPackage(dir); + } + + @NotNull + @Override + public PsiClass[] getClasses(@NotNull PsiDirectory dir) { + LOG.assertTrue(dir.isValid()); + + List classes = null; + for (PsiFile file : dir.getFiles()) { + if (file instanceof PsiClassOwner && file.getViewProvider().getLanguages().size() == 1) { + PsiClass[] psiClasses = ((PsiClassOwner)file).getClasses(); + if (psiClasses.length == 0) continue; + if (classes == null) classes = new ArrayList(); + ContainerUtil.addAll(classes, psiClasses); + } + } + return classes == null ? PsiClass.EMPTY_ARRAY : classes.toArray(new PsiClass[classes.size()]); + } + + @NotNull + @Override + public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiClass createClass(@NotNull PsiDirectory dir, @NotNull String name, @NotNull String templateName) + throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @Override + public PsiClass createClass(@NotNull PsiDirectory dir, + @NotNull String name, + @NotNull String templateName, + boolean askForUndefinedVariables) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkCreateClass(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiClass createInterface(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiClass createEnum(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiClass createAnnotationType(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSourceRoot(@NotNull PsiDirectory dir) { + return false; + } + + @Override + public LanguageLevel getLanguageLevel(@NotNull PsiDirectory dir) { + return LanguageLevel.HIGHEST; + } +} diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java index 57e42dca74e9..8925fca42e3c 100644 --- a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java @@ -16,6 +16,7 @@ package com.intellij.core; import com.intellij.openapi.roots.PackageIndex; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem; import com.intellij.openapi.vfs.local.CoreLocalFileSystem; @@ -70,6 +71,18 @@ public class CoreJavaFileManager extends PackageIndex implements JavaFileManager return result; } + @Nullable + public PsiPackage getPackage(PsiDirectory dir) { + final File ioFile = new File(dir.getVirtualFile().getPath()); + for (File root : myClasspath) { + if (FileUtil.isAncestor(root, ioFile, false)) { + final String relativePath = FileUtil.getRelativePath(root.getPath(), ioFile.getPath(), '.'); + return new PsiPackageImpl(myPsiManager, relativePath); + } + } + return null; + } + @Nullable private VirtualFile findUnderClasspathEntry(File classpathEntry, String relativeName) { if (classpathEntry.isFile()) { diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java index 373a014e4a02..b48ba051d82d 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java @@ -62,8 +62,11 @@ public class JavaCoreEnvironment extends CoreEnvironment { registerExtensionPoint(Extensions.getRootArea(), ClsStubBuilderFactory.EP_NAME, ClsStubBuilderFactory.class); addExtension(ClsStubBuilderFactory.EP_NAME, new DefaultClsStubBuilderFactory()); + myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper()); + myFileManager = new CoreJavaFileManager(myPsiManager, getLocalFileSystem(), myJarFileSystem); JavaPsiFacadeImpl javaPsiFacade = new JavaPsiFacadeImpl(myProject, myPsiManager, myFileManager, null); + myProject.registerService(CoreJavaFileManager.class, myFileManager); registerComponentInstance(myProject.getPicoContainer(), JavaPsiFacade.class, javaPsiFacade); @@ -72,10 +75,10 @@ public class JavaCoreEnvironment extends CoreEnvironment { myProject.registerService(JavaPsiImplementationHelper.class, new CoreJavaPsiImplementationHelper()); myProject.registerService(PsiResolveHelper.class, new PsiResolveHelperImpl(myPsiManager)); myProject.registerService(LanguageLevelProjectExtension.class, new CoreLanguageLevelProjectExtension()); - myProject.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper()); myProject.registerService(PackageIndex.class, myFileManager); - + myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl()); + myApplication.registerService(JavaDirectoryService.class, new CoreJavaDirectoryService()); } public void addToClasspath(File path) { From 4caad786d748ca9d3046696b2ef502e54516b208 Mon Sep 17 00:00:00 2001 From: Alexander Doroshko Date: Tue, 20 Dec 2011 20:15:58 +0400 Subject: [PATCH 16/49] EA-32675 --- .../com/intellij/psi/impl/source/codeStyle/ImportHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index 22fed27b0178..840947dedf8e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -789,7 +789,8 @@ public class ImportHelper{ } private static void addUnresolvedImportNames(@NotNull final Set> namesToImport, @NotNull PsiJavaFile file) { - PsiImportStatementBase[] imports = file.getImportList().getAllImportStatements(); + final PsiImportList importList = file.getImportList(); + PsiImportStatementBase[] imports = importList == null ? PsiImportStatementBase.EMPTY_ARRAY : importList.getAllImportStatements(); final Map> unresolvedNames = new THashMap>(); @NotNull Set> unresolvedOnDemand = new THashSet>(); for (PsiImportStatementBase anImport : imports) { From ea0b4b72edc505de43c372cd5b3be6341643606d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Dec 2011 17:38:56 +0100 Subject: [PATCH 17/49] better autodetection of platform prefix --- .../intellij/testFramework/IdeaTestCase.java | 5 ----- .../testFramework/PlatformTestCase.java | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/java/testFramework/src/com/intellij/testFramework/IdeaTestCase.java b/java/testFramework/src/com/intellij/testFramework/IdeaTestCase.java index c5372661a182..abdb236f010b 100644 --- a/java/testFramework/src/com/intellij/testFramework/IdeaTestCase.java +++ b/java/testFramework/src/com/intellij/testFramework/IdeaTestCase.java @@ -43,11 +43,6 @@ public abstract class IdeaTestCase extends PlatformTestCase { super.tearDown(); } - @SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"}) - protected IdeaTestCase() { - initPlatformPrefix(); - } - public final JavaPsiFacadeEx getJavaFacade() { return myJavaFacade; } diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index c7a3c088f4d3..a1f279e041cb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -83,6 +83,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; +import java.net.URL; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -125,6 +126,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro protected void initApplication() throws Exception { boolean firstTime = ourApplication == null; + autodetectPlatformPrefix(); ourApplication = IdeaTestApplication.getInstance(getApplicationConfigDirPath()); ourApplication.setDataProvider(this); @@ -133,6 +135,22 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro } } + private static void autodetectPlatformPrefix() { + if (ourPlatformPrefixInitialized) { + return; + } + URL resource = PlatformTestCase.class.getClassLoader().getResource("idea/ApplicationInfo.xml"); + if (resource == null) { + resource = PlatformTestCase.class.getClassLoader().getResource("idea/IdeaApplicationInfo.xml"); + if (resource == null) { + System.setProperty("idea.platform.prefix", "PlatformLangXml"); + } + else { + System.setProperty("idea.platform.prefix", "Idea"); + } + } + } + private static void cleanPersistedVFSContent() { ((PersistentFS)ManagingFS.getInstance()).cleanPersistedContents(); } From 14aac0c0c831a9b05a3c384e099d1fba111f40db Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Dec 2011 20:42:24 +0400 Subject: [PATCH 18/49] no tag name completion after known prefix --- .../completion/XmlCompletionContributor.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java index dec9c5de128c..bcde765f388d 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java @@ -33,13 +33,14 @@ import com.intellij.patterns.XmlPatterns; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.xml.*; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTokenType; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import com.intellij.xml.XmlBundle; -import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlExtension; -import com.intellij.xml.impl.schema.AnyXmlElementDescriptor; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -142,19 +143,18 @@ public class XmlCompletionContributor extends CompletionContributor { result.stopHere(); PsiElement parent = element.getParent(); if (!(parent instanceof XmlTag) || - !(parameters.getOriginalFile() instanceof XmlFile) || - !((XmlTag)parent).getNamespacePrefix().isEmpty()) { + !(parameters.getOriginalFile() instanceof XmlFile)) { return; } final XmlTag tag = (XmlTag)parent; final String namespace = tag.getNamespace(); - final XmlElementDescriptor parentDescriptor = tag.getDescriptor(); final String prefix = result.getPrefixMatcher().getPrefix(); final int pos = prefix.indexOf(':'); final String namespacePrefix = pos > 0 ? prefix.substring(0, pos) : null; final PsiReference reference = tag.getReference(); - if (reference != null && namespace.length() > 0 && parentDescriptor != null && !(parentDescriptor instanceof AnyXmlElementDescriptor)) { + if (reference != null && !namespace.isEmpty() && !tag.getNamespacePrefix().isEmpty()) { + // fallback to simple completion final Set set = new HashSet(); new XmlCompletionData().completeReference(reference, set, element, parameters.getOriginalFile(), parameters.getOffset()); for (final LookupElement item : set) { From 02de54fd2271d58eac3b79c250a2de6c5e1f051e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Dec 2011 19:53:28 +0300 Subject: [PATCH 19/49] Fix GitHttpAdapter#isHttpUrl and rename to make more descriptive. Add a test. --- plugins/git4idea/src/git4idea/actions/GitPull.java | 2 +- .../src/git4idea/checkout/GitCheckoutProvider.java | 2 +- .../git4idea/src/git4idea/checkout/GitCloneDialog.java | 2 +- plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java | 8 ++++---- plugins/git4idea/src/git4idea/merge/GitPullDialog.java | 2 +- plugins/git4idea/src/git4idea/push/GitPusher.java | 4 ++-- plugins/git4idea/src/git4idea/update/GitFetcher.java | 2 +- .../netrc/n7_uppercase_and_order_change/n7_config.txt | 3 +++ .../netrc/n7_uppercase_and_order_change/n7_desc.txt | 1 + .../netrc/n7_uppercase_and_order_change/n7_result.txt | 1 + 10 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_config.txt create mode 100644 plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_result.txt diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java index 98304bc1a462..b29f0e1bc7e5 100644 --- a/plugins/git4idea/src/git4idea/actions/GitPull.java +++ b/plugins/git4idea/src/git4idea/actions/GitPull.java @@ -82,7 +82,7 @@ public class GitPull extends GitRepositoryAction { return; } - if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) { + if (GitHttpAdapter.shouldUseJGit(url)) { boolean fetchSuccessful = new GitFetcher(project, indicator).fetchRootsAndNotify(gitRoots, "Push failed", false); if (!fetchSuccessful) { return; diff --git a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java index d4cb41e77a2a..f5077d4bc764 100644 --- a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java +++ b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java @@ -104,7 +104,7 @@ public class GitCheckoutProvider implements CheckoutProvider { } private static boolean doClone(@NotNull Project project, @NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) { - if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(sourceRepositoryURL)) { + if (GitHttpAdapter.shouldUseJGit(sourceRepositoryURL)) { GitFetchResult result = GitHttpAdapter.cloneRepository(project, new File(parentDirectory, directoryName), sourceRepositoryURL); GitFetcher.displayFetchResult(project, result, "Clone failed", result.getErrors()); return result.isSuccess(); diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java index 769b67b9fa66..7e0351bf02bd 100644 --- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java +++ b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java @@ -141,7 +141,7 @@ public class GitCloneDialog extends DialogWrapper { private void test() { myTestURL = getCurrentUrlText(); - boolean testResult = GitHttpAdapter.isHttpUrlWithoutUserCredentials(myTestURL) ? testHttp(myTestURL) : testNatively(myTestURL); + boolean testResult = GitHttpAdapter.shouldUseJGit(myTestURL) ? testHttp(myTestURL) : testNatively(myTestURL); if (testResult) { Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL), diff --git a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java index f5ef78f7d239..6c121759108e 100644 --- a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java +++ b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java @@ -65,11 +65,11 @@ public final class GitHttpAdapter { private static final Pattern HTTP_URL_WITH_USERNAME_AND_PASSWORD = Pattern.compile("http(s?)://([^\\s^@:]+):([^\\s^@:]+)@.*"); - public static boolean isHttpUrlWithoutUserCredentials(@NotNull String url) { - // if username & password are specified in the url, give it to the native Git + public static boolean shouldUseJGit(@NotNull String url) { if (!url.startsWith("http")) { return false; } + // if username & password are specified in the url, give it to the native Git if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) { return false; } @@ -79,11 +79,11 @@ public final class GitHttpAdapter { return !netrcData.hasAuthDataForUrl(url); } catch (FileNotFoundException e) { - return false; + return true; } catch (IOException e) { LOG.warn("Couldn't read netrc file", e); - return false; + return true; } } diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java index dd4056af5133..db8e7b4ec5d0 100644 --- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java +++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java @@ -182,7 +182,7 @@ public class GitPullDialog extends DialogWrapper { @NotNull private Collection getRemoteBranches(@NotNull GitDeprecatedRemote remote) { - if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(remote.fetchUrl())) { + if (GitHttpAdapter.shouldUseJGit(remote.fetchUrl())) { GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(gitRoot()); if (repository == null) { return Collections.emptyList(); diff --git a/plugins/git4idea/src/git4idea/push/GitPusher.java b/plugins/git4idea/src/git4idea/push/GitPusher.java index ed83f78e39b7..c4391ab1e8f0 100644 --- a/plugins/git4idea/src/git4idea/push/GitPusher.java +++ b/plugins/git4idea/src/git4idea/push/GitPusher.java @@ -332,7 +332,7 @@ public final class GitPusher { return pushNatively(repository, pushSpec); } else { - return GitHttpAdapter.isHttpUrlWithoutUserCredentials(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec); + return GitHttpAdapter.shouldUseJGit(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec); } } else { @@ -340,7 +340,7 @@ public final class GitPusher { assert remote != null : "Remote can't be null for pushSpec " + pushSpec; String httpUrl = null; for (String pushUrl : remote.getPushUrls()) { - if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(pushUrl)) { + if (GitHttpAdapter.shouldUseJGit(pushUrl)) { httpUrl = pushUrl; break; // TODO support http and ssh urls in one origin } diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 7089b831cad8..d2d88c36e37a 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -67,7 +67,7 @@ public class GitFetcher { if (url == null) { continue; } - if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) { + if (GitHttpAdapter.shouldUseJGit(url)) { GitFetchResult res = GitHttpAdapter.fetch(repository, remote, url); myErrors.addAll(res.getErrors()); if (!res.isSuccess()) { diff --git a/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_config.txt b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_config.txt new file mode 100644 index 000000000000..7a205675b3e3 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_config.txt @@ -0,0 +1,3 @@ +MACHine BITBUCKET.org + password pass + LOGIN john diff --git a/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_desc.txt b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_desc.txt new file mode 100644 index 000000000000..43fca76614c8 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_desc.txt @@ -0,0 +1 @@ +n7 uppercase, login & password order change diff --git a/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_result.txt b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_result.txt new file mode 100644 index 000000000000..8d6804e3f9af --- /dev/null +++ b/plugins/git4idea/testData/netrc/n7_uppercase_and_order_change/n7_result.txt @@ -0,0 +1 @@ +bitbucket.org john pass From 45270a68938669d4017b70b955693afd71b1121e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Dec 2011 20:31:23 +0300 Subject: [PATCH 20/49] Git: don't hang if a remote operation requests username or password Instead kill the process and show authentication error. --- plugins/git4idea/src/git4idea/Git.java | 9 ++- .../src/git4idea/checkout/GitCloneDialog.java | 36 +++--------- .../GitLineHandlerPasswordRequestAware.java | 55 +++++++++++++++++++ .../src/git4idea/update/GitFetcher.java | 11 +++- 4 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/commands/GitLineHandlerPasswordRequestAware.java diff --git a/plugins/git4idea/src/git4idea/Git.java b/plugins/git4idea/src/git4idea/Git.java index 208219fd1c9f..7cfc387b939f 100644 --- a/plugins/git4idea/src/git4idea/Git.java +++ b/plugins/git4idea/src/git4idea/Git.java @@ -125,7 +125,7 @@ public class Git { @NotNull public static GitCommandResult clone(@NotNull Project project, @NotNull File parentDirectory, @NotNull String url, @NotNull String clonedDirectoryName) { - GitLineHandler handler = new GitLineHandler(project, parentDirectory, GitCommand.CLONE); + GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(project, parentDirectory, GitCommand.CLONE); handler.addParameters(url); handler.addParameters(clonedDirectoryName); return run(handler, true); @@ -221,7 +221,7 @@ public class Git { } public static GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull GitLineHandlerListener... listeners) { - final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.PUSH); + final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(), GitCommand.PUSH); h.setSilent(false); for (GitLineHandlerListener listener : listeners) { @@ -274,6 +274,11 @@ public class Git { }); handler.runInCurrentThread(null); + + if (handler instanceof GitLineHandlerPasswordRequestAware && ((GitLineHandlerPasswordRequestAware)handler).hadAuthRequest()) { + errorOutput.add("Authentication failed"); + } + final boolean success = !startFailed.get() && errorOutput.isEmpty() && (handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0); return new GitCommandResult(success, exitCode.get(), errorOutput, output); } diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java index 7e0351bf02bd..219f0c2c1361 100644 --- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java +++ b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java @@ -19,14 +19,15 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; -import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.EditorComboBox; import com.intellij.util.ArrayUtil; -import git4idea.commands.*; +import git4idea.commands.GitCommand; +import git4idea.commands.GitLineHandlerPasswordRequestAware; +import git4idea.commands.GitTask; +import git4idea.commands.GitTaskResult; import git4idea.i18n.GitBundle; -import git4idea.jgit.GitHttpAdapter; import git4idea.remote.GitRememberedInputs; import org.jetbrains.annotations.NonNls; @@ -38,7 +39,6 @@ import java.awt.event.ActionListener; import java.io.File; import java.net.URI; import java.net.URISyntaxException; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; /** @@ -141,7 +141,7 @@ public class GitCloneDialog extends DialogWrapper { private void test() { myTestURL = getCurrentUrlText(); - boolean testResult = GitHttpAdapter.shouldUseJGit(myTestURL) ? testHttp(myTestURL) : testNatively(myTestURL); + boolean testResult = test(myTestURL); if (testResult) { Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL), @@ -158,31 +158,13 @@ public class GitCloneDialog extends DialogWrapper { * That way, we have a hack here: if http response asked for a password, then the url is at least valid and existant, and we consider * that the test passed. */ - private boolean testHttp(String url) { - final AtomicBoolean passwordRequested = new AtomicBoolean(); - final GitLineHandler handler = new GitLineHandler(myProject, new File("."), GitCommand.LS_REMOTE); - handler.addParameters(url, "master"); - handler.addLineListener(new GitLineHandlerAdapter() { - @Override - public void onLineAvailable(String line, Key outputType) { - String lowerCasedLine = line.toLowerCase(); - if (lowerCasedLine.contains("password") || lowerCasedLine.contains("login") || lowerCasedLine.contains("username")) { - handler.cancel(); - passwordRequested.set(true); - } - } - }); - GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url)); - GitTaskResult result = task.executeModal(); - return result.isOK() || passwordRequested.get(); - } - - private boolean testNatively(String url) { - GitSimpleHandler handler = new GitSimpleHandler(myProject, new File("."), GitCommand.LS_REMOTE); + private boolean test(String url) { + final GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE); handler.addParameters(url, "master"); GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url)); GitTaskResult result = task.executeModal(); - return result.isOK(); + boolean authFailed = handler.hadAuthRequest(); + return result.isOK() || authFailed; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitLineHandlerPasswordRequestAware.java b/plugins/git4idea/src/git4idea/commands/GitLineHandlerPasswordRequestAware.java new file mode 100644 index 000000000000..b117b2092946 --- /dev/null +++ b/plugins/git4idea/src/git4idea/commands/GitLineHandlerPasswordRequestAware.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.commands; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +/** + * {@link GitLineHandler} that listens to Git output and kills itself if "username" or "password" is queried throughout the prompt. + * We can't pass the data to the prompt anyway, so better to kill the process and show an error message, than to hang the task. + * + * @author Kirill Likhodedov + */ +public class GitLineHandlerPasswordRequestAware extends GitLineHandler { + + private boolean myAuthRequest; + + public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull VirtualFile vcsRoot, @NotNull GitCommand command) { + super(project, vcsRoot, command); + } + + public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull File directory, @NotNull GitCommand clone) { + super(project, directory, clone); + } + + @Override + protected void onTextAvailable(String text, Key outputType) { + super.onTextAvailable(text, outputType); + if (text.toLowerCase().startsWith("password") || text.toLowerCase().startsWith("username")) { + myAuthRequest = true; + destroyProcess(); + } + } + + public boolean hadAuthRequest() { + return myAuthRequest; + } +} diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index d2d88c36e37a..31491f7fa65a 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -19,6 +19,7 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitVcs; import git4idea.commands.*; @@ -86,7 +87,7 @@ public class GitFetcher { } private boolean fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote) { - final GitLineHandler h = new GitLineHandler(myProject, root, GitCommand.FETCH); + final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH); h.addParameters(remote.getName()); final GitTask fetchTask = new GitTask(myProject, h, "Fetching..."); fetchTask.setProgressIndicator(myProgressIndicator); @@ -102,11 +103,15 @@ public class GitFetcher { protected void onCancel() { LOG.info("Cancelled fetch."); } - + @Override protected void onFailure() { LOG.info("Error fetching: " + h.errors()); - myErrors.addAll(h.errors()); + if (!h.hadAuthRequest()) { + myErrors.addAll(h.errors()); + } else { + myErrors.add(new VcsException("Authentication failed")); + } } }); return success.get(); From 60557a8fdb1a293a0b1210f15e1e4ebc7c9566ad Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 15:18:11 +0100 Subject: [PATCH 21/49] track NPE (EA-32624) --- .../impl/quickfix/ImportClassFixBase.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java index e60f67bc6c97..63ec9c667a79 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java @@ -55,13 +55,23 @@ import java.util.regex.PatternSyntaxException; public abstract class ImportClassFixBase implements HintAction, HighPriorityAction { private final T myRef; - protected ImportClassFixBase(T ref) { + protected ImportClassFixBase(@NotNull T ref) { myRef = ref; } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myRef.isValid() && file.getManager().isInProject(file) && !getClassesToImport().isEmpty(); + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { + if (!myRef.isValid()) { + return false; + } + PsiManager manager = file.getManager(); + if (!manager.isInProject(file)) { + return false; + } + if (getClassesToImport().isEmpty()) { + return false; + } + return true; } @Nullable @@ -70,6 +80,7 @@ public abstract class ImportClassFixBase im protected abstract boolean hasTypeParameters(T reference); + @NotNull public List getClassesToImport() { PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myRef.getProject()); String name = getReferenceName(myRef); From 0795bed9af49f5f21bbce4629a84b50f655af75f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 15:42:52 +0100 Subject: [PATCH 22/49] an new list shouldn't be null, whatever happens (EA-31426) --- .../org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy index 3290efc2b831..4c76fc96a009 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy @@ -17,6 +17,7 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.AnnotatedScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClosureScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope +import com.intellij.util.ObjectUtils /** * @author ilyas @@ -24,7 +25,7 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope public class GroovyDslExecutor { static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class } - final List> enhancers = [] + final List> enhancers = ObjectUtils.assertNotNull([]) private final String myFileName; static final String ideaVersion From a71edba393d24102f0c9ec1ed61b40d2dec7e089 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 16:13:34 +0100 Subject: [PATCH 23/49] EA-32006 - IAE: PsiSearchHelperImpl.processRequests - defensive copying of FindUsagesOptions --- .../src/com/intellij/find/findUsages/FindUsagesManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 623c38576ed9..2103f229738b 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -358,9 +358,9 @@ public class FindUsagesManager implements JDOMExternalizable { private static UsageSearcher createUsageSearcher(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, final FindUsagesHandler handler, - final FindUsagesOptions options, + FindUsagesOptions _options, final PsiFile scopeFile) { - + final FindUsagesOptions options = _options.clone(); return new UsageSearcher() { @Override public void generate(@NotNull final Processor processor) { From 6b085907a0341cc69ee65da6e57871e86eff251d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 16:18:14 +0100 Subject: [PATCH 24/49] no more stale tailOffset assertions as it won't fail anything (EA-31719) --- .../codeInsight/completion/XmlTagInsertHandler.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java index e55101bd5509..0ad958e47c7c 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java @@ -60,8 +60,6 @@ public class XmlTagInsertHandler implements InsertHandler { public static final XmlTagInsertHandler INSTANCE = new XmlTagInsertHandler(); public void handleInsert(InsertionContext context, LookupElement item) { - LOG.assertTrue(context.getTailOffset() >= 0); - Project project = context.getProject(); Editor editor = context.getEditor(); // Need to insert " " to prevent creating tags like { PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); PsiElement current = context.getFile().findElementAt(context.getStartOffset()); editor.getDocument().deleteString(offset, offset + 1); - LOG.assertTrue(context.getTailOffset() >= 0); final XmlTag tag = PsiTreeUtil.getContextOfType(current, XmlTag.class, true); @@ -87,7 +84,6 @@ public class XmlTagInsertHandler implements InsertHandler { if (descriptor != null) { insertIncompleteTag(context.getCompletionChar(), editor, project, descriptor, tag); - LOG.assertTrue(context.getTailOffset() >= 0); } } else if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) { @@ -112,8 +108,6 @@ public class XmlTagInsertHandler implements InsertHandler { editor.getDocument().deleteString(sOffset, eOffset); assert otherTag != null; editor.getDocument().insertString(sOffset, ((XmlTag)otherTag).getName()); - - LOG.assertTrue(context.getTailOffset() >= 0); } } @@ -122,15 +116,12 @@ public class XmlTagInsertHandler implements InsertHandler { editor.getSelectionModel().removeSelection(); } - LOG.assertTrue(context.getTailOffset() >= 0); - if (context.getCompletionChar() == ' ' && TemplateManager.getInstance(project).getActiveTemplate(editor) != null) { return; } final TailType tailType = LookupItem.handleCompletionChar(editor, item, context.getCompletionChar()); tailType.processTail(editor, editor.getCaretModel().getOffset()); - LOG.assertTrue(context.getTailOffset() >= 0); } private static void insertIncompleteTag(char completionChar, From 81b3af6e4b0eb195b9c0836b7a661ff0dfcc2cb8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 17:04:29 +0100 Subject: [PATCH 25/49] balanced markers when parsing enum constant --- .../parsing/statements/typeDefinitions/members/EnumConstant.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java index 4771add7edf7..fab1f7a20b8d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/members/EnumConstant.java @@ -66,6 +66,7 @@ public class EnumConstant implements GroovyElementTypes { PsiBuilder.Marker enumConstantsMarker = builder.mark(); if (!parseEnumConstant(builder, parser)) { + enumConstantsMarker.drop(); return; } From 7ce982118978323059c49ba9888a237ef9d4dfe3 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 18:21:22 +0100 Subject: [PATCH 26/49] correct containingClass and other properties of stub-based groovy enum constants (EA-31346) --- .../lang/parser/GroovyElementTypes.java | 17 ++++++-- .../typedef/GrEnumDefinitionBody.java | 2 + .../typedef/members/GrEnumConstant.java | 7 +++ .../typedef/GrEnumTypeDefinitionImpl.java | 2 +- .../typedef/GrTypeDefinitionBodyBase.java | 9 +++- .../enumConstant/GrEnumConstantListImpl.java | 22 ++++++++-- .../stubs/elements/GrStubFileElementType.java | 2 +- .../groovy/lang/GroovyStubsTest.groovy | 43 +++++++++++++++++++ 8 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStubsTest.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java index 45a1ce9622d3..e1d73e4cc191 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java @@ -34,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; @@ -45,6 +46,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrOpenBlockI import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterListImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.*; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.enumConstant.GrEnumConstantListImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrAnnotationMethodImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrConstructorImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl; @@ -176,8 +178,12 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy GroovyElementType BLOCK_STATEMENT = new GroovyElementType("Block statement"); - // Enum - GroovyElementType ENUM_CONSTANTS = new GroovyElementType("Enumeration constants"); + EmptyStubElementType ENUM_CONSTANTS = new EmptyStubElementType("Enumeration constants", GroovyFileType.GROOVY_LANGUAGE) { + @Override + public GrEnumConstantList createPsi(@NotNull EmptyStub stub) { + return new GrEnumConstantListImpl(stub); + } + }; GroovyElementType IMPORT_STATEMENT = new GroovyElementType("Import statement"); //Branch statements GroovyElementType BREAK_STATEMENT = new GroovyElementType("Break statement"); @@ -374,7 +380,12 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy } }; - IElementType ENUM_BODY = new GroovyElementType("enum block"); + EmptyStubElementType ENUM_BODY = new EmptyStubElementType("enum block", GroovyFileType.GROOVY_LANGUAGE) { + @Override + public GrEnumDefinitionBody createPsi(@NotNull EmptyStub stub) { + return new GrTypeDefinitionBodyBase.GrEnumBody(stub); + } + }; //statements GroovyElementType IF_STATEMENT = new GroovyElementType("if statement"); GroovyElementType FOR_STATEMENT = new GroovyElementType("for statement"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrEnumDefinitionBody.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrEnumDefinitionBody.java index 76602400da06..c8c3146829a9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrEnumDefinitionBody.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrEnumDefinitionBody.java @@ -15,11 +15,13 @@ */ package org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList; /** * @author ven */ public interface GrEnumDefinitionBody extends GrTypeDefinitionBody { + @Nullable GrEnumConstantList getEnumConstantList(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrEnumConstant.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrEnumConstant.java index 06a6cbad32c0..e87d5d5d5d04 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrEnumConstant.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrEnumConstant.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members; import com.intellij.psi.PsiEnumConstant; +import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -29,6 +30,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConsta */ public interface GrEnumConstant extends GrField, GrConstructorCall, PsiEnumConstant { GrEnumConstant[] EMPTY_ARRAY = new GrEnumConstant[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public GrEnumConstant[] create(int count) { + return new GrEnumConstant[count]; + } + }; @Nullable GrEnumConstantInitializer getInitializingClass(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java index eefe0cdf1e13..42308ec1959b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrEnumTypeDefinitionImpl.java @@ -66,7 +66,7 @@ public class GrEnumTypeDefinitionImpl extends GrTypeDefinitionImpl implements Gr } public GrEnumDefinitionBody getBody() { - return (GrEnumDefinitionBody)findChildByType(GroovyElementTypes.ENUM_BODY); + return getStubOrPsiChild(GroovyElementTypes.ENUM_BODY); } public boolean isEnum() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java index 56cd0a9b72cc..8f25096c52d1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java @@ -173,13 +173,18 @@ public abstract class GrTypeDefinitionBodyBase extends GrStubElementBase { public GrEnumBody(@NotNull ASTNode node) { super(node); } + public GrEnumBody(EmptyStub stub) { + super(stub, GroovyElementTypes.ENUM_BODY); + } + + @Nullable public GrEnumConstantList getEnumConstantList() { - return findChildByClass(GrEnumConstantList.class); + return getStubOrPsiChild(GroovyElementTypes.ENUM_CONSTANTS); } public void accept(GroovyElementVisitor visitor) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantListImpl.java index 115245a45f39..9d379c3c843d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantListImpl.java @@ -17,21 +17,30 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.enumConstant; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.stubs.EmptyStub; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList; +import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase; /** * @author: Dmitry.Krasilschikov * @date: 06.04.2007 */ -public class GrEnumConstantListImpl extends GroovyPsiElementImpl implements GrEnumConstantList { +public class GrEnumConstantListImpl extends GrStubElementBase implements GrEnumConstantList, StubBasedPsiElement { + public GrEnumConstantListImpl(@NotNull ASTNode node) { super(node); } + public GrEnumConstantListImpl(EmptyStub stub) { + super(stub, GroovyElementTypes.ENUM_CONSTANTS); + } + public void accept(GroovyElementVisitor visitor) { visitor.visitEnumConstants(this); } @@ -41,6 +50,11 @@ public class GrEnumConstantListImpl extends GroovyPsiElementImpl implements GrEn } public GrEnumConstant[] getEnumConstants() { - return findChildrenByClass(GrEnumConstant.class); + return getStubOrPsiChildren(GroovyElementTypes.ENUM_CONSTANT, GrEnumConstant.ARRAY_FACTORY); + } + + @Override + public PsiElement getParent() { + return getParentByStub(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java index ea0e80abeea8..1fd9a185609d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java @@ -54,7 +54,7 @@ public class GrStubFileElementType extends IStubFileElementType { @Override public int getStubVersion() { - return super.getStubVersion() + 10; + return super.getStubVersion() + 11; } public String getExternalId() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStubsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStubsTest.groovy new file mode 100644 index 000000000000..504671b77f43 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStubsTest.groovy @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang + +import com.intellij.psi.impl.source.PsiFileImpl +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiShortNamesCache +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumDefinitionBody + +/** + * @author peter + */ +class GroovyStubsTest extends LightCodeInsightFixtureTestCase { + + public void testEnumConstant() { + myFixture.tempDirFixture.createFile('A.groovy', 'enum A { MyEnumConstant }') + GrEnumConstant ec = (GrEnumConstant)PsiShortNamesCache.getInstance(project).getFieldsByName("MyEnumConstant", GlobalSearchScope.allScope(project))[0] + def file = (PsiFileImpl)ec.containingFile + assert file.stub + assert ec.containingClass.qualifiedName == 'A' + assert file.stub + + assert ec in ec.containingClass.fields + assert ec in ((GrEnumDefinitionBody)((GrTypeDefinition)ec.containingClass).body).enumConstantList.enumConstants + assert file.stub + } +} From 24e6828e374fe0ec684077d45eddc39aa2ba8486 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 20 Dec 2011 18:35:43 +0100 Subject: [PATCH 27/49] mem leak in status panel --- .../openapi/wm/impl/status/StatusPanel.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java index 62d49c79c5f1..66ea78ea857a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java @@ -17,9 +17,11 @@ package com.intellij.openapi.wm.impl.status; import com.intellij.notification.EventLog; import com.intellij.notification.Notification; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; @@ -130,7 +132,16 @@ class StatusPanel extends JPanel { text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")"; } setStatusText(text); - myLogAlarm.addRequest(this, 30000); + myLogAlarm.addRequest(this, 30000); + if (project != null) { + final Runnable request = this; + Disposer.register(project, new Disposable() { + @Override + public void dispose() { + myLogAlarm.cancelRequest(request); + } + }); + } } }.run(); } else { From 106b40ed195280eb6403f1fcdd06a28ece861afe Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 18:45:12 +0100 Subject: [PATCH 28/49] diagnosing EA-32678 - NPE: UsageInfoToUsageConverter$TargetElementsDescriptor$.fun --- .../packageDependencies/ui/DependenciesUsagesPanel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java index f85bc3bf68bd..da342e6ceb2f 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java @@ -36,6 +36,7 @@ import com.intellij.usages.UsageInfoToUsageConverter; import com.intellij.util.Consumer; import javax.swing.*; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -87,6 +88,7 @@ public class DependenciesUsagesPanel extends UsagesPanel { elementsToSearch = searchFor; usages = FindDependencyUtil.findDependencies(myBuilders, searchIn, searchFor); } + assert !new HashSet(elementsToSearch).contains(null); } catch (ProcessCanceledException e) { } From 47b9af8d1e794f541ca17ce587e54a54f9ab3d7d Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Tue, 20 Dec 2011 20:50:28 +0300 Subject: [PATCH 29/49] focus fix for progress windows that dont have time to show up and screw focus trackback --- .../openapi/progress/util/ProgressWindow.java | 21 ++++++++++++++----- .../src/com/intellij/ui/FocusTrackback.java | 7 ++++++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 4e680f68474a..ccbb4f8afcc4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -247,19 +247,26 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa super.stop(); + if (isDialogShowing()) { + if (myFocusTrackback != null) { + myFocusTrackback.setWillBeSheduledForRestore(); + } + } UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { - boolean wasShowing = myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing(); + boolean wasShowing = isDialogShowing(); if (myDialog != null) { myDialog.hide(); } - if (wasShowing) { - myFocusTrackback.restoreFocus(); - } else { - myFocusTrackback.consume(); + if (myFocusTrackback != null) { + if (wasShowing) { + myFocusTrackback.restoreFocus(); + } else { + myFocusTrackback.consume(); + } } myStoppedAlready = true; @@ -271,6 +278,10 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa SwingUtilities.invokeLater(EmptyRunnable.INSTANCE); // Just to give blocking dispatching a chance to go out. } + private boolean isDialogShowing() { + return myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing(); + } + public void cancel() { super.cancel(); if (myDialog != null) { diff --git a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java index 7354a8443df0..583474d1ed5f 100644 --- a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java +++ b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java @@ -307,7 +307,12 @@ public class FocusTrackback { if (mustBeLastInStack) { for (int i = index + 1; i < stack.size(); i++) { - if (!stack.get(i).isConsumed()) { + if (!stack.get(i).isMustBeShown()) { + if ((stack.get(i).isSheduledForRestore() || stack.get(i).isWillBeSheduledForRestore()) && !stack.get(i).isConsumed()) { + toFocus = null; + break; + } + } else if (!stack.get(i).isConsumed()) { toFocus = null; break; } From 5ba5d27e67a23a84af90d0621d58bce98ac55f8f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Dec 2011 19:05:13 +0100 Subject: [PATCH 30/49] when project is closed, clear its last notification status from status bar --- .../platform-impl/src/com/intellij/notification/EventLog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index b973cbf6bbe5..f346ef7953d1 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -268,6 +268,7 @@ public class EventLog implements Notifications { @Override public void projectClosed() { + myProjectModel.setStatusMessage(null, 0); getApplicationComponent().myModel.setStatusMessage(null, 0); } From f92a65f6ed0652ee7019ac4881e93b16f2686a8e Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 16:53:50 +0100 Subject: [PATCH 31/49] remember last chosen directory (IDEA-79024) --- .../intellij/ide/util/DirectoryChooser.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/DirectoryChooser.java b/platform/lang-impl/src/com/intellij/ide/util/DirectoryChooser.java index ea8bac8d7fbf..071777a95785 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/DirectoryChooser.java +++ b/platform/lang-impl/src/com/intellij/ide/util/DirectoryChooser.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -55,6 +56,7 @@ import java.util.Map; public class DirectoryChooser extends DialogWrapper { @NonNls private static final String FILTER_NON_EXISTING = "filter_non_existing"; + private static final String DEFAULT_SELECTION = "last_directory_selection"; private final DirectoryChooserView myView; private boolean myFilterExisting; private PsiDirectory myDefaultSelection; @@ -106,6 +108,13 @@ public class DirectoryChooser extends DialogWrapper { if (myTabbedPaneWrapper.getSelectedIndex() == 1) { setSelection(myChooseByNamePanel.getChosenElement()); } + final ItemWrapper item = myView.getSelectedItem(); + if (item != null) { + final PsiDirectory directory = item.getDirectory(); + if (directory != null) { + PropertiesComponent.getInstance(directory.getProject()).setValue(DEFAULT_SELECTION, directory.getVirtualFile().getPath()); + } + } super.doOKAction(); } @@ -363,8 +372,11 @@ public class DirectoryChooser extends DialogWrapper { if (myView.getItemsSize() > 0){ myView.clearItems(); } - if (defaultSelection == null && directories.length > 0) { - defaultSelection = directories[0]; + if (defaultSelection == null) { + defaultSelection = getDefaultSelection(directories, project); + if (defaultSelection == null && directories.length > 0) { + defaultSelection = directories[0]; + } } int selectionIndex = -1; for(int i = 0; i < directories.length; i++){ @@ -437,6 +449,19 @@ public class DirectoryChooser extends DialogWrapper { myView.getComponent().repaint(); } + @Nullable + private static PsiDirectory getDefaultSelection(PsiDirectory[] directories, Project project) { + final String defaultSelectionPath = PropertiesComponent.getInstance(project).getValue(DEFAULT_SELECTION); + if (defaultSelectionPath != null) { + final VirtualFile directoryByDefault = LocalFileSystem.getInstance().findFileByPath(defaultSelectionPath); + if (directoryByDefault != null) { + final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(directoryByDefault); + return directory != null && ArrayUtil.find(directories, directory) > -1 ? directory : null; + } + } + return null; + } + private static boolean isParent(PsiDirectory directory, PsiDirectory parentCandidate) { while (directory != null) { if (directory.equals(parentCandidate)) return true; From 5df622731c8e1fdc054946fd3598051718f53135 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 17:58:44 +0100 Subject: [PATCH 32/49] install plugin with dbl click (IDEA-60594) --- .../ide/plugins/ActionInstallPlugin.java | 8 ++++++-- .../plugins/AvailablePluginsManagerMain.java | 20 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java index dea164fdbb1d..c96d1f09a529 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java @@ -74,6 +74,10 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } public void actionPerformed(AnActionEvent e) { + install(); + } + + public void install() { IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects(); if (userConfirm(selection)) { @@ -113,14 +117,14 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } catch (IOException e1) { PluginManagerMain.LOG.error(e1); - IOExceptionDialog.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed")); + IOExceptionDialog + .showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed")); } getPluginTable().updateUI(); } } - public PluginTable getPluginTable() { return host.getPluginTable(); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java index 4b9139ed5d51..d23a81795535 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java @@ -16,7 +16,10 @@ package com.intellij.ide.plugins; import com.intellij.ide.IdeBundle; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.DumbAware; @@ -30,6 +33,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -87,6 +92,19 @@ public class AvailablePluginsManagerMain extends PluginManagerMain { return ScrollPaneFactory.createScrollPane(pluginTable); } + @Override + protected void installTableActions(final PluginTable pluginTable) { + super.installTableActions(pluginTable); + pluginTable.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() != 2) return; + if (pluginTable.columnAtPoint(e.getPoint()) < 0) return; + if (pluginTable.rowAtPoint(e.getPoint()) < 0) return; + new ActionInstallPlugin(AvailablePluginsManagerMain.this, installed).install(); + } + }); + } + @Override public void reset() { UiNotifyConnector.doWhenFirstShown(getPluginTable(), new Runnable() { From 08b12236e4915b42fb0419a3a08477f3b9331723 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 18:49:52 +0100 Subject: [PATCH 33/49] check if move in subdirectory (IDEA-79141) --- .../MoveClassesOrPackagesToNewDirectoryDialog.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java index 9267fddaf182..bae2a5c929c5 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java @@ -38,8 +38,8 @@ import com.intellij.refactoring.MoveDestination; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.move.MoveCallback; import com.intellij.refactoring.move.MoveHandler; +import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil; import com.intellij.ui.DocumentAdapter; -import com.intellij.ui.IdeBorderFactory; import com.intellij.usageView.UsageViewUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -170,6 +170,13 @@ public class MoveClassesOrPackagesToNewDirectoryDialog extends DialogWrapper { return; } + try { + MoveFilesOrDirectoriesUtil.checkIfMoveIntoSelf(myDirectory, directory); + } + catch (IncorrectOperationException e) { + Messages.showErrorDialog(project, e.getMessage(), RefactoringBundle.message("cannot.move")); + return; + } super.doOKAction(); final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory); From eaeb6d12578b9e23b3dc047abea6e37bc2c0793c Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Dec 2011 21:07:02 +0100 Subject: [PATCH 34/49] convert to instance: remove target class parameter javadoc (IDEA-78892 ) --- .../ConvertToInstanceMethodProcessor.java | 32 ++++++++++++------- .../ParameterUsageInfo.java | 13 ++++---- .../JavadocParameter.java | 10 ++++++ .../JavadocParameter.java.after | 10 ++++++ .../ConvertToInstanceMethodTest.java | 2 ++ 5 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java create mode 100644 java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java index bc976272930f..ee35d83a111f 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodProcessor.java @@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; +import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.search.GlobalSearchScope; @@ -114,8 +115,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } for (final PsiReference ref : ReferencesSearch.search(myTargetParameter, new LocalSearchScope(myMethod), false)) { - if (ref.getElement() instanceof PsiReferenceExpression) { - result.add(new ParameterUsageInfo((PsiReferenceExpression)ref)); + final PsiElement element = ref.getElement(); + if (element instanceof PsiReferenceExpression || element instanceof PsiDocParamRef) { + result.add(new ParameterUsageInfo(ref)); } } @@ -344,15 +346,23 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor { } private void processParameterUsage(ParameterUsageInfo usage) throws IncorrectOperationException { - final PsiJavaCodeReferenceElement referenceExpression = usage.getReferenceExpression(); - if (referenceExpression.getParent() instanceof PsiReferenceExpression) { - // todo: check for correctness - referenceExpression.delete(); - } - else { - final PsiExpression expression = - JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null); - referenceExpression.replace(expression); + final PsiReference reference = usage.getReferenceExpression(); + if (reference instanceof PsiReferenceExpression) { + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)reference; + if (referenceExpression.getParent() instanceof PsiReferenceExpression) { + // todo: check for correctness + referenceExpression.delete(); + } + else { + final PsiExpression expression = + JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null); + referenceExpression.replace(expression); + } + } else { + final PsiElement element = reference.getElement(); + if (element instanceof PsiDocParamRef) { + element.getParent().delete(); + } } } diff --git a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ParameterUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ParameterUsageInfo.java index d73093e9581d..56a2c4cd0e3b 100644 --- a/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ParameterUsageInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/convertToInstanceMethod/ParameterUsageInfo.java @@ -15,22 +15,21 @@ */ package com.intellij.refactoring.convertToInstanceMethod; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiReferenceExpression; +import com.intellij.psi.PsiReference; import com.intellij.usageView.UsageInfo; /** * @author dsl */ class ParameterUsageInfo extends UsageInfo { - private final PsiReferenceExpression myReferenceExpression; + private final PsiReference myReferenceExpression; - public ParameterUsageInfo(PsiReferenceExpression refereneceElement) { - super(refereneceElement); - myReferenceExpression = refereneceElement; + public ParameterUsageInfo(PsiReference referenceElement) { + super(referenceElement); + myReferenceExpression = referenceElement; } - public PsiJavaCodeReferenceElement getReferenceExpression() { + public PsiReference getReferenceExpression() { return myReferenceExpression; } } diff --git a/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java b/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java new file mode 100644 index 000000000000..413e75678055 --- /dev/null +++ b/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java @@ -0,0 +1,10 @@ +class Test { + /** + * method description + * @param a description + */ + public static void main(A a) { + } +} + +class A {} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java.after b/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java.after new file mode 100644 index 000000000000..34491fac484f --- /dev/null +++ b/java/java-tests/testData/refactoring/convertToInstanceMethod/JavadocParameter.java.after @@ -0,0 +1,10 @@ +class Test { +} + +class A { + /** + * method description + */ + public void main() { + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java index bc019202d4f4..99c75fab5296 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/convertToInstanceMethod/ConvertToInstanceMethodTest.java @@ -30,6 +30,8 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase { public void testInterfaceTypeParameter() throws Exception { doTest(0); } + public void testJavadocParameter() throws Exception { doTest(0); } + private void doTest(final int targetParameter) throws Exception { final String filePath = "/refactoring/convertToInstanceMethod/" + getTestName(false) + ".java"; configureByFile(filePath); From 110a280e12612afb5c31d7a2ce27cdaeb28eddc8 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 20 Dec 2011 21:56:03 +0100 Subject: [PATCH 35/49] leaks(cherry picked from commit 68eb942) --- .../openapi/wm/impl/status/StatusPanel.java | 83 ++++++++++--------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java index 66ea78ea857a..06f191463cba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java @@ -17,11 +17,9 @@ package com.intellij.openapi.wm.impl.status; import com.intellij.notification.EventLog; import com.intellij.notification.Notification; -import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; @@ -44,7 +42,7 @@ class StatusPanel extends JPanel { private boolean myLogMode; private boolean myDirty; private boolean myAfterClick; - private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + private Alarm myLogAlarm; private final TextPanel myTextPanel = new TextPanel() { @Override protected String getTextForPreferredSize() { @@ -105,6 +103,17 @@ class StatusPanel extends JPanel { return null; } + private Alarm getAlarm() { + if (myLogAlarm == null || myLogAlarm.isDisposed()) { + myLogAlarm = null; //Welcome screen + Project project = getActiveProject(); + if (project != null) { + myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project); + } + } + return myLogAlarm; + } + public void setLogMessage(String text) { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -119,35 +128,30 @@ class StatusPanel extends JPanel { final Project project = getActiveProject(); final Pair statusMessage = EventLog.getStatusMessage(project); myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null; - myLogAlarm.cancelAllRequests(); + final Alarm alarm = getAlarm(); - if (myLogMode) { - myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - new Runnable() { - @Override - public void run() { - assert statusMessage != null; - String text = EventLog.formatForLog(statusMessage.first).status; - if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) { - text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")"; + if (alarm != null) { + alarm.cancelAllRequests(); + + if (myLogMode) { + myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + new Runnable() { + @Override + public void run() { + assert statusMessage != null; + String text = EventLog.formatForLog(statusMessage.first).status; + if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) { + text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")"; + } + setStatusText(text); + alarm.addRequest(this, 30000); } - setStatusText(text); - myLogAlarm.addRequest(this, 30000); - if (project != null) { - final Runnable request = this; - Disposer.register(project, new Disposable() { - @Override - public void dispose() { - myLogAlarm.cancelRequest(request); - } - }); - } - } - }.run(); - } else { - myTextPanel.setCursor(Cursor.getDefaultCursor()); - myDirty = true; - setStatusText(nonLogText); + }.run(); + } else { + myTextPanel.setCursor(Cursor.getDefaultCursor()); + myDirty = true; + setStatusText(nonLogText); + } } return myLogMode; } @@ -166,15 +170,18 @@ class StatusPanel extends JPanel { } public void restoreLogIfNeeded() { - myLogAlarm.cancelAllRequests(); - myLogAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (StringUtil.isEmpty(myTextPanel.getText())) { - updateText(true, ""); + Alarm alarm = getAlarm(); + if (alarm != null) { + alarm.cancelAllRequests(); + alarm.addRequest(new Runnable() { + @Override + public void run() { + if (StringUtil.isEmpty(myTextPanel.getText())) { + updateText(true, ""); + } } - } - }, 300); + }, 300); + } } public String getText() { From ec8c2c006dc7499824c6ace7b292a40081077114 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 21 Dec 2011 00:23:59 +0100 Subject: [PATCH 36/49] assertion fix --- .../platform-impl/src/com/intellij/notification/EventLog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index f346ef7953d1..b973cbf6bbe5 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -268,7 +268,6 @@ public class EventLog implements Notifications { @Override public void projectClosed() { - myProjectModel.setStatusMessage(null, 0); getApplicationComponent().myModel.setStatusMessage(null, 0); } From 2a709b4b728e2da7a590d67ae4c92a57c09ddffd Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 21 Dec 2011 10:14:23 +0400 Subject: [PATCH 37/49] xdebugger api: breakpoint editors can depend on project --- .../com/intellij/xdebugger/breakpoints/XBreakpointType.java | 4 ++-- .../impl/breakpoints/ui/XBreakpointPropertiesPanel.java | 2 +- .../impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index ccded14b5c56..405fdbf069fc 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -119,7 +119,7 @@ public abstract class XBreakpointType, P extends XBreak } /** - * @deprecated override {@link #getEditorsProvider(XBreakpoint)} instead + * @deprecated override {@link #getEditorsProvider(B, com.intellij.openapi.project.Project)} instead */ @Nullable public XDebuggerEditorsProvider getEditorsProvider() { @@ -127,7 +127,7 @@ public abstract class XBreakpointType, P extends XBreak } @Nullable - public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint) { + public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint, @NotNull Project project) { return getEditorsProvider(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPropertiesPanel.java index 04dc11f69023..c145d23283dc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPropertiesPanel.java @@ -63,7 +63,7 @@ public class XBreakpointPropertiesPanel> { mySuspendPolicyPanel.init(project, breakpointManager, breakpoint); - XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint); + XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project); myBreakpointActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index ca5e69bb1372..051401fd6739 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -105,7 +105,7 @@ public class XLightBreakpointPropertiesPanel> implement mySubPanels.add(mySuspendPolicyPanel); myMasterBreakpointPanel.init(project, breakpointManager, breakpoint); mySubPanels.add(myMasterBreakpointPanel); - XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint); + XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project); myActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider); mySubPanels.add(myActionsPanel); From 354418717a69cae235dac9dbf3af57b565081ef4 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 21 Dec 2011 10:51:03 +0400 Subject: [PATCH 38/49] fix test --- .../plugins/groovy/refactoring/copy/GroovyCopyClassTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/copy/GroovyCopyClassTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/copy/GroovyCopyClassTest.groovy index 0e5a7605e992..c497fda75130 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/copy/GroovyCopyClassTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/copy/GroovyCopyClassTest.groovy @@ -60,6 +60,6 @@ public class GroovyCopyClassTest extends LightCodeInsightFixtureTestCase { def psiFile = myFixture.psiManager.findFile(file) //would be copied as file assertFalse(CopyClassesHandler.canCopyClass(myFixture.javaFacade.findClass("foo.$testName", GlobalSearchScope.allScope(project)))); - assertFalse(CopyClassesHandler.canCopyClass(psiFile)); + assertTrue(CopyClassesHandler.canCopyClass(psiFile)); } } From 8d8c0c3dbef66c33952e9ba3e8687d22d6a98705 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 21 Dec 2011 11:53:14 +0400 Subject: [PATCH 39/49] preserve custom prefix for tag name completion --- .../codeInsight/completion/XmlCompletionContributor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java index bcde765f388d..d293ff34118e 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionContributor.java @@ -150,10 +150,11 @@ public class XmlCompletionContributor extends CompletionContributor { final String namespace = tag.getNamespace(); final String prefix = result.getPrefixMatcher().getPrefix(); final int pos = prefix.indexOf(':'); - final String namespacePrefix = pos > 0 ? prefix.substring(0, pos) : null; final PsiReference reference = tag.getReference(); - if (reference != null && !namespace.isEmpty() && !tag.getNamespacePrefix().isEmpty()) { + String namespacePrefix = tag.getNamespacePrefix(); + + if (reference != null && !namespace.isEmpty() && !namespacePrefix.isEmpty()) { // fallback to simple completion final Set set = new HashSet(); new XmlCompletionData().completeReference(reference, set, element, parameters.getOriginalFile(), parameters.getOffset()); @@ -170,7 +171,7 @@ public class XmlCompletionContributor extends CompletionContributor { for (Pair pair : names) { final String name = pair.getFirst(); final String ns = pair.getSecond(); - final LookupElement item = createLookupElement(name, ns, ns, namespacePrefix); + final LookupElement item = createLookupElement(name, ns, ns, namespacePrefix.isEmpty() ? null : namespacePrefix); newResult.addElement(item); } } From 81136098c0c074303899bc25d8aa53efad9dc638 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Dec 2011 19:41:53 +0400 Subject: [PATCH 40/49] IDEA-78828 Java Depend Order - broken --- .../com/intellij/psi/impl/JavaPsiFacadeImpl.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index cea124217dae..2d939ed05086 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -299,7 +299,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { @Override @NotNull - public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) { List list = null; String packageName = psiPackage.getQualifiedName(); for (PsiDirectory dir : psiPackage.getDirectories(scope)) { @@ -315,9 +315,18 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { } } } - return list == null ? PsiClass.EMPTY_ARRAY : list.toArray(new PsiClass[list.size()]); - } + if (list == null) { + return PsiClass.EMPTY_ARRAY; + } + ContainerUtil.quickSort(list, new Comparator() { + @Override + public int compare(PsiClass o1, PsiClass o2) { + return scope.compare(o2.getContainingFile().getVirtualFile(), o1.getContainingFile().getVirtualFile()); + } + }); + return list.toArray(new PsiClass[list.size()]); + } @Override public Set getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { From e6e62bc7076303db944969ada4743c66018e6be7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 21 Dec 2011 13:06:42 +0400 Subject: [PATCH 41/49] catch more exceptions during tearDown() --- .../src/com/intellij/testFramework/PlatformTestCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index a1f279e041cb..dfaf270a37ac 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -445,7 +445,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro try { LightPlatformTestCase.checkEditorsReleased(); } - catch (AssertionError error) { + catch (Throwable error) { result.add(error); } } From e2539319872d0f33dd3f8f25b119432e07f6ba54 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 21 Dec 2011 13:04:37 +0400 Subject: [PATCH 42/49] Test fixes 1. Don't try to match test data during tests execution; 2. Moved matching logic to 'collect slow line markers'; --- .../TestDataLineMarkerProvider.java | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java index 4337b4ae59a8..19c96dfdf501 100644 --- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java +++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java @@ -1,9 +1,25 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.testAssistant; import com.intellij.codeHighlighting.Pass; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; @@ -22,14 +38,6 @@ import java.util.List; */ public class TestDataLineMarkerProvider implements LineMarkerProvider { public LineMarkerInfo getLineMarkerInfo(PsiElement element) { - if (!(element instanceof PsiMethod)) { - return null; - } - final PsiMethod method = (PsiMethod)element; - if (isTestMethod(method)) { - return new LineMarkerInfo(method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, - new TestDataNavigationHandler()); - } return null; } @@ -56,6 +64,20 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider { } public void collectSlowLineMarkers(List elements, Collection result) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return; + } + for (PsiElement element : elements) { + if (!(element instanceof PsiMethod)) { + continue; + } + final PsiMethod method = (PsiMethod)element; + if (isTestMethod(method)) { + result.add(new LineMarkerInfo( + method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, new TestDataNavigationHandler() + )); + } + } } @Nullable @@ -69,13 +91,17 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider { final Object constantValue = evaluationHelper.computeConstantExpression(value, false); if (constantValue instanceof String) { String path = (String) constantValue; - if (path.indexOf("$CONTENT_ROOT") >= 0) { + if (path.contains("$CONTENT_ROOT")) { final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); - final VirtualFile contentRoot = fileIndex.getContentRootForFile(psiClass.getContainingFile().getVirtualFile()); + final VirtualFile file = psiClass.getContainingFile().getVirtualFile(); + if (file == null) { + return null; + } + final VirtualFile contentRoot = fileIndex.getContentRootForFile(file); if (contentRoot == null) return null; path = path.replace("$CONTENT_ROOT", contentRoot.getPath()); } - if (path.indexOf("$PROJECT_ROOT") >= 0) { + if (path.contains("$PROJECT_ROOT")) { final VirtualFile baseDir = project.getBaseDir(); if (baseDir == null) { return null; From 1355b64db4ab222e91b8842c81d0a39a92132fd4 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 21 Dec 2011 13:26:21 +0400 Subject: [PATCH 43/49] always escape symbols when text is pasted to groovy string literal --- .../StringLiteralCopyPasteProcessor.java | 14 +-- .../GroovyLiteralCopyPasteProcessor.java | 103 ++++++++++++------ .../groovy/lang/psi/util/GrStringUtil.java | 79 ++++++++++++-- 3 files changed, 143 insertions(+), 53 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java index 31ffdc25d1a7..f79099f4c2db 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java @@ -132,11 +132,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { } if (isStringLiteral(token)) { - boolean escapeSlashes = true; if (rawText != null && rawText.rawText != null) { - //is is assumed that all slashes are escaped in the raw text but some unescaped symbols can present (for example " copied from CharLiteral '"') - //so we should escape all needed symbols except slash. - escapeSlashes = false; text = rawText.rawText; } @@ -144,7 +140,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { @NonNls String breaker = getLineBreaker(token); final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true); for (int i = 0; i < lines.length; i++) { - buffer.append(escapeCharCharacters(lines[i], token, escapeSlashes)); + buffer.append(escapeCharCharacters(lines[i], token)); if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) { buffer.append(breaker); } @@ -153,10 +149,10 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { } else if (isCharLiteral(token)) { if (rawText != null && rawText.rawText != null) { - return escapeCharCharacters(rawText.rawText, token, false); + return escapeCharCharacters(rawText.rawText, token); } else { - return escapeCharCharacters(text, token, true); + return escapeCharCharacters(text, token); } } return text; @@ -206,9 +202,9 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { } @NotNull - protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) { + protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) { StringBuilder buffer = new StringBuilder(); - StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'",escapeSlashes, buffer); + StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'", buffer); return buffer.toString(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java index db50abfabe87..650d9c1bbd24 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java @@ -17,14 +17,23 @@ package org.jetbrains.plugins.groovy.lang.editor; import com.intellij.codeInsight.editorActions.StringLiteralCopyPasteProcessor; import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RawText; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; @@ -106,51 +115,81 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce } - @NotNull @Override - protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) { - IElementType tokenType = token.getNode().getElementType(); + public String preprocessOnPaste(Project project, PsiFile file, Editor editor, String text, RawText rawText) { + final Document document = editor.getDocument(); + PsiDocumentManager.getInstance(project).commitDocument(document); + final SelectionModel selectionModel = editor.getSelectionModel(); - if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) { - if (escapeSlashes) { - return StringUtil.escapeSlashes(s); - } - else { - return s; - } + // pastes in block selection mode (column mode) are not handled by a CopyPasteProcessor + final int selectionStart = selectionModel.getSelectionStart(); + final int selectionEnd = selectionModel.getSelectionEnd(); + PsiElement token = findLiteralTokenType(file, selectionStart, selectionEnd); + if (token == null) { + return text; } - String chars; - if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) { - if (token.getText().contains("\"\"\"")) { - chars = "$"; - } - else { - chars = "\"$"; + if (isStringLiteral(token)) { + StringBuilder buffer = new StringBuilder(text.length()); + @NonNls String breaker = getLineBreaker(token); + final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true); + for (int i = 0; i < lines.length; i++) { + buffer.append(escapeCharCharacters(lines[i], token)); + if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) { + buffer.append(breaker); + } } + text = buffer.toString(); } - else if (tokenType == mSTRING_LITERAL && !token.getText().contains("'''")) { - chars = "'"; - } - else { - chars = ""; - } - - StringBuilder buffer = new StringBuilder(); - StringUtil.escapeStringCharacters(s.length(), s, chars, escapeSlashes, buffer); - return buffer.toString(); + return text; } @NotNull @Override - protected String unescape(String text, PsiElement token) { - final IElementType tokenType = token.getNode().getElementType(); + protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) { + IElementType tokenType = token.getNode().getElementType(); - if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) { - return StringUtil.unescapeSlashes(text); + if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) { + return GrStringUtil.escapeForSlashyStrings(s); } - return super.unescape(text, token); + if (tokenType == mDOLLAR_SLASH_REGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_LITERAL) { + return GrStringUtil.escapeSymbolsForDollarSlashyStrings(s); + } + + if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) { + return GrStringUtil.escapeSymbolsForGString(s, !token.getText().contains("\"\"\"")); + } + + if (tokenType == mSTRING_LITERAL) { + return GrStringUtil.escapeSymbolsForString(s, !token.getText().contains("'''")); + } + + return super.escapeCharCharacters(s, token); + } + + @NotNull + @Override + protected String unescape(String s, PsiElement token) { + final IElementType tokenType = token.getNode().getElementType(); + + if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) { + return GrStringUtil.unescapeSlashyString(s); + } + + if (tokenType == mDOLLAR_SLASH_REGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_LITERAL) { + return GrStringUtil.unescapeDollarSlashyString(s); + } + + if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) { + return StringUtil.unescapeStringCharacters(s); + } + + if (tokenType == mSTRING_LITERAL) { + return StringUtil.unescapeStringCharacters(s); + } + + return super.unescape(s, token); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java index 68037fe17eef..e5fed4659e7b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java @@ -35,6 +35,67 @@ public class GrStringUtil { private GrStringUtil() { } + public static String unescapeSlashyString(String s) { + return unescapeRegex(s, true); + } + + public static String unescapeDollarSlashyString(String s) { + return unescapeRegex(s, false); + } + + private static String unescapeRegex(String s, boolean unescapeSlash) { + final int length = s.length(); + StringBuilder buffer = new StringBuilder(length); + + boolean escaped = false; + for (int idx = 0; idx < length; idx++) { + char ch = s.charAt(idx); + if (!escaped) { + if (ch == '\\') { + escaped = true; + } + else { + buffer.append(ch); + } + } + else { + switch (ch) { + case '/': + if (!unescapeSlash) { + buffer.append('\\'); + } + buffer.append('/'); + break; + case 'u': + if (idx + 4 < length) { + try { + int code = Integer.valueOf(s.substring(idx + 1, idx + 5), 16).intValue(); + idx += 4; + buffer.append((char)code); + } + catch (NumberFormatException e) { + buffer.append("\\u"); + } + } + else { + buffer.append("\\u"); + } + break; + + default: + buffer.append('\\'); + buffer.append(ch); + break; + } + escaped = false; + } + } + + if (escaped) buffer.append('\\'); + return buffer.toString(); + } + + public static String escapeForSlashyStrings(String str) { final StringBuilder buffer = new StringBuilder(str.length()); escapeSymbolsForSlashyStrings(buffer, str); @@ -105,7 +166,7 @@ public class GrStringUtil { public static String escapeSymbolsForGString(String s, boolean escapeDoubleQuotes, boolean forInjection) { StringBuilder b = new StringBuilder(); - escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", false, forInjection, b); + escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", forInjection, b); if (!forInjection) { unescapeCharacters(b, escapeDoubleQuotes ? "'" : "'\"", true); } @@ -118,7 +179,7 @@ public class GrStringUtil { public static String escapeSymbolsForString(String s, boolean escapeQuotes, boolean forInjection) { final StringBuilder builder = new StringBuilder(); - escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", false, forInjection, builder); + escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", forInjection, builder); if (!forInjection) { unescapeCharacters(builder, escapeQuotes ? "$\"" : "$'\"", true); } @@ -129,8 +190,7 @@ public class GrStringUtil { public static StringBuilder escapeStringCharacters(int length, @NotNull String str, @Nullable String additionalChars, - boolean escapeNR, - boolean escapeSlash, + boolean escapeLineFeeds, @NotNull @NonNls StringBuilder buffer) { for (int idx = 0; idx < length; idx++) { char ch = str.charAt(idx); @@ -148,16 +208,11 @@ public class GrStringUtil { break; case '\\': - if (escapeSlash) { - buffer.append("\\\\"); - } - else { - buffer.append("\\"); - } + buffer.append("\\\\"); break; case '\n': - if (escapeNR) { + if (escapeLineFeeds) { buffer.append("\\n"); } else { @@ -166,7 +221,7 @@ public class GrStringUtil { break; case '\r': - if (escapeNR) { + if (escapeLineFeeds) { buffer.append("\\r"); } else { From bc730581555b7fc8db959b48f147b0102d6ee58a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 21 Dec 2011 11:38:59 +0100 Subject: [PATCH 44/49] register missing extension --- .../src/com/intellij/core/JavaCoreEnvironment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java index b48ba051d82d..ba04ff0d99b3 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java @@ -27,6 +27,7 @@ import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.EmptySubstitutorImpl; import com.intellij.psi.impl.JavaPsiFacadeImpl; import com.intellij.psi.impl.JavaPsiImplementationHelper; @@ -60,6 +61,7 @@ public class JavaCoreEnvironment extends CoreEnvironment { registerProjectExtensionPoint(PsiElementFinder.EP_NAME, PsiElementFinder.class); registerExtensionPoint(Extensions.getRootArea(), ClsStubBuilderFactory.EP_NAME, ClsStubBuilderFactory.class); + registerExtensionPoint(Extensions.getRootArea(), PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class); addExtension(ClsStubBuilderFactory.EP_NAME, new DefaultClsStubBuilderFactory()); myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper()); From 3296eddd4f76fb5c72303a7466c200f4f27682b6 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 19 Dec 2011 18:48:45 +0400 Subject: [PATCH 45/49] IDEA-69831 references can be values of simple xml resources --- .../android/dom/AdditionalConverter.java | 17 +++ .../QuietResourceReferenceConverter.java | 10 ++ .../ResourceReferenceConverter.java | 127 +++++++++++------- .../android/dom/resources/ArrayElement.java | 12 ++ .../android/dom/resources/BoolElement.java | 5 +- .../dom/resources/IntegerArrayItem.java | 5 +- .../android/dom/resources/IntegerElement.java | 5 +- .../jetbrains/android/dom/resources/Item.java | 6 +- .../android/dom/resources/Resources.java | 12 +- .../dom/resources/ScalarResourceElement.java | 11 ++ .../android/dom/resources/StringArray.java | 4 +- .../android/dom/resources/StringElement.java | 4 + .../LocalResourceManager.java | 2 +- .../dom/layout/createResourceFromUsage.xml | 9 ++ ...createResourceFromUsage_drawable_after.xml | 3 + .../dom/resources/createResourceFromUsage.xml | 3 + .../createResourceFromUsage_after.xml | 4 + .../resourceReferenceAsValueCompletion1.xml | 9 ++ ...ourceReferenceAsValueCompletion1_after.xml | 9 ++ .../resourceReferenceAsValueCompletion2.xml | 9 ++ ...ourceReferenceAsValueCompletion2_after.xml | 9 ++ .../resourceReferenceAsValueCompletion3.xml | 9 ++ .../resourceReferenceAsValueCompletion4.xml | 9 ++ .../resourceReferenceAsValueHighlighting.xml | 82 +++++++++++ .../android/dom/AndroidLayoutDomTest.java | 33 +++++ .../dom/AndroidValueResourcesTest.java | 55 ++++++++ 26 files changed, 403 insertions(+), 60 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/dom/AdditionalConverter.java create mode 100644 plugins/android/src/org/jetbrains/android/dom/converters/QuietResourceReferenceConverter.java create mode 100644 plugins/android/src/org/jetbrains/android/dom/resources/ArrayElement.java create mode 100644 plugins/android/src/org/jetbrains/android/dom/resources/ScalarResourceElement.java create mode 100644 plugins/android/testData/dom/layout/createResourceFromUsage.xml create mode 100644 plugins/android/testData/dom/layout/createResourceFromUsage_drawable_after.xml create mode 100644 plugins/android/testData/dom/resources/createResourceFromUsage.xml create mode 100644 plugins/android/testData/dom/resources/createResourceFromUsage_after.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion1.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion1_after.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion2.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion2_after.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion3.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueCompletion4.xml create mode 100644 plugins/android/testData/dom/resources/resourceReferenceAsValueHighlighting.xml diff --git a/plugins/android/src/org/jetbrains/android/dom/AdditionalConverter.java b/plugins/android/src/org/jetbrains/android/dom/AdditionalConverter.java new file mode 100644 index 000000000000..e0548b50854c --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/dom/AdditionalConverter.java @@ -0,0 +1,17 @@ +package org.jetbrains.android.dom; + +import com.intellij.util.xml.ResolvingConverter; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Eugene.Kudelevsky + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface AdditionalConverter { + Class value(); +} diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/QuietResourceReferenceConverter.java b/plugins/android/src/org/jetbrains/android/dom/converters/QuietResourceReferenceConverter.java new file mode 100644 index 000000000000..85f9bfbea8af --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/dom/converters/QuietResourceReferenceConverter.java @@ -0,0 +1,10 @@ +package org.jetbrains.android.dom.converters; + +/** + * @author Eugene.Kudelevsky + */ +public class QuietResourceReferenceConverter extends ResourceReferenceConverter { + public QuietResourceReferenceConverter() { + setQuiet(true); + } +} diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java index 55c070b6fcd7..ad7fee9ff8a5 100644 --- a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java +++ b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java @@ -18,6 +18,7 @@ package org.jetbrains.android.dom.converters; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.command.undo.UndoUtil; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; @@ -28,11 +29,9 @@ import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import com.intellij.util.PsiNavigateUtil; -import com.intellij.util.xml.ConvertContext; -import com.intellij.util.xml.CustomReferenceConverter; -import com.intellij.util.xml.GenericDomValue; -import com.intellij.util.xml.ResolvingConverter; +import com.intellij.util.xml.*; import org.jetbrains.android.dom.ResourceType; +import org.jetbrains.android.dom.AdditionalConverter; import org.jetbrains.android.dom.resources.Item; import org.jetbrains.android.dom.resources.ResourceElement; import org.jetbrains.android.dom.resources.ResourceValue; @@ -61,6 +60,7 @@ public class ResourceReferenceConverter extends ResolvingConverter()); @@ -81,6 +81,10 @@ public class ResourceReferenceConverter extends ResolvingConverter additionalConverter = getAdditionalConverter(context); + + if (additionalConverter != null) { + for (String variant : additionalConverter.getVariants(context)) { result.add(ResourceValue.literal(variant)); } } @@ -162,6 +171,9 @@ public class ResourceReferenceConverter extends ResolvingConverter additionalConverter = getAdditionalConverter(context); + + if ((parsed == null || !parsed.isReference()) && additionalConverter != null) { + String value = additionalConverter.fromString(s, context); if (value != null) { return ResourceValue.literal(value); } @@ -224,6 +238,27 @@ public class ResourceReferenceConverter extends ResolvingConverter getAdditionalConverter(ConvertContext context) { + if (myAdditionalConverter != null) { + return myAdditionalConverter; + } + + final AdditionalConverter additionalConverterAnnotation = + context.getInvocationElement().getAnnotation(AdditionalConverter.class); + + if (additionalConverterAnnotation != null) { + final Class converterClass = additionalConverterAnnotation.value(); + + if (converterClass != null) { + final ConverterManager converterManager = ServiceManager.getService(ConverterManager.class); + //noinspection unchecked + return (ResolvingConverter)converterManager.getConverterInstance(converterClass); + } + } + return null; + } + public String toString(@Nullable ResourceValue resourceElement, ConvertContext context) { return resourceElement != null ? resourceElement.toString() : null; } @@ -232,22 +267,24 @@ public class ResourceReferenceConverter extends ResolvingConverter getStrings(); StringElement addString(); - List getColors(); - ResourceElement addColor(); + List getColors(); + ScalarResourceElement addColor(); - List getDrawables(); - ResourceElement addDrawable(); + List getDrawables(); + ScalarResourceElement addDrawable(); - List getDimens(); - ResourceElement addDimen(); + List getDimens(); + ScalarResourceElement addDimen(); List