From 5fa8a1d7ddbf5aa84249647247797a0cddb9aaa4 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 4 Aug 2011 17:46:18 +0200 Subject: [PATCH 01/77] fix spelling and cleanup --- .../cvsSupport2/connections/CvsRootData.java | 12 +++++------- .../intellij/cvsSupport2/application/CvsInfo.java | 4 ++-- .../connections/ext/ExtConnectionCvsSettings.java | 2 +- .../connections/pserver/PServerCvsSettings.java | 2 +- .../connections/ssh/SshConnectionSettings.java | 6 +++--- .../intellij/cvsSupport2/impl/CvsServicesImpl.java | 13 ++++++------- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsRootData.java b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsRootData.java index a6f332ecd9b1..c8f91d1559e0 100644 --- a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsRootData.java +++ b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsRootData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -21,7 +21,7 @@ import com.intellij.openapi.util.Comparing; * author: lesya */ public class CvsRootData implements CvsSettings{ - protected final String myStringRepsentation; + private final String myStringRepresentation; public CvsMethod METHOD = null; public String HOST = ""; public String USER = ""; @@ -32,13 +32,12 @@ public class CvsRootData implements CvsSettings{ public String PROXY_PORT = null; public boolean CONTAINS_PROXY_INFO = false; - - public CvsRootData(String stringRepsentation) { - myStringRepsentation = stringRepsentation; + public CvsRootData(String stringRepresentation) { + myStringRepresentation = stringRepresentation; } public String getCvsRootAsString() { - return myStringRepsentation; + return myStringRepresentation; } public boolean equals(Object object) { @@ -57,7 +56,6 @@ public class CvsRootData implements CvsSettings{ return methodHashCode ^ HOST.hashCode() ^ USER.hashCode() ^ REPOSITORY.hashCode() ^ PORT; } - public void setPassword(String password) { PASSWORD = password; } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsInfo.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsInfo.java index 3ea5b8815cda..1683c8e28596 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsInfo.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsInfo.java @@ -295,8 +295,8 @@ public class CvsInfo { public ThreeState silentLogin(boolean forceCheck) { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { - new VcsBalloonProblemNotifier(project, CvsBundle.message("message.error.invalid.cvs.root", myStringRepsentation), - MessageType.ERROR).run(); + new VcsBalloonProblemNotifier(project, CvsBundle.message("message.error.invalid.cvs.root", getCvsRootAsString()), + MessageType.ERROR).run(); } }); return ThreeState.NO; diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ext/ExtConnectionCvsSettings.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ext/ExtConnectionCvsSettings.java index e11e37232ae1..2f677889424d 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ext/ExtConnectionCvsSettings.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ext/ExtConnectionCvsSettings.java @@ -79,7 +79,7 @@ public class ExtConnectionCvsSettings extends CvsConnectionSettings { public boolean promptForPassword() { if (! mySshChecked) { mySshChecked = true; - return SshConnectionUtil.promptForPassword(mySshSettings, myStringRepsentation); + return SshConnectionUtil.promptForPassword(mySshSettings, getCvsRootAsString()); } return myWorker.promptForPassword(); } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/PServerCvsSettings.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/PServerCvsSettings.java index 6656c0d4c75a..252ca2b32390 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/PServerCvsSettings.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/PServerCvsSettings.java @@ -38,7 +38,7 @@ public class PServerCvsSettings extends CvsConnectionSettings { protected IConnection createOriginalConnection(ErrorRegistry errorRegistry, CvsRootConfiguration cvsRootConfiguration) { if (PASSWORD == null) { - PASSWORD = PServerLoginProvider.getInstance().getScrambledPasswordForCvsRoot(myStringRepsentation); + PASSWORD = PServerLoginProvider.getInstance().getScrambledPasswordForCvsRoot(getCvsRootAsString()); } return CvsConnectionUtil.createPServerConnection(this, cvsRootConfiguration.PROXY_SETTINGS, getTimeoutMillis()); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionSettings.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionSettings.java index f8a1f17a4882..37aaa9aedeff 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionSettings.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionSettings.java @@ -68,7 +68,7 @@ public class SshConnectionSettings extends CvsConnectionSettings { } public CvsLoginWorkerImpl getLoginWorker(ModalityContext executor, Project project) { - return new MyLoginWorker(project, executor, myStringRepsentation, this); + return new MyLoginWorker(project, executor, getCvsRootAsString(), this); } private class MyLoginWorker extends CvsLoginWorkerImpl { @@ -82,9 +82,9 @@ public class SshConnectionSettings extends CvsConnectionSettings { @Override protected void clearOldCredentials() { if (getSshConfiguration().USE_PPK) { - SSHPasswordProviderImpl.getInstance().removePPKPasswordFor(myStringRepsentation); + SSHPasswordProviderImpl.getInstance().removePPKPasswordFor(getCvsRootAsString()); } else { - SSHPasswordProviderImpl.getInstance().removePasswordFor(myStringRepsentation); + SSHPasswordProviderImpl.getInstance().removePasswordFor(getCvsRootAsString()); } } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/impl/CvsServicesImpl.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/impl/CvsServicesImpl.java index 4b5e7adaa1cd..ad4b7cb61aa8 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/impl/CvsServicesImpl.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/impl/CvsServicesImpl.java @@ -73,23 +73,22 @@ public class CvsServicesImpl extends CvsServices { } public CvsRepository[] getConfiguredRepositories() { - List configurations = CvsApplicationLevelConfiguration.getInstance().CONFIGURATIONS; + List configurations = CvsApplicationLevelConfiguration.getInstance().CONFIGURATIONS; CvsRepository[] result = new CvsRepository[configurations.size()]; for (int i = 0; i < configurations.size(); i++) { - result[i] = ((CvsRootConfiguration)configurations.get(i)).createCvsRepository(); + result[i] = configurations.get(i).createCvsRepository(); } return result; } private static ComparableVcsRevisionOnOperation createCvsVersionOn(CvsModule module, Project project) { final CvsRootConfiguration rootConfiguration = CvsApplicationLevelConfiguration.getInstance() - .getConfigurationForCvsRoot(module.getRepository() - .getStringRepresentation()); + .getConfigurationForCvsRoot(module.getRepository().getStringRepresentation()); CvsConnectionSettings env = new IDEARootFormatter(rootConfiguration).createConfiguration(); - GetFileContentOperation operation = new GetFileContentOperation(new File(module.getPathInCvs()), - env, new SimpleRevision(module.getRevision()) - ); + GetFileContentOperation operation = + new GetFileContentOperation(new File(module.getPathInCvs()), + env, new SimpleRevision(module.getRevision())); return new ComparableVcsRevisionOnOperation(operation, project); From 12dc18355263d87fce8519b8a063f2a10ea2a751 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 5 Aug 2011 12:53:53 +0200 Subject: [PATCH 02/77] Filter out globally ignored files from status/update results if they are not contained in the CVS repository IDEA-37008 (.DS_Store files not filtered out when doing CVS update or check status) --- .../cvsSupport2/CvsStatusEnvironment.java | 7 ++++--- .../cvsSupport2/CvsUpdateEnvironment.java | 9 ++++----- .../updateinfo/UpdatedFilesProcessor.java | 17 ++++++++++------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsStatusEnvironment.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsStatusEnvironment.java index bec976b09de9..796ec760aa33 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsStatusEnvironment.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsStatusEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -47,12 +47,13 @@ public class CvsStatusEnvironment implements UpdateEnvironment { } @NotNull - public UpdateSession updateDirectories(@NotNull FilePath[] contentRoots, final UpdatedFiles updatedFiles, ProgressIndicator progressIndicator, + public UpdateSession updateDirectories(@NotNull FilePath[] contentRoots, final UpdatedFiles updatedFiles, + ProgressIndicator progressIndicator, @NotNull final Ref context) { final UpdateSettings updateSettings = UpdateSettings.DONT_MAKE_ANY_CHANGES; final UpdateHandler handler = CommandCvsHandler.createUpdateHandler(contentRoots, updateSettings, myProject, updatedFiles); - handler.addCvsListener(new UpdatedFilesProcessor(myProject, updatedFiles)); + handler.addCvsListener(new UpdatedFilesProcessor(updatedFiles)); CvsOperationExecutor cvsOperationExecutor = new CvsOperationExecutor(true, myProject, ModalityState.defaultModalityState()); cvsOperationExecutor.setShowErrors(false); cvsOperationExecutor.performActionSync(handler, CvsOperationExecutorCallback.EMPTY); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUpdateEnvironment.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUpdateEnvironment.java index dc937e307807..509c400f92b1 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUpdateEnvironment.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUpdateEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -65,7 +65,6 @@ public class CvsUpdateEnvironment implements UpdateEnvironment { private static class CvsSequentialUpdateContext implements SequentialUpdatesContext { private final UpdateSettingsOnCvsConfiguration myConfiguration; private final String myUpdateTagName; - private final static String error = "merge.wasnt.started.only.update.was.performed"; private CvsSequentialUpdateContext(final UpdateSettingsOnCvsConfiguration configuration, final String tagName) { myUpdateTagName = tagName; @@ -90,8 +89,8 @@ public class CvsUpdateEnvironment implements UpdateEnvironment { } } - private UpdateSettingsOnCvsConfiguration createSettingsAndUpdateContext(final CvsConfiguration cvsConfiguration, - @NotNull final Ref contextRef) { + private static UpdateSettingsOnCvsConfiguration createSettingsAndUpdateContext(final CvsConfiguration cvsConfiguration, + @NotNull final Ref contextRef) { if (contextRef.get() != null) { final CvsSequentialUpdateContext cvsContext = (CvsSequentialUpdateContext) contextRef.get(); contextRef.set(null); @@ -130,7 +129,7 @@ public class CvsUpdateEnvironment implements UpdateEnvironment { try { final UpdateSettingsOnCvsConfiguration updateSettings = createSettingsAndUpdateContext(cvsConfiguration, contextRef); final UpdateHandler handler = CommandCvsHandler.createUpdateHandler(contentRoots, updateSettings, myProject, updatedFiles); - handler.addCvsListener(new UpdatedFilesProcessor(myProject, updatedFiles)); + handler.addCvsListener(new UpdatedFilesProcessor(updatedFiles)); CvsOperationExecutor cvsOperationExecutor = new CvsOperationExecutor(true, myProject, ModalityState.defaultModalityState()); cvsOperationExecutor.setShowErrors(false); cvsOperationExecutor.performActionSync(handler, CvsOperationExecutorCallback.EMPTY); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/updateinfo/UpdatedFilesProcessor.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/updateinfo/UpdatedFilesProcessor.java index 42030d647df3..e8885634aabd 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/updateinfo/UpdatedFilesProcessor.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/updateinfo/UpdatedFilesProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -23,7 +23,7 @@ import com.intellij.cvsSupport2.cvsoperations.cvsMessages.FileMessage; import com.intellij.cvsSupport2.history.CvsRevisionNumber; import com.intellij.cvsSupport2.util.CvsVfsUtil; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.vcs.update.FileGroup; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; @@ -35,19 +35,22 @@ import java.io.File; public class UpdatedFilesProcessor extends CvsMessagesAdapter { private static final Logger LOG = Logger.getInstance("#com.intellij.cvsSupport2.updateinfo.UpdatedFilesProcessor"); - private final Project myProject; private final UpdatedFiles myUpdatedFiles; - public UpdatedFilesProcessor(Project project, UpdatedFiles updatedFiles) { - myProject = project; + public UpdatedFilesProcessor(UpdatedFiles updatedFiles) { myUpdatedFiles = updatedFiles; } public void addFileMessage(FileMessage message) { String path = message.getFileAbsolutePath(); VirtualFile virtualFile = getVirtualFileFor(path); - FileGroup collection = getCollectionFor(message.getType(), virtualFile); - LOG.assertTrue(collection != null, String.valueOf(message.getType())); + final int messageType = message.getType(); + if (virtualFile != null && messageType == FileMessage.NOT_IN_REPOSITORY && + FileTypeManager.getInstance().isFileIgnored(virtualFile)) { + return; + } + FileGroup collection = getCollectionFor(messageType, virtualFile); + LOG.assertTrue(collection != null, String.valueOf(messageType)); final CvsRevisionNumber revision = message.getRevision(); collection.add(path, CvsVcs2.getKey(), revision); } From 05e257951ae8194e8ba7fa3d0da3f5e693166378 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 5 Aug 2011 15:07:34 +0400 Subject: [PATCH 03/77] NPE fix --- .../com/intellij/ide/favoritesTreeView/FavoritesManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java index 69acdb8697e0..1e62ea523fa0 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java @@ -108,8 +108,10 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { return result; } + @NotNull public Collection> getFavoritesListRootUrls(@NotNull String name) { - return myName2FavoritesRoots.get(name); + final LinkedHashSet> pairs = myName2FavoritesRoots.get(name); + return pairs == null ? Collections.>emptyList() : pairs; } public synchronized boolean addRoots(@NotNull String name, Module moduleContext, @NotNull Object elements) { From 1f45ec9902e66413385a0a8c3a3547a12a4d411d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 5 Aug 2011 15:57:05 +0400 Subject: [PATCH 04/77] assign Commander shortcut for Favorites --- platform/platform-resources/src/idea/Keymap_Default.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 0d531152aa72..868c9d9f1b87 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -733,6 +733,9 @@ + + + @@ -748,7 +751,7 @@ - + From 5c6e79c3b42a525b0cf05b0d18bb1d81bcfab68b Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 16:01:50 +0400 Subject: [PATCH 05/77] inspections view: do not insert same suppression twice (IDEA-72888) --- .../daemon/impl/actions/SuppressFix.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java index 4634b30c1734..e5bb3330bcb0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java @@ -160,19 +160,24 @@ public class SuppressFix extends SuppressIntentionAction { final String id) { if (annotation != null) { - if (annotation.getText().indexOf("{") == -1) { + final String currentSuppressedId = "\"" + id + "\""; + if (!annotation.getText().contains("{")) { final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); if (attributes.length == 1) { final String suppressedWarnings = attributes[0].getText(); - return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText("@" + - SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "({" + suppressedWarnings + ", \"" + id + "\"})", container); + if (suppressedWarnings.contains(currentSuppressedId)) return null; + return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText( + "@" + SuppressManager.SUPPRESS_INSPECTIONS_ANNOTATION_NAME + "({" + suppressedWarnings + ", " + currentSuppressedId + "})", container); + } } else { final int curlyBraceIndex = annotation.getText().lastIndexOf("}"); if (curlyBraceIndex > 0) { + final String oldSuppressWarning = annotation.getText().substring(0, curlyBraceIndex); + if (oldSuppressWarning.contains(currentSuppressedId)) return null; return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText( - annotation.getText().substring(0, curlyBraceIndex) + ", \"" + id + "\"})", container); + oldSuppressWarning + ", " + currentSuppressedId + "})", container); } else if (!ApplicationManager.getApplication().isUnitTestMode() && editor != null) { Messages.showErrorDialog(editor.getComponent(), From 119171901de69ada6ab293a56ec9862c68263109 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 5 Aug 2011 16:25:11 +0400 Subject: [PATCH 06/77] PsiDirectory now always is navigated to project view. --- .../psi/impl/file/PsiJavaDirectoryImpl.java | 7 ------ .../psi/impl/file/PsiDirectoryImpl.java | 25 +++++++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiJavaDirectoryImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiJavaDirectoryImpl.java index 07b65811a1fd..b4f2da0072b5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiJavaDirectoryImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiJavaDirectoryImpl.java @@ -15,8 +15,6 @@ */ package com.intellij.psi.impl.file; -import com.intellij.ide.impl.ProjectViewSelectInTarget; -import com.intellij.ide.projectView.impl.ProjectViewPane; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -25,7 +23,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -77,8 +74,4 @@ public class PsiJavaDirectoryImpl extends PsiDirectoryImpl { super.checkAdd(element); } } - - public void navigate(final boolean requestFocus) { - ProjectViewSelectInTarget.select(getProject(), this, ProjectViewPane.ID, null, getVirtualFile(), requestFocus); - } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java index 391ec3a8bd21..91c7b7438dd5 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/PsiDirectoryImpl.java @@ -16,6 +16,8 @@ package com.intellij.psi.impl.file; +import com.intellij.ide.impl.ProjectViewSelectInTarget; +import com.intellij.ide.projectView.impl.ProjectViewPane; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.diagnostic.Logger; @@ -208,13 +210,13 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu if (vFile.isDirectory()) { PsiDirectory dir = myManager.findDirectory(vFile); if (dir != null) { - if(!processor.execute(dir)) return false; + if (!processor.execute(dir)) return false; } } else { PsiFile file = myManager.findFile(vFile); if (file != null) { - if(!processor.execute(file)) return false; + if (!processor.execute(file)) return false; } } } @@ -312,7 +314,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu try { VirtualFile file = getVirtualFile().createChildDirectory(myManager, name); PsiDirectory directory = myManager.findDirectory(file); - if (directory == null) throw new IncorrectOperationException("Cannot find directory in '"+file.getPresentableUrl()+"'"); + if (directory == null) throw new IncorrectOperationException("Cannot find directory in '" + file.getPresentableUrl() + "'"); return directory; } catch (IOException e) { @@ -365,15 +367,14 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu } final PsiFile copyPsi = myManager.findFile(copyVFile); if (copyPsi == null) { - LOG.error("Could not find file '"+copyVFile+"' after copying '"+vFile+"'"); + LOG.error("Could not find file '" + copyVFile + "' after copying '" + vFile + "'"); } updateAddedFile(copyPsi); return copyPsi; } catch (IOException e) { - throw new IncorrectOperationException(e.toString(),e); + throw new IncorrectOperationException(e.toString(), e); } - } private static void updateAddedFile(PsiFile copyPsi) throws IncorrectOperationException { @@ -420,7 +421,8 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu if (document != null) { document.setText(text); fileDocumentManager.saveDocument(document); - } else { + } + else { String lineSeparator = fileDocumentManager.getLineSeparator(newVFile, getProject()); if (!lineSeparator.equals("\n")) { text = StringUtil.convertLineSeparators(text, lineSeparator); @@ -453,7 +455,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu return newFile; } catch (IOException e) { - throw new IncorrectOperationException(e.toString(),e); + throw new IncorrectOperationException(e.toString(), e); } } else { @@ -468,7 +470,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu String name = ((PsiDirectory)element).getName(); PsiDirectory[] subpackages = getSubdirectories(); for (PsiDirectory dir : subpackages) { - if (Comparing.strEqual(dir.getName(),name)) { + if (Comparing.strEqual(dir.getName(), name)) { throw new IncorrectOperationException(VfsBundle.message("dir.already.exists.error", dir.getVirtualFile().getPresentableUrl())); } } @@ -477,7 +479,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu String name = ((PsiFile)element).getName(); PsiFile[] files = getFiles(); for (PsiFile file : files) { - if (Comparing.strEqual(file.getName(),name, SystemInfo.isFileSystemCaseSensitive)) { + if (Comparing.strEqual(file.getName(), name, SystemInfo.isFileSystemCaseSensitive)) { throw new IncorrectOperationException(VfsBundle.message("file.already.exists.error", file.getVirtualFile().getPresentableUrl())); } } @@ -510,7 +512,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu myFile.delete(myManager); } catch (IOException e) { - throw new IncorrectOperationException(e.toString(),e); + throw new IncorrectOperationException(e.toString(), e); } /* @@ -552,6 +554,7 @@ public class PsiDirectoryImpl extends PsiElementBase implements PsiDirectory, Qu } public void navigate(boolean requestFocus) { + ProjectViewSelectInTarget.select(getProject(), this, ProjectViewPane.ID, null, getVirtualFile(), requestFocus); } public FileStatus getFileStatus() { From 41a81e661a4aa472577943343e94310cffbb97a7 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 5 Aug 2011 15:43:04 +0400 Subject: [PATCH 07/77] SimpleDataContext.getData() fix --- .../actionSystem/impl/SimpleDataContext.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/SimpleDataContext.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/SimpleDataContext.java index 3592e481b757..04d7fe38435b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/SimpleDataContext.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/SimpleDataContext.java @@ -18,18 +18,24 @@ package com.intellij.openapi.actionSystem.impl; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.util.containers.HashMap; +import java.awt.*; +import java.lang.ref.WeakReference; import java.util.Map; public class SimpleDataContext implements DataContext { private final Map myDataId2Data; private final DataContext myParent; + private WeakReference myContextComponent; + private SimpleDataContext(String dataId, Object data, DataContext parent) { myDataId2Data = new HashMap(1); myDataId2Data.put(dataId, data); myParent = parent; + myContextComponent = new WeakReference(IdeFocusManager.getGlobalInstance().getFocusOwner()); } private SimpleDataContext(Map dataid2data, DataContext parent) { @@ -38,8 +44,14 @@ public class SimpleDataContext implements DataContext { } public Object getData(String dataId) { - return myDataId2Data.containsKey(dataId) ? myDataId2Data.get(dataId) : + Object result = myDataId2Data.containsKey(dataId) ? myDataId2Data.get(dataId) : myParent == null ? null : myParent.getData(dataId); + + if (result == null && PlatformDataKeys.CONTEXT_COMPONENT.getName().equals(dataId)) { + result = myContextComponent.get(); + } + + return result; } public static DataContext getSimpleContext(String dataId, Object data, DataContext parent) { From 129785c814d5f83aec8de9003f0e7ba3ed661082 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 15:04:13 +0200 Subject: [PATCH 08/77] crash tolerance in GeneralHighlightingPass [r=peter,cdr] --- .../daemon/impl/GeneralHighlightingPass.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index fb5c4a564e53..a209d1552f2e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -23,6 +23,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil; import com.intellij.codeInsight.problems.ProblemImpl; +import com.intellij.codeInsight.problems.WolfTheProblemSolverImpl; import com.intellij.concurrency.JobUtil; import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.Language; @@ -49,6 +50,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; @@ -558,6 +560,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP final Runnable action = new Runnable() { public void run() { //noinspection unchecked + boolean failed = false; for (List elements : new List[]{elements1, elements2}) { int nextLimit = chunkSize; for (int i = 0; i < elements.size(); i++) { @@ -575,7 +578,24 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP holder.clear(); for (final HighlightVisitor visitor : visitors) { - visitor.visit(element, holder); + try { + visitor.visit(element, holder); + } + catch (ProcessCanceledException e) { + throw e; + } + catch (IndexNotReadyException e) { + throw e; + } + catch (WolfTheProblemSolverImpl.HaveGotErrorException e) { + throw e; + } + catch (Exception e) { + if (!failed) { + LOG.error(e); + } + failed = true; + } } if (i == nextLimit) { From fc5915945a57bd31a6ce0c96500eeff5c8799ab0 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 15:04:34 +0200 Subject: [PATCH 09/77] crash tolerance in GeneralHighlightingPass [r=peter,cdr] --- .../intellij/codeInsight/problems/WolfTheProblemSolverImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java index 081015492807..fd758a9341fc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java @@ -253,7 +253,7 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { } } - private static class HaveGotErrorException extends RuntimeException { + public static class HaveGotErrorException extends RuntimeException { private final HighlightInfo myHighlightInfo; private final boolean myHasErrorElement; From a0c57b62270fb30cb625d7ab9d4a2778b2cdd3d3 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 5 Aug 2011 15:09:45 +0200 Subject: [PATCH 10/77] remove unused class --- .../cvsStatus/StatusOperation.java | 82 ------------------- 1 file changed, 82 deletions(-) delete mode 100644 plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsStatus/StatusOperation.java diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsStatus/StatusOperation.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsStatus/StatusOperation.java deleted file mode 100644 index 309433bb2798..000000000000 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsStatus/StatusOperation.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.cvsSupport2.cvsoperations.cvsStatus; - -import com.intellij.cvsSupport2.connections.CvsRootProvider; -import com.intellij.cvsSupport2.cvsoperations.common.CvsExecutionEnvironment; -import com.intellij.cvsSupport2.cvsoperations.common.CvsOperationOnFiles; -import org.netbeans.lib.cvsclient.command.Command; -import org.netbeans.lib.cvsclient.command.status.StatusCommand; -import org.netbeans.lib.cvsclient.command.status.StatusInformation; -import org.netbeans.lib.cvsclient.file.FileStatus; - -import java.io.File; -import java.util.Collection; - -public class StatusOperation extends CvsOperationOnFiles { - private static final String ourNoneTag = "(none)"; - - private String myRepositoryRevision; - private FileStatus myStatus; - private String myStickyDate; - private String myStickyTag; - - public StatusOperation(Collection files) { - for (final File file : files) { - addFile(file); - } - } - - protected Command createCommand(final CvsRootProvider root, final CvsExecutionEnvironment cvsExecutionEnvironment) { - final StatusCommand command = new StatusCommand(); - addFilesToCommand(root, command); - return command; - } - - protected String getOperationName() { - return "status"; - } - - public void fileInfoGenerated(Object info) { - super.fileInfoGenerated(info); - - if (info instanceof StatusInformation) { - final StatusInformation statusInformation = (StatusInformation) info; - myRepositoryRevision = statusInformation.getRepositoryRevision(); - myStatus = statusInformation.getStatus(); - myStickyDate = statusInformation.getStickyDate(); - myStickyDate = ourNoneTag.equals(myStickyDate) ? null : myStickyDate; - myStickyTag = statusInformation.getStickyTag(); - myStickyTag = ourNoneTag.equals(myStickyTag) ? null : myStickyTag; - } - } - - public String getRepositoryRevision() { - return myRepositoryRevision; - } - - public FileStatus getStatus() { - return myStatus; - } - - public String getStickyDate() { - return myStickyDate; - } - - public String getStickyTag() { - return myStickyTag; - } -} From da0a6ab674d0c6eea5c130fe2f97bf65a7b981b1 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 5 Aug 2011 15:16:28 +0200 Subject: [PATCH 11/77] IDEA-12476 (Getting clean copy: confusing behavior when choosing No in confirmation idalog) --- .../CancelledConfigurationException.java | 23 +++++++++++++++++++ .../update/UpdateOrStatusOptionsDialog.java | 6 ++++- .../cvsUpdate/ui/UpdateOptionsPanel.java | 6 ++++- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/options/CancelledConfigurationException.java diff --git a/platform/platform-api/src/com/intellij/openapi/options/CancelledConfigurationException.java b/platform/platform-api/src/com/intellij/openapi/options/CancelledConfigurationException.java new file mode 100644 index 000000000000..4b07e71d2143 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/options/CancelledConfigurationException.java @@ -0,0 +1,23 @@ +/* + * 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.openapi.options; + +public class CancelledConfigurationException extends ConfigurationException { + + public CancelledConfigurationException() { + super(null); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateOrStatusOptionsDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateOrStatusOptionsDialog.java index d90327343144..d7b0512ca995 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateOrStatusOptionsDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/UpdateOrStatusOptionsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.update; import com.intellij.openapi.help.HelpManager; +import com.intellij.openapi.options.CancelledConfigurationException; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; @@ -87,6 +88,9 @@ public abstract class UpdateOrStatusOptionsDialog extends OptionsDialog { try { configurable.apply(); } + catch (CancelledConfigurationException e) { + return; + } catch (ConfigurationException e) { Messages.showErrorDialog(myProject, VcsBundle.message("messge.text.cannot.save.settings", e.getLocalizedMessage()), getRealTitle()); return; diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java index 7ab4bba86df6..019193b97d00 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java @@ -21,6 +21,8 @@ import com.intellij.cvsSupport2.cvsoperations.cvsTagOrBranch.TagsHelper; import com.intellij.cvsSupport2.cvsoperations.cvsTagOrBranch.TagsProviderOnVirtualFiles; import com.intellij.cvsSupport2.cvsoperations.dateOrRevision.ui.DateOrRevisionOrTagSettings; import com.intellij.cvsSupport2.ui.ChangeKeywordSubstitutionPanel; +import com.intellij.openapi.options.CancelledConfigurationException; +import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -125,7 +127,7 @@ public class UpdateOptionsPanel { } } - public void apply() { + public void apply() throws ConfigurationException { CvsConfiguration configuration = CvsConfiguration.getInstance(myProject); configuration.CLEAN_COPY = false; @@ -134,6 +136,8 @@ public class UpdateOptionsPanel { CvsBundle.message("confirmation.clean.copy"), CvsBundle.message("confirmation.title.clean.copy"), Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) { configuration.CLEAN_COPY = true; + } else { + throw new CancelledConfigurationException(); } } From d3156231ada46b95950e965887fd0b2575746108 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 5 Aug 2011 17:33:09 +0400 Subject: [PATCH 12/77] maximized window bounds bigger than screen --- .../platform-api/src/com/intellij/ui/ScreenUtil.java | 10 +++++++++- .../intellij/openapi/wm/impl/WindowManagerImpl.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java index 24012761c34e..57e51e661d20 100644 --- a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java +++ b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java @@ -26,7 +26,15 @@ import java.awt.*; public class ScreenUtil { private ScreenUtil() { } - + + public static boolean isVisible(Rectangle bounds) { + final Rectangle intersection = getScreenBounds().intersection(bounds); + final int sq1 = intersection.width * intersection.height; + final int sq2 = bounds.width * bounds.height; + if (sq1 == 0 || sq2 == 0) return false; + return (double)sq1 / (double)sq2 > 0.1; + } + public static Rectangle getScreenBounds() { Rectangle screenBounds = new Rectangle(); final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index e55e57197fd8..031f176a41d2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -218,7 +218,7 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat myProject2Frame.put(null, frame); if (myFrameBounds == null - || !ScreenUtil.getScreenBounds().contains(myFrameBounds)) { //avoid situations when IdeFrame is out of all screens + || !ScreenUtil.isVisible(myFrameBounds)) { //avoid situations when IdeFrame is out of all screens Rectangle rect = ScreenUtil.getScreenRectangle(0, 0); int yParts = rect.height / 6; int xParts = rect.width / 5; From 0f940ca72cc85b8bfed99aafb7e0f4911770cc49 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 5 Aug 2011 15:41:09 +0200 Subject: [PATCH 13/77] IDEA-72303 (idea specifies incorrect username for ssh CVS repository) --- .../connections/CvsConnectionUtil.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsConnectionUtil.java b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsConnectionUtil.java index b61c52a18710..905b86345750 100644 --- a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsConnectionUtil.java +++ b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/connections/CvsConnectionUtil.java @@ -22,6 +22,7 @@ import com.intellij.cvsSupport2.config.SshSettings; import com.intellij.cvsSupport2.connections.ext.ExtConnection; import com.intellij.cvsSupport2.connections.ssh.*; import com.intellij.cvsSupport2.errorHandling.ErrorRegistry; +import com.intellij.util.SystemProperties; import org.netbeans.lib.cvsclient.connection.ConnectionSettings; import org.netbeans.lib.cvsclient.connection.IConnection; import org.netbeans.lib.cvsclient.connection.PServerConnection; @@ -51,11 +52,11 @@ public class CvsConnectionUtil { final ConnectionPoolI pool = SshConnectionPool.getInstance(); final SshAuthentication authentication; if (sshConfiguration.USE_PPK) { - authentication = new SshPublicKeyAuthentication(new File(sshConfiguration.PATH_TO_PPK), settings.USER, sshPasswordProvider, + authentication = new SshPublicKeyAuthentication(new File(sshConfiguration.PATH_TO_PPK), getUserName(settings), sshPasswordProvider, settings.getCvsRootAsString()); } else { - authentication = new SshPasswordAuthentication(settings.USER, sshPasswordProvider, settings.getCvsRootAsString()); + authentication = new SshPasswordAuthentication(getUserName(settings), sshPasswordProvider, settings.getCvsRootAsString()); } return pool.getConnection(settings.REPOSITORY, connectionSettings, authentication); } @@ -73,7 +74,7 @@ public class CvsConnectionUtil { timeout); } else { - return new ExtConnection(settings.HOST, settings.USER, settings.REPOSITORY, extConfiguration, errorRegistry); + return new ExtConnection(settings.HOST, getUserName(settings), settings.REPOSITORY, extConfiguration, errorRegistry); } } @@ -91,7 +92,17 @@ public class CvsConnectionUtil { return new PServerConnection(connectionSettings, root.USER, root.PASSWORD, adjustRepository(root)); } - public static String adjustRepository(CvsRootData root) { + private static String getUserName(CvsRootData settings) { + final String login; + if (settings.USER.isEmpty()) { + login = SystemProperties.getUserName(); + } else { + login = settings.USER; + } + return login; + } + + private static String adjustRepository(CvsRootData root) { if (root.REPOSITORY != null) { return root.REPOSITORY.replace('\\', '/'); } else { From 18d5745c3896fecf4fd1cbb4ef4068ab3293804f Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Fri, 5 Aug 2011 18:00:05 +0400 Subject: [PATCH 14/77] [mac] Messages as sheet panels --- .../intellij/openapi/ui/DialogWrapper.java | 5 +- .../src/com/intellij/openapi/ui/Messages.java | 182 ++++++++-- .../com/intellij/util/ui/OptionsDialog.java | 4 +- .../com/intellij/ide/impl/ProjectUtil.java | 16 +- .../plugins/PluginManagerConfigurable.java | 4 +- .../application/impl/ApplicationImpl.java | 15 +- .../application/impl/ConfirmExitDialog.java | 75 ----- .../ui/mac/MacFileChooserDialogImpl.java | 3 +- .../ui/mac/MacMainFrameDecorator.java | 43 +-- .../src/messages/IdeBundle.properties | 2 +- .../openapi/util/text/StringUtil.java | 8 + .../intellij/ui/mac/DoNotAskDialogOption.java | 31 ++ .../src/com/intellij/ui/mac/MacMessages.java | 318 ++++++++++++++++++ .../ui/mac/foundation/Foundation.java | 4 + .../intellij/ui/mac/foundation/MacUtil.java | 67 ++++ 15 files changed, 619 insertions(+), 158 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/openapi/application/impl/ConfirmExitDialog.java create mode 100644 platform/util/src/com/intellij/ui/mac/DoNotAskDialogOption.java create mode 100644 platform/util/src/com/intellij/ui/mac/MacMessages.java create mode 100644 platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 46ace4a57518..cd2e7f732181 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -30,6 +30,7 @@ import com.intellij.openapi.wm.IdeGlassPaneUtil; import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.UIBundle; +import com.intellij.ui.mac.DoNotAskDialogOption; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.AwtVisitor; @@ -1147,7 +1148,7 @@ public abstract class DialogWrapper { } public boolean isOK() { - return myExitCode == OK_EXIT_CODE; + return getExitCode() == OK_EXIT_CODE; } public boolean isOKActionEnabled() { @@ -1556,7 +1557,7 @@ public abstract class DialogWrapper { return myDisposable; } - public interface DoNotAskOption { + public interface DoNotAskOption extends DoNotAskDialogOption { boolean isToBeShown(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 0f5859f14ccb..fae5466b4425 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -20,13 +20,16 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.WindowManager; import com.intellij.ui.BrowserHyperlinkListener; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.InsertPathAction; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.mac.MacMessages; import com.intellij.util.PairFunction; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nls; @@ -173,10 +176,20 @@ public class Messages { * @see com.intellij.openapi.ui.DialogWrapper#DialogWrapper(Project,boolean) */ public static void showMessageDialog(Project project, String message, String title, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + return; + } + showDialog(project, message, title, new String[]{OK_BUTTON}, 0, icon); } public static void showMessageDialog(Component parent, String message, String title, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(parent)); + return; + } + showDialog(parent, message, title, new String[]{OK_BUTTON}, 0, icon); } @@ -187,23 +200,63 @@ public class Messages { * @see #showMessageDialog(Component, String, String, Icon) */ public static void showMessageDialog(String message, String title, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON); + return; + } + showDialog(message, title, new String[]{OK_BUTTON}, 0, icon); } + /** + * @return 0 if user pressed "Yes" and returns 1 if user pressed "No" button. + */ + public static int showYesNoDialog(Project project, String message, String title, String yesText, String noText, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(message, title, yesText, noText, WindowManager.getInstance().suggestParentWindow(project)); + } + + return showDialog(project, message, title, new String[]{yesText, noText}, 0, icon); + } + /** * @return 0 if user pressed "Yes" and returns 1 if user pressed "No" button. */ public static int showYesNoDialog(Project project, String message, String title, @Nullable Icon icon) { - return showDialog(project, message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon); + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + } + + return showYesNoDialog(project, message, title, YES_BUTTON, NO_BUTTON, icon); } /** * @return 0 if user pressed "Yes" and returns 1 if user pressed "No" button. */ public static int showYesNoDialog(Component parent, String message, String title, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent)); + } + return showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon); } + + /** + * Use this method only if you do not know project or component + * + * @return 0 if user pressed "Yes" and returns 1 if user pressed "No" button. + * @see #showYesNoDialog(Project, String, String, Icon) + * @see #showYesNoDialog(Component, String, String, Icon) + */ + public static int showYesNoDialog(String message, String title, String yesText, String noText, @Nullable Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(title, message, yesText, noText, null); + } + + return showDialog(message, title, new String[]{yesText, noText}, 0, icon); + } + /** * Use this method only if you do not know project or component * @@ -212,26 +265,27 @@ public class Messages { * @see #showYesNoDialog(Component, String, String, Icon) */ public static int showYesNoDialog(String message, String title, @Nullable Icon icon) { - return showDialog(message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon); - } + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, null); + } - public static int showYesNoDialog(Component parent, String message, String title, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { - return showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon); - } - - public static int showYesNoDialog(Project project, String message, String title, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { - return showDialog(project, message, title, new String[]{YES_BUTTON, NO_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon); + return showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, icon); } public static int showOkCancelDialog(Project project, String message, String title, Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(title, message, OK_BUTTON, CANCEL_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + } + return showDialog(project, message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon); } - public static int showOkCancelDialog(Component parent, String message, String title, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { - return showDialog(parent, message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon); - } - public static int showOkCancelDialog(Component parent, String message, String title, Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(title, message, OK_BUTTON, CANCEL_BUTTON, SwingUtilities.getWindowAncestor(parent)); + } + + return showDialog(parent, message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon); } @@ -242,12 +296,17 @@ public class Messages { * @see #showOkCancelDialog(Component, String, String, Icon) */ public static int showOkCancelDialog(String message, String title, Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoDialog(title, message, OK_BUTTON, CANCEL_BUTTON, null); + } + return showDialog(message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon); } public static int showCheckboxOkCancelDialog(String message, String title, String checkboxText, final boolean checked, final int defaultOptionIndex, final int focusedOptionIndex, Icon icon) { - return showCheckboxMessageDialog(message, title, new String[] {OK_BUTTON, CANCEL_BUTTON}, checkboxText, checked, defaultOptionIndex, focusedOptionIndex, icon, + return showCheckboxMessageDialog(message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, checkboxText, checked, defaultOptionIndex, + focusedOptionIndex, icon, new PairFunction() { @Override public Integer fun(final Integer exitCode, final JCheckBox cb) { @@ -272,18 +331,33 @@ public class Messages { public static int showTwoStepConfirmationDialog(String message, String title, String checkboxText, Icon icon) { - return showCheckboxMessageDialog(message, title, new String[] {OK_BUTTON, CANCEL_BUTTON}, checkboxText, true, -1, -1, icon, null); + return showCheckboxMessageDialog(message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, checkboxText, true, -1, -1, icon, null); } public static void showErrorDialog(Project project, @Nls String message, @Nls String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + return; + } + showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon()); } public static void showErrorDialog(Component component, String message, @Nls String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component)); + return; + } + showDialog(component, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon()); } public static void showErrorDialog(Component component, String message) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, SwingUtilities.getWindowAncestor(component)); + return; + } + showDialog(component, message, CommonBundle.getErrorTitle(), new String[]{OK_BUTTON}, 0, getErrorIcon()); } @@ -294,14 +368,29 @@ public class Messages { * @see #showErrorDialog(Component, String, String) */ public static void showErrorDialog(String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, null); + return; + } + showDialog(message, title, new String[]{OK_BUTTON}, 0, getErrorIcon()); } public static void showWarningDialog(Project project, String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + return; + } + showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getWarningIcon()); } public static void showWarningDialog(Component component, String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, SwingUtilities.getWindowAncestor(component)); + return; + } + showDialog(component, message, title, new String[]{OK_BUTTON}, 0, getWarningIcon()); } @@ -312,22 +401,55 @@ public class Messages { * @see #showWarningDialog(Component, String, String) */ public static void showWarningDialog(String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, null); + return; + } + showDialog(message, title, new String[]{OK_BUTTON}, 0, getWarningIcon()); } - public static int showYesNoCancelDialog(Project project, String message, String title, Icon icon) { - return showDialog(project, message, title, new String[]{YES_BUTTON, NO_BUTTON, CANCEL_BUTTON}, 0, icon); + public static int showYesNoCancelDialog(Project project, String message, String title, String yes, String no, String cancel, Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoCancelDialog(title, message, yes, no, cancel, + WindowManager.getInstance().suggestParentWindow(project), null); + } + + return showDialog(project, message, title, new String[]{yes, no, cancel}, 0, icon); } - public static int showYesNoCancelDialog(Project project, String message, String title, final int defaultOptionIndex, - final int focusedOptionIndex, Icon icon) { - return showDialog(project, message, title, new String[]{YES_BUTTON, NO_BUTTON, CANCEL_BUTTON}, defaultOptionIndex, focusedOptionIndex, icon); + + public static int showYesNoCancelDialog(Project project, String message, String title, Icon icon) { + return showYesNoCancelDialog(project, message, title, YES_BUTTON, NO_BUTTON, CANCEL_BUTTON, icon); + } + + public static int showYesNoCancelDialog(Component parent, String message, String title, String yes, String no, String cancel, Icon icon) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoCancelDialog(title, message, yes, no, cancel, + SwingUtilities.getWindowAncestor(parent), null); + } + + return showDialog(parent, message, title, new String[]{yes, no, cancel}, 0, icon); } public static int showYesNoCancelDialog(Component parent, String message, String title, Icon icon) { - return showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON, CANCEL_BUTTON}, 0, icon); + return showYesNoCancelDialog(parent, message, title, YES_BUTTON, NO_BUTTON, CANCEL_BUTTON, icon); } + + public static int showYesNoCancelDialog(String message, String title, String yes, String no, String cancel, Icon icon, + DialogWrapper.DoNotAskOption doNotAskOption) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + return MacMessages.showYesNoCancelDialog(title, message, yes, no, cancel, null, doNotAskOption); + } + + return showDialog(message, title, new String[]{yes, no, cancel}, 0, icon, doNotAskOption); + } + + public static int showYesNoCancelDialog(String message, String title, String yes, String no, String cancel, Icon icon) { + return showYesNoCancelDialog(message, title, yes, no, cancel, icon, null); + } + /** * Use this method only if you do not know project or component * @@ -335,7 +457,7 @@ public class Messages { * @see #showYesNoCancelDialog(Component, String, String, Icon) */ public static int showYesNoCancelDialog(String message, String title, Icon icon) { - return showDialog(message, title, new String[]{YES_BUTTON, NO_BUTTON, CANCEL_BUTTON}, 0, icon); + return showYesNoCancelDialog(message, title, YES_BUTTON, NO_BUTTON, CANCEL_BUTTON, icon); } /** @@ -520,6 +642,11 @@ public class Messages { * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button */ public static void showInfoMessage(Component component, String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component)); + return; + } + showMessageDialog(component, message, title, getInformationIcon()); } @@ -527,6 +654,11 @@ public class Messages { * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button */ public static void showInfoMessage(Project project, @Nls String message, @Nls String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + return; + } + showMessageDialog(project, message, title, getInformationIcon()); } @@ -534,6 +666,12 @@ public class Messages { * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button */ public static void showInfoMessage(String message, String title) { + if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { + MacMessages.showOkMessageDialog(title, message, OK_BUTTON, null); + return; + } + + showMessageDialog(message, title, getInformationIcon()); } diff --git a/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java b/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java index 8043cc9874da..00d79f3d1f24 100644 --- a/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java +++ b/platform/platform-api/src/com/intellij/util/ui/OptionsDialog.java @@ -24,8 +24,10 @@ import java.awt.*; /** * author: lesya + * + * @deprecated use one of {@link com.intellij.openapi.ui.Messages} methods instead. */ - +@Deprecated public abstract class OptionsDialog extends DialogWrapper { protected final Project myProject; diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index 62c5cf0a798b..f5613fde8de9 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -128,14 +128,12 @@ public class ProjectUtil { public static Project openProject(final String path, Project projectToClose, boolean forceOpenInNewFrame) { File file = new File(path); if (!file.exists()) { - Messages.showMessageDialog(IdeBundle.message("error.project.file.does.not.exist", path), CommonBundle.getErrorTitle(), - Messages.getErrorIcon()); + Messages.showErrorDialog(IdeBundle.message("error.project.file.does.not.exist", path), CommonBundle.getErrorTitle()); return null; } if (file.isDirectory() && !new File(file, com.intellij.openapi.project.ProjectUtil.DIRECTORY_BASED_PROJECT_DIR).exists()) { - Messages.showMessageDialog(IdeBundle.message("error.project.file.does.not.exist", new File(file, com.intellij.openapi.project.ProjectUtil.DIRECTORY_BASED_PROJECT_DIR).getPath()), CommonBundle.getErrorTitle(), - Messages.getErrorIcon()); + Messages.showErrorDialog(IdeBundle.message("error.project.file.does.not.exist", new File(file, com.intellij.openapi.project.ProjectUtil.DIRECTORY_BASED_PROJECT_DIR).getPath()), CommonBundle.getErrorTitle()); return null; } @@ -182,10 +180,12 @@ public class ProjectUtil { public static int confirmOpenNewProject() { final GeneralSettings settings = GeneralSettings.getInstance(); if (settings.getConfirmOpenNewProject() == GeneralSettings.OPEN_PROJECT_ASK) { - return Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), - new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), - CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon(), - new ProjectNewWindowDoNotAskOption()); + return Messages.showYesNoCancelDialog(IdeBundle.message("prompt.open.project.in.new.frame"), + IdeBundle.message("title.open.project"), + IdeBundle.message("button.newframe"), + IdeBundle.message("button.existingframe"), + CommonBundle.getCancelButtonText(), Messages.getQuestionIcon(), + new ProjectNewWindowDoNotAskOption()); } else { return settings.getConfirmOpenNewProject(); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java index ab0994454db0..82404ca67143 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java @@ -174,13 +174,13 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc private static int showShutDownIDEADialog() { String message = IdeBundle.message("message.idea.shutdown.required", ApplicationNamesInfo.getInstance().getProductName()); String title = IdeBundle.message("title.plugins.changed"); - return Messages.showDialog(message, title, new String[]{"Shut Down", POSTPONE},0,0,Messages.getQuestionIcon()); + return Messages.showYesNoDialog(message, title, "Shut Down", POSTPONE,Messages.getQuestionIcon()); } public static int showRestartIDEADialog() { String message = IdeBundle.message("message.idea.restart.required", ApplicationNamesInfo.getInstance().getProductName()); String title = IdeBundle.message("title.plugins.changed"); - return Messages.showDialog(message, title, new String[]{"Restart", POSTPONE},0,0,Messages.getQuestionIcon()); + return Messages.showYesNoDialog(message, title, "Restart", POSTPONE, Messages.getQuestionIcon()); } public boolean isModified() { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index dcf34687503e..979f14617bbb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -773,16 +773,17 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application private static boolean showConfirmation() { final boolean hasUnsafeBgTasks = ProgressManager.getInstance().hasUnsafeProgressIndicator(); - final ConfirmExitDialog confirmExitDialog = new ConfirmExitDialog(hasUnsafeBgTasks); - if (confirmExitDialog.isToBeShown()) { - confirmExitDialog.show(); - if (!confirmExitDialog.isOK()) { + if (hasUnsafeBgTasks || GeneralSettings.getInstance().isConfirmExit()) { + String message = ApplicationBundle + .message(hasUnsafeBgTasks ? "exit.confirm.prompt.tasks" : "exit.confirm.prompt", + ApplicationNamesInfo.getInstance().getFullProductName()); + + if (DialogWrapper.OK_EXIT_CODE != Messages.showYesNoDialog(message, ApplicationBundle.message("exit.confirm.title"), + ApplicationBundle.message("command.exit"), "Cancel", + Messages.getQuestionIcon())) { return false; } } - else { - confirmExitDialog.close(DialogWrapper.OK_EXIT_CODE); - } return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ConfirmExitDialog.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ConfirmExitDialog.java deleted file mode 100644 index cff46c5dea8e..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ConfirmExitDialog.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.application.impl; - -import com.intellij.ide.GeneralSettings; -import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.ui.Messages; -import com.intellij.util.ui.OptionsDialog; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Eugene Zhuravlev - * Date: Jun 2, 2005 - */ -public class ConfirmExitDialog extends OptionsDialog { - - private final boolean myHasTasks; - - public ConfirmExitDialog(boolean hasBgTasks) { - super(false); - setTitle(ApplicationBundle.message("exit.confirm.title")); - myHasTasks = hasBgTasks; - init(); - } - - protected Action[] createActions() { - setOKButtonText(ApplicationBundle.message("command.exit")); - return new Action[] {getOKAction(), getCancelAction()}; - } - - protected boolean isToBeShown() { - return GeneralSettings.getInstance().isConfirmExit() || myHasTasks; - } - - protected void setToBeShown(boolean value, boolean onOk) { - GeneralSettings.getInstance().setConfirmExit(value); - } - - protected boolean shouldSaveOptionsOnCancel() { - return !myHasTasks; - } - - protected boolean canBeHidden() { - return !myHasTasks; - } - - protected JComponent createCenterPanel() { - final JPanel panel = new JPanel(new BorderLayout()); - - final String message = ApplicationBundle.message(myHasTasks ? "exit.confirm.prompt.tasks": "exit.confirm.prompt", ApplicationNamesInfo.getInstance().getFullProductName()); - - final JLabel label = new JLabel(message); - label.setIconTextGap(10); - label.setIcon(Messages.getQuestionIcon()); - panel.add(label, BorderLayout.CENTER); - panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH); - return panel; - } -} diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java index 7cd2a4feeb34..526bc463fb72 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; +import com.intellij.ui.mac.foundation.MacUtil; import com.sun.jna.Callback; import com.sun.jna.Pointer; import org.jetbrains.annotations.NotNull; @@ -139,7 +140,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { activeWindowTitle = ((JDialog)activeWindow).getTitle(); } - final ID focusedWindow = MacMainFrameDecorator.findWindowForTitle(activeWindowTitle); + final ID focusedWindow = MacUtil.findWindowForTitle(activeWindowTitle); if (focusedWindow != null) { invoke(chooser, "beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo:", directory, file, null, focusedWindow, self, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), null); diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index f6843b23bdc7..8a860c73fb9c 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -23,17 +23,16 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; +import com.intellij.ui.mac.foundation.MacUtil; import com.intellij.util.Function; import com.sun.jna.Callback; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.concurrent.atomic.AtomicInteger; import static com.intellij.ui.mac.foundation.Foundation.invoke; -import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8; /** * User: spLeaner @@ -95,7 +94,7 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { private Callback myDidEnter; public MacMainFrameDecorator(@NotNull final Frame frame, final boolean navBar) { - final ID window = findWindowForTitle(frame.getTitle()); + final ID window = MacUtil.findWindowForTitle(frame.getTitle()); if (window == null) return; if (CURRENT_SETTER == null) { @@ -212,7 +211,7 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { public static void toggleFullScreen(Frame frame) { if (!SystemInfo.isMacOSLion) return; - final ID window = findWindowForTitle(frame.getTitle()); + final ID window = MacUtil.findWindowForTitle(frame.getTitle()); if (window == null) return; invoke(window, "toggleFullScreen:", window); @@ -221,45 +220,11 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { public static boolean isFullScreenMode(@NotNull Frame frame) { if (!SystemInfo.isMacOSLion) return false; - final ID window = findWindowForTitle(frame.getTitle()); + final ID window = MacUtil.findWindowForTitle(frame.getTitle()); if (window == null) return false; final ID mask = invoke(window, "styleMask"); return (mask.intValue() & (1 << 14)) == (1 << 14); } - @Nullable - public static ID findWindowForTitle(final String title) { - if (title == null || title.length() == 0) return null; - final ID pool = invoke("NSAutoreleasePool", "new"); - - ID focusedWindow = null; - try { - final ID sharedApplication = invoke("NSApplication", "sharedApplication"); - final ID windows = invoke(sharedApplication, "windows"); - final ID windowEnumerator = invoke(windows, "objectEnumerator"); - - while (true) { - // dirty hack: walks through all the windows to find a cocoa window to show sheet for - final ID window = invoke(windowEnumerator, "nextObject"); - if (0 == window.intValue()) break; - - final ID windowTitle = invoke(window, "title"); - if (windowTitle != null && windowTitle.intValue() != 0) { - final String titleString = toStringViaUTF8(windowTitle); - if (titleString.equals(title)) { - if (1 == invoke(window, "isVisible").intValue()) { - focusedWindow = window; - break; - } - } - } - } - } - finally { - invoke(pool, "release"); - } - - return focusedWindow; - } } diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 4485aa23edc8..5f8e78577085 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -218,7 +218,7 @@ select.in.project=Project select.in.nav.bar = Navigation Bar error.adding.module.to.project=Error adding module to project: {0} title.add.module=Add Module -prompt.open.project.in.new.frame=New projects can either be opened in a new window or replace the project in the existing window.
How would you like to open the project?? +prompt.open.project.in.new.frame=New projects can either be opened in a new window or replace the project in the existing window.
How would you like to open the project? title.new.project=New Project button.newframe=New &Window button.existingframe=&This Window 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 4f416f60cc4b..2d3b89ff5e57 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -221,6 +221,14 @@ public class StringUtil { return Character.toLowerCase(a); } + public static String stripHtml(String html, boolean convertBreaks) { + if (convertBreaks) { + html = html.replaceAll("
", "\n"); + } + + return html.replaceAll("<(.|\n)*?>", ""); + } + @Nullable public static String toLowerCase(@Nullable final String str) { return str == null ? null : str.toLowerCase(); diff --git a/platform/util/src/com/intellij/ui/mac/DoNotAskDialogOption.java b/platform/util/src/com/intellij/ui/mac/DoNotAskDialogOption.java new file mode 100644 index 000000000000..741883c9ba1c --- /dev/null +++ b/platform/util/src/com/intellij/ui/mac/DoNotAskDialogOption.java @@ -0,0 +1,31 @@ +/* + * 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.ui.mac; + +/** + * @author pegov + */ +public interface DoNotAskDialogOption { + boolean isToBeShown(); + + void setToBeShown(boolean value, int exitCode); + + boolean canBeHidden(); + + boolean shouldSaveOptionsOnCancel(); + + String getDoNotShowMessage(); +} diff --git a/platform/util/src/com/intellij/ui/mac/MacMessages.java b/platform/util/src/com/intellij/ui/mac/MacMessages.java new file mode 100644 index 000000000000..0fc3fb9a99b1 --- /dev/null +++ b/platform/util/src/com/intellij/ui/mac/MacMessages.java @@ -0,0 +1,318 @@ +/* + * 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.ui.mac; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.mac.foundation.Foundation; +import com.intellij.ui.mac.foundation.ID; +import com.intellij.ui.mac.foundation.MacUtil; +import com.intellij.util.ui.UIUtil; +import com.sun.jna.Callback; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; + +import static com.intellij.ui.mac.foundation.Foundation.*; + +/** + * @author pegov + */ +public class MacMessages { + private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.MacMessages"); + + private static final Callback SHEET_DID_END = new Callback() { + public void callback(ID self, String selector, ID alert, ID returnCode, ID contextInfo) { + String fakeDialogTitle = toStringViaUTF8(contextInfo); + Window[] windows = Window.getWindows(); + + ID suppressState = invoke(invoke(alert, "suppressionButton"), "state"); + + for (Window window : windows) { + if (window instanceof JFrame) { + JFrame frame = (JFrame)window; + JRootPane rootPane = frame.getRootPane(); + if (rootPane.getClientProperty(MAC_SHEET_ACTIVE) == Boolean.TRUE && + fakeDialogTitle.equals(rootPane.getClientProperty(MAC_SHEET_ID))) { + processResult(rootPane, returnCode.intValue(), suppressState.intValue()); + break; + } + } + else if (window instanceof JDialog) { + JDialog dialog = (JDialog)window; + JRootPane rootPane = dialog.getRootPane(); + if (rootPane.getClientProperty(MAC_SHEET_ACTIVE) == Boolean.TRUE && + fakeDialogTitle.equals(rootPane.getClientProperty(MAC_SHEET_ID))) { + processResult(rootPane, returnCode.intValue(), suppressState.intValue()); + } + } + } + + cfRelease(self); + } + }; + + private static final Callback MAIN_THREAD_RUNNABLE = new Callback() { + public void callback(ID self, String selector, ID params) { + ID title = invoke(params, "objectAtIndex:", 0); + ID defaultText = invoke(params, "objectAtIndex:", 1); + ID otherText = invoke(params, "objectAtIndex:", 2); + ID alternateText = invoke(params, "objectAtIndex:", 3); + ID message = invoke(params, "objectAtIndex:", 4); + ID focusedWindow = invoke(params, "objectAtIndex:", 5); + ID fakeId = invoke(params, "objectAtIndex:", 6); + ID alertStyle = invoke(params, "objectAtIndex:", 7); + ID doNotAskText = invoke(params, "objectAtIndex:", 8); + + boolean alternateExist = !"-1".equals(toStringViaUTF8(alternateText)); + boolean otherExist = !"-1".equals(toStringViaUTF8(otherText)); + + final ID alert = invoke("NSAlert", "alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat:", + title, defaultText, alternateExist ? alternateText : null, otherExist ? otherText : null, message); + + if ("error".equals(toStringViaUTF8(alertStyle))) { + invoke(alert, "setAlertStyle:", 2); // NSCriticalAlertStyle = 2 + } + + String doNotAsk = toStringViaUTF8(doNotAskText); + if (!"-1".equals(doNotAsk)) { + invoke(alert, "setShowsSuppressionButton:", 1); + invoke(invoke(alert, "suppressionButton"), "setTitle:", doNotAskText); + } + + invoke(alert, "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:", focusedWindow, self, + createSelector("alertDidEnd:returnCode:contextInfo:"), fakeId); + } + }; + + private static void processResult(JRootPane rootPane, int returnCode, int suppressDialog) { + rootPane.putClientProperty(MAC_SHEET_RESULT, returnCode); + rootPane.putClientProperty(MAC_SHEET_SUPPRESS, suppressDialog == 1 ? Boolean.TRUE : Boolean.FALSE); + rootPane.putClientProperty(MAC_SHEET_ID, null); + rootPane.putClientProperty(MAC_SHEET_ACTIVE, null); + } + + private static final String MAC_SHEET_ACTIVE = "mac_sheet_active"; + private static final String MAC_SHEET_RESULT = "mac_sheet_result"; + private static final String MAC_SHEET_SUPPRESS = "mac_sheet_suppress"; + private static final String MAC_SHEET_ID = "mac_sheet_id"; + + private MacMessages() { + } + + static { + final ID delegateClass = Foundation.registerObjcClass(Foundation.getClass("NSObject"), "NSAlertDelegate_"); + if (!Foundation.addMethod(delegateClass, Foundation.createSelector("alertDidEnd:returnCode:contextInfo:"), SHEET_DID_END, "v*")) { + throw new RuntimeException("Unable to add method to objective-c delegate class!"); + } + if (!Foundation.addMethod(delegateClass, Foundation.createSelector("showSheet:"), MAIN_THREAD_RUNNABLE, "v*")) { + throw new RuntimeException("Unable to add method to objective-c delegate class!"); + } + + Foundation.registerObjcClassPair(delegateClass); + } + + public static void showOkMessageDialog(String title, String message, String okText, @Nullable Window window) { + showMessageDialog(title, okText, null, null, message, window); + } + + public static void showOkMessageDialog(String title, String message, String okText) { + showMessageDialog(title, okText, null, null, message, null); + } + + public static int showYesNoDialog(String title, String message, String yesButton, String noButton, @Nullable Window window) { + return showMessageDialog(title, yesButton, null, noButton, message, window); + } + + public static void showErrorDialog(String title, String message, String okButton, @Nullable Window window) { + showAlertDialog(title, okButton, null, null, message, window, true, null); + } + + public static int showYesNoCancelDialog(String title, + String message, + String defaultButton, + String alternateButton, + String otherButton, + Window window, + @Nullable DoNotAskDialogOption doNotAskOption) { + return showAlertDialog(title, defaultButton, alternateButton, otherButton, message, window, false, doNotAskOption); + } + + public static int showAlertDialog(String title, + String defaultText, + @Nullable String alternateText, + @Nullable String otherText, + String message, + @Nullable Window window, + boolean errorStyle, + @Nullable DoNotAskDialogOption doNotAskDialogOption) { + LOG.assertTrue(SwingUtilities.isEventDispatchThread()); + + JRootPane pane = null; + String _windowTitle = null; + + final Window _window = window == null ? KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() : window; + if (_window instanceof JFrame) { + JFrame frame = (JFrame)_window; + pane = frame.getRootPane(); + _windowTitle = frame.getTitle(); + } + else if (_window instanceof JDialog) { + JDialog dialog = (JDialog)_window; + pane = dialog.getRootPane(); + _windowTitle = dialog.getTitle(); + } + + LOG.assertTrue(_windowTitle != null && _windowTitle.length() > 0 && pane != null, "Window should have a title and a root pane!"); + + final ID focusedWindow = MacUtil.findWindowForTitle(_windowTitle); + if (focusedWindow != null) { + String fakeTitle = null; + + ID pool = invoke("NSAutoreleasePool", "new"); + try { + final ID delegate = invoke(Foundation.getClass("NSAlertDelegate_"), "new"); + cfRetain(delegate); + + fakeTitle = String.format("MacSheetDialog-%d", delegate.intValue()); + + ID paramsArray = invoke("NSArray", "arrayWithObjects:", cfString(title), cfString(UIUtil.removeMnemonic(defaultText)), + cfString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)), + cfString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)), cfString(StringUtil.stripHtml(message, true)), + focusedWindow, cfString(fakeTitle), cfString(errorStyle ? "error" : "-1"), + cfString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() + // TODO: state=!doNotAsk.shouldBeShown() + ? "-1" + : doNotAskDialogOption.getDoNotShowMessage()), null); + + invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", + Foundation.createSelector("showSheet:"), paramsArray, true); + } + finally { + invoke(pool, "release"); + } + + if (fakeTitle != null) { + pane.putClientProperty(MAC_SHEET_ACTIVE, Boolean.TRUE); + pane.putClientProperty(MAC_SHEET_ID, fakeTitle); + + startModal(pane); + Integer result = (Integer)pane.getClientProperty(MAC_SHEET_RESULT); + boolean suppress = Boolean.TRUE == pane.getClientProperty(MAC_SHEET_SUPPRESS); + + // DEFAULT = 1 + // ALTERNATE = 0 + // OTHER = -1 (cancel) + + int cancelCode = 1; + int code; + if (alternateText != null) { + // DEFAULT = 0 + // ALTERNATE = 1 + // CANCEL = 2 + + cancelCode = 2; + + switch (result) { + case 1: + code = 0; + break; + case 0: + code = 1; + break; + case -1: // cancel + default: + code = 2; + break; + } + } else { + // DEFAULT = 0 + // CANCEL = 1 + + cancelCode = 1; + + switch (result) { + case 1: + code = 0; + break; + case -1: // cancel + default: + code = 1; + break; + } + } + + if (doNotAskDialogOption != null) { + if (cancelCode != code || doNotAskDialogOption.shouldSaveOptionsOnCancel()) { + if (doNotAskDialogOption.canBeHidden()) { + doNotAskDialogOption.setToBeShown(!suppress, code); + } + } + } + + pane.putClientProperty(MAC_SHEET_RESULT, null); + pane.putClientProperty(MAC_SHEET_SUPPRESS, null); + + return code; + } + } + + return -1; + } + + public static int showMessageDialog(String title, + String okText, + @Nullable String alternateText, + @Nullable String cancelText, + String message, + @Nullable Window window) { + return showAlertDialog(title, okText, alternateText, cancelText, message, window, false, null); + } + + private static synchronized void startModal(JRootPane pane) { + try { + if (SwingUtilities.isEventDispatchThread()) { + EventQueue theQueue = pane.getToolkit().getSystemEventQueue(); + + while (pane.getClientProperty(MAC_SHEET_ACTIVE) == Boolean.TRUE) { + AWTEvent event = theQueue.getNextEvent(); + Object source = event.getSource(); + if (event instanceof ActiveEvent) { + ((ActiveEvent)event).dispatch(); + } + else if (source instanceof Component) { + ((Component)source).dispatchEvent(event); + } + else if (source instanceof MenuComponent) { + ((MenuComponent)source).dispatchEvent(event); + } + else { + System.err.println("Unable to dispatch: " + event); + } + } + } + else { + while (pane.getClientProperty(MAC_SHEET_ACTIVE) == Boolean.TRUE) { + // TODO: + //wait(); + } + } + } + catch (InterruptedException ignored) { + } + } +} \ No newline at end of file diff --git a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java index 118e8c10be2e..71f3be7c8683 100644 --- a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java +++ b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java @@ -142,6 +142,10 @@ public class Foundation { myFoundationLibrary.CFRetain(id); } + public static void cfRelease(ID id) { + myFoundationLibrary.CFRelease(id); + } + private static Map ourMainThreadRunnables = new HashMap(); private static long ourCurrentRunnableCount = 0; private static final Object RUNNABLE_LOCK = new Object(); diff --git a/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java new file mode 100644 index 000000000000..63f21d146f91 --- /dev/null +++ b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java @@ -0,0 +1,67 @@ +/* + * 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.ui.mac.foundation; + +import org.jetbrains.annotations.Nullable; + +import static com.intellij.ui.mac.foundation.Foundation.invoke; +import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8; + +/** + * @author pegov + */ +public class MacUtil { + + private MacUtil() { + } + + @Nullable + public static ID findWindowForTitle(final String title) { + if (title == null || title.length() == 0) return null; + final ID pool = invoke("NSAutoreleasePool", "new"); + + ID focusedWindow = null; + try { + final ID sharedApplication = invoke("NSApplication", "sharedApplication"); + final ID windows = invoke(sharedApplication, "windows"); + final ID windowEnumerator = invoke(windows, "objectEnumerator"); + + while (true) { + // dirty hack: walks through all the windows to find a cocoa window to show sheet for + final ID window = invoke(windowEnumerator, "nextObject"); + if (0 == window.intValue()) break; + + final ID windowTitle = invoke(window, "title"); + if (windowTitle != null && windowTitle.intValue() != 0) { + final String titleString = toStringViaUTF8(windowTitle); + if (titleString.equals(title)) { + if (1 == invoke(window, "isVisible").intValue()) { + focusedWindow = window; + break; + } + } + } + } + } + finally { + invoke(pool, "release"); + } + + return focusedWindow; + } + + +} From 2a5419270e9dbe7cac87d3aad27921719311ff99 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 5 Aug 2011 17:58:48 +0400 Subject: [PATCH 15/77] IDEA-66098 misprint --- plugins/git4idea/src/META-INF/plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index 1d133aa8fd81..a69c0cbd97d0 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -27,7 +27,7 @@ - + From 127f97d99db51b1ee7aac61e40e1963d3e547f58 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 5 Aug 2011 18:05:20 +0400 Subject: [PATCH 16/77] fixes for Favorites --- platform/platform-resources/src/idea/Keymap_Mac.xml | 2 +- platform/platform-resources/src/idea/Keymap_MacClassic.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources/src/idea/Keymap_Mac.xml b/platform/platform-resources/src/idea/Keymap_Mac.xml index 0e02d49c0d2f..d56f04eb4557 100644 --- a/platform/platform-resources/src/idea/Keymap_Mac.xml +++ b/platform/platform-resources/src/idea/Keymap_Mac.xml @@ -188,7 +188,7 @@ - + diff --git a/platform/platform-resources/src/idea/Keymap_MacClassic.xml b/platform/platform-resources/src/idea/Keymap_MacClassic.xml index f23673164633..9051f9a400a3 100644 --- a/platform/platform-resources/src/idea/Keymap_MacClassic.xml +++ b/platform/platform-resources/src/idea/Keymap_MacClassic.xml @@ -188,7 +188,7 @@ - + From 3cd2b371a490adf42e7f26c58282905937cc78da Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 4 Aug 2011 13:38:23 +0200 Subject: [PATCH 17/77] minor --- .../codeInsight/completion/CodeCompletionHandlerBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index de686c51ae40..e55f598a0e5d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -634,7 +634,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { public static final Key>> FILE_COPY_KEY = Key.create("CompletionFileCopy"); - protected PsiFile createFileCopy(PsiFile file) { + private static PsiFile createFileCopy(PsiFile file) { final VirtualFile virtualFile = file.getVirtualFile(); if (file.isPhysical() && virtualFile != null && virtualFile.getFileSystem() == LocalFileSystem.getInstance() // must not cache injected file copy, since it does not reflect changes in host document From 02c878f4b3d35c4e12f43232a9ab0aa15ff7367b Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 4 Aug 2011 16:14:19 +0200 Subject: [PATCH 18/77] yet more RecursionManager assertions --- .../openapi/util/RecursionManager.java | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index 8803ca8e59ac..f278bdb9ad60 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -59,6 +59,12 @@ public class RecursionManager { return 0; } }; + private static final ThreadLocal ourDepth = new ThreadLocal() { + @Override + protected Integer initialValue() { + return 0; + } + }; private static final ThreadLocal> ourProgress = new ThreadLocal>() { @Override protected LinkedHashMap initialValue() { @@ -91,6 +97,9 @@ public class RecursionManager { if (memoize) { SoftReference reference = ourIntermediateCache.get().get(realKey); if (reference != null) { + if (ourDepth.get() == 0) { + throw new AssertionError("Memoized values with empty stack"); + } Object o = reference.get(); if (o != null) { //noinspection unchecked @@ -103,7 +112,17 @@ public class RecursionManager { throw new AssertionError("Non-zero stamp with empty stack: " + ourStamp.get()); } + if (ourDepth.get() != progressMap.size()) { + throw new AssertionError("Inconsistent depth 1"); + } + progressMap.put(realKey, ourStamp.get()); + ourDepth.set(ourDepth.get() + 1); + + if (ourDepth.get() != progressMap.size()) { + throw new AssertionError("Inconsistent depth 2"); + } + int startStamp = ourMemoizationStamp.get(); try { @@ -116,10 +135,13 @@ public class RecursionManager { return result; } finally { + ourDepth.set(ourDepth.get() - 1); Integer value = progressMap.remove(realKey); + if (value == null) { throw new AssertionError(key + " has changed its equals/hashCode"); } + ourStamp.set(value); if (value == 0) { ourIntermediateCache.get().clear(); @@ -130,6 +152,10 @@ public class RecursionManager { } else { checkZero(); } + + if (ourDepth.get() != progressMap.size()) { + throw new AssertionError("Inconsistent depth 3"); + } } } @@ -158,10 +184,11 @@ public class RecursionManager { @Override public void prohibitResultCaching(Object since) { - ourMemoizationStamp.set(_prohibitResultCaching(since)); + _prohibitResultCaching(since); + ourMemoizationStamp.set(ourMemoizationStamp.get() + 1); } - private int _prohibitResultCaching(Object since) { + private void _prohibitResultCaching(Object since) { int stamp = ourStamp.get() + 1; ourStamp.set(stamp); @@ -178,8 +205,6 @@ public class RecursionManager { } checkZero(); - - return stamp; } }; } From 8f022bd35b2c3fe09dc395e2861217123fafaad9 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 14:49:19 +0200 Subject: [PATCH 19/77] fix geget problem when a completion restarts which has shown a lookup --- .../completion/JavaAutoPopupTest.groovy | 16 ++++++++++++++++ .../codeInsight/AutoPopupController.java | 16 +++++++++++++--- .../completion/CodeCompletionHandlerBase.java | 19 ++++++++++++++----- .../CompletionAutoPopupHandler.java | 9 ++++++++- 4 files changed, 51 insertions(+), 9 deletions(-) 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 a69074d6fee9..d95eb8b7e7e3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -700,6 +700,22 @@ class Foo { assert !lookup } + public void testAutoRestartAndTypingDuringCopyCommit() { + registerLongCompletionContributor() + + myFixture.configureByText("a.java", """ class Foo { { int iteraaa; } } """) + type 'ite' + assert !('iter' in myFixture.lookupElementStrings) + myFixture.type 'r' + joinCommit() + myFixture.type 'a' + joinAutopopup() + joinCompletion() + myFixture.type '\n' + myFixture.checkResult(" class Foo { { int iteraaa; iteraaa } } ") + assert !lookup + } + private void joinSomething(int degree) { if (degree == 0) return joinAlarm() diff --git a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java index 849987b4cd1f..99c668458742 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java @@ -22,6 +22,8 @@ import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler; import com.intellij.codeInsight.hint.ShowParameterInfoHandler; +import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.ide.IdeEventQueue; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; @@ -97,15 +99,18 @@ public class AutoPopupController implements Disposable { return; } + LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor); + boolean shouldBeFast = lookup != null && lookup.isShown(); + final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); if (currentCompletion != null) { - currentCompletion.closeAndFinish(true); + currentCompletion.closeAndFinish(false); } final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(false, editor); CompletionServiceImpl.setCompletionPhase(phase); - addRequest(new Runnable() { + Runnable request = new Runnable() { @Override public void run() { CompletionAutoPopupHandler.runLaterWithCommitted(myProject, editor.getDocument(), new Runnable() { @@ -120,7 +125,12 @@ public class AutoPopupController implements Disposable { } }); } - }, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY); + }; + if (shouldBeFast) { + request.run(); + } else { + addRequest(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY); + } } @TestOnly diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index e55f598a0e5d..9ac45d80c11b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; @@ -28,6 +29,7 @@ import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.application.ex.ApplicationManagerEx; @@ -48,15 +50,13 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.CommitToPsiFileAction; import com.intellij.psi.impl.PsiFileEx; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.impl.source.PostprocessReformattingAspect; @@ -500,10 +500,19 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { final Project project = hostFile.getProject(); - if (autopopup) { + if (!invokedExplicitly) { final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(true, hostEditor); CompletionServiceImpl.setCompletionPhase(phase); + ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() { + @Override + public void beforeWriteActionStart(Object action) { + if (!(action instanceof Class) || !CommitToPsiFileAction.class.isAssignableFrom((Class)action)) { + AutoPopupController.getInstance(project).scheduleAutoPopup(hostEditor, Condition.TRUE); + } + } + }, phase); + CompletionAutoPopupHandler.runLaterWithCommitted(project, hostDocument, new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index eaa7315beb24..88bd527e77b4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -24,6 +24,7 @@ import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.ide.PowerSaveMode; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.FileType; @@ -39,6 +40,7 @@ import org.jetbrains.annotations.NotNull; * @author peter */ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler"); public static volatile boolean ourTestingAutopopup = false; @Override @@ -88,13 +90,18 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { public static void invokeCompletion(CompletionType completionType, boolean autopopup, Project project, Editor editor, int time) { + if (editor.isDisposed()) return; + // retrieve the injected file from scratch since our typing might have destroyed the old one completely Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(editor); PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(topLevelEditor.getDocument()); if (file == null) return; PsiFile topLevelFile = InjectedLanguageUtil.getTopLevelFile(file); - PsiDocumentManager.getInstance(project).commitAllDocuments(); + if (!PsiDocumentManager.getInstance(project).isCommitted(editor.getDocument())) { + LOG.error("Non-committed document"); + PsiDocumentManager.getInstance(project).commitAllDocuments(); + } Editor newEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile); try { new CodeCompletionHandlerBase(completionType, false, autopopup).invokeCompletion(project, newEditor, time, false); From 0dbb562a2af5e55ff4605600ddbbeed80745a939 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 15:07:51 +0200 Subject: [PATCH 20/77] when no imported clas is found, show non-imported. on explicit completion only --- .../completion/AbstractBasicToClassNameDelegator.java | 2 +- .../completion/BasicToClassNameDelegator.java | 9 ++++++++- .../completion/JavaCompletionContributor.java | 7 +++---- .../completion/HeavyNormalCompletionTest.java | 9 +++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java index 2d5a8ed7e453..933613a83726 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java @@ -32,7 +32,7 @@ public abstract class AbstractBasicToClassNameDelegator extends CompletionContri @Override public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - if (parameters.getCompletionType() != CompletionType.BASIC) return; + if (parameters.getCompletionType() != CompletionType.BASIC || parameters.getInvocationCount() == 0) return; final PsiFile file = parameters.getOriginalFile(); final PsiElement position = parameters.getPosition(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java index 29f3eeb1f972..32414a444ef6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.StdLanguages; +import com.intellij.lang.xml.XMLLanguage; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -28,7 +29,13 @@ public class BasicToClassNameDelegator extends AbstractBasicToClassNameDelegator @Override protected boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position) { - return file.getLanguage().isKindOf(StdLanguages.XML) && JavaCompletionContributor.mayStartClassName(result, false); + if (!JavaCompletionContributor.mayStartClassName(result, false)) return false; + + if (file.getLanguage() == StdLanguages.JAVA) { + return JavaCompletionContributor.isClassNamePossible(position); + } + + return file.getLanguage() instanceof XMLLanguage; } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 9a91c820e199..c240ad91b64a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -235,7 +235,7 @@ public class JavaCompletionContributor extends CompletionContributor { public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) { - if (!isClassNamePossible(parameters) || !mayStartClassName(result, parameters.isRelaxedMatching())) return; + if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result, parameters.isRelaxedMatching())) return; if (mayShowAllClasses(parameters)) { JavaClassNameCompletionContributor.addAllClasses(parameters, result, new Consumer() { @@ -276,7 +276,7 @@ public class JavaCompletionContributor extends CompletionContributor { checkAccess, result.getPrefixMatcher(), parameters); PsiClass arrays = JavaPsiFacade.getInstance(position.getProject()).findClass(CommonClassNames.JAVA_UTIL_ARRAYS, position.getResolveScope()); - if (arrays != null && filter.isAcceptable(arrays, position) && isClassNamePossible(parameters)) { + if (arrays != null && filter.isAcceptable(arrays, position) && isClassNamePossible(parameters.getPosition())) { set.add(JavaClassNameCompletionContributor.createClassLookupItem(arrays, true)); } for (LookupElement element : set) { @@ -350,8 +350,7 @@ public class JavaCompletionContributor extends CompletionContributor { } } - private static boolean isClassNamePossible(CompletionParameters parameters) { - PsiElement position = parameters.getPosition(); + public static boolean isClassNamePossible(final PsiElement position) { final PsiElement parent = position.getParent(); if (!(parent instanceof PsiJavaCodeReferenceElement)) return false; if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return false; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.java index b63065a15b07..19cd6d1d4e0f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.java @@ -5,6 +5,7 @@ package com.intellij.codeInsight.completion; import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; @@ -42,6 +43,14 @@ public class HeavyNormalCompletionTest extends CompletionTestCase{ assertTrue(JavaPsiFacade.getInstance(myProject).findPackage("foo.bar.goo").isValid()); } + public void testAllClassesWhenNothingIsFound() throws Throwable { + createClass("package foo.bar; public class AxBxCxDxEx {}"); + + configureByFile("/codeInsight/completion/normal/" + getTestName(false) + ".java"); + ((LookupImpl)LookupManager.getActiveLookup(myEditor)).finishLookup(Lookup.NORMAL_SELECT_CHAR); + checkResultByFile("/codeInsight/completion/normal/" + getTestName(false) + "_after.java"); + } + public void testAllClassesOnSecondBasicCompletion() throws Throwable { createClass("package foo.bar; public class AxBxCxDxEx {}"); From 8c0eff1379e947d001dfcb69da3e025f9e9fe2af Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 15:11:20 +0200 Subject: [PATCH 21/77] assertion recovery --- .../openapi/util/RecursionManager.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index f278bdb9ad60..b3db8bec0dfc 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -112,16 +112,12 @@ public class RecursionManager { throw new AssertionError("Non-zero stamp with empty stack: " + ourStamp.get()); } - if (ourDepth.get() != progressMap.size()) { - throw new AssertionError("Inconsistent depth 1"); - } + checkDepth("1"); progressMap.put(realKey, ourStamp.get()); ourDepth.set(ourDepth.get() + 1); - if (ourDepth.get() != progressMap.size()) { - throw new AssertionError("Inconsistent depth 2"); - } + checkDepth("2"); int startStamp = ourMemoizationStamp.get(); @@ -153,9 +149,7 @@ public class RecursionManager { checkZero(); } - if (ourDepth.get() != progressMap.size()) { - throw new AssertionError("Inconsistent depth 3"); - } + checkDepth("3"); } } @@ -209,6 +203,14 @@ public class RecursionManager { }; } + private static void checkDepth(String s) { + LinkedHashMap progressMap = ourProgress.get(); + if (ourDepth.get() != progressMap.size()) { + ourDepth.set(progressMap.size()); + throw new AssertionError("Inconsistent depth " + s); + } + } + private static void checkZero() { LinkedHashMap progressMap = ourProgress.get(); if (!progressMap.isEmpty() && progressMap.get(progressMap.keySet().iterator().next()) != 0) { From b835909013151bd3e1e849feb09e3eb7e73f7626 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 15:15:12 +0200 Subject: [PATCH 22/77] restart completion when a live template name is entered, also when another live template with shorter name was already suggested --- .../template/impl/LiveTemplateCompletionContributor.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java index 3fae1eabd179..14245bfb5f2f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java @@ -54,10 +54,9 @@ public class LiveTemplateCompletionContributor extends CompletionContributor { final TemplateImpl template = findApplicableTemplate(file, offset, prefix); if (template != null) { result.addElement(new LiveTemplateLookupElement(template)); - } else { - for (final TemplateImpl possible : listApplicableTemplates(file, offset)) { - result.restartCompletionOnPrefixChange(possible.getKey()); - } + } + for (final TemplateImpl possible : listApplicableTemplates(file, offset)) { + result.restartCompletionOnPrefixChange(possible.getKey()); } } From 4e3ea2c0e7793226c426fb487a868e40816a5de2 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 15:37:01 +0200 Subject: [PATCH 23/77] no event log activity during shutdown --- .../src/com/intellij/notification/EventLog.java | 5 ++++- 1 file changed, 4 insertions(+), 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 e9ede9c63a3f..8fe1cbb69c97 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -37,6 +37,7 @@ import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; @@ -274,7 +275,9 @@ public class EventLog implements Notifications { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - console.doPrintNotification(notification); + if (!ShutDownTracker.isShutdownHookRunning()) { + console.doPrintNotification(notification); + } } }); } From 2a4c1898db235219d6adff605d17440e7ee389c5 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 5 Aug 2011 16:24:47 +0200 Subject: [PATCH 24/77] IDEA-38803 (CVS: menus / ** / CVS / Add command is disable for not yet added files in not added directory) --- .../intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java | 3 +-- .../src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java index 727dd4574bd5..e55d902b6098 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -66,7 +66,6 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { CvsActionVisibility visibility = getVisibility(); visibility.addCondition(FILES_ARENT_UNDER_CVS); - visibility.addCondition(FILES_HAVE_PARENT_UNDER_CVS); } public void update(AnActionEvent e) { super.update(e); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java index aeef0caf2a9b..75b428a19981 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -53,7 +53,6 @@ public class IgnoreFileAction extends AnAction { public IgnoreFileAction() { myVisibility.canBePerformedOnSeveralFiles(); - myVisibility.addCondition(ActionOnSelectedElement.FILES_HAVE_PARENT_UNDER_CVS); myVisibility.addCondition(ActionOnSelectedElement.FILES_ARENT_UNDER_CVS); myVisibility.addCondition(ActionOnSelectedElement.FILES_ARE_NOT_IGNORED); } From d55866fa3bbd0c4d920c27da9a6b327d5104a86e Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 16:57:00 +0200 Subject: [PATCH 25/77] todo and suppressions --- .../src/com/intellij/usages/impl/UsageViewManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java index e510f7717fc3..446f1e76354e 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java @@ -344,6 +344,7 @@ public class UsageViewManagerImpl extends UsageViewManager { myPresentation.getScopeText()); if (notFoundActions == null || notFoundActions.isEmpty()) { + //noinspection SSBasedInspection ToolWindowManager.getInstance(myProject).notifyByBalloon(ToolWindowId.FIND, MessageType.INFO, XmlStringUtil.escapeString(message), IconLoader.getIcon("/actions/find.png"), null); From 72e5d5ffafca3912b77e2e4a390a6980a79080ab Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 17:26:03 +0200 Subject: [PATCH 26/77] more info in assertions --- .../util/src/com/intellij/openapi/util/RecursionManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index b3db8bec0dfc..8606cbbd86da 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -205,9 +205,10 @@ public class RecursionManager { private static void checkDepth(String s) { LinkedHashMap progressMap = ourProgress.get(); - if (ourDepth.get() != progressMap.size()) { + Integer depth = ourDepth.get(); + if (depth != progressMap.size()) { ourDepth.set(progressMap.size()); - throw new AssertionError("Inconsistent depth " + s); + throw new AssertionError("Inconsistent depth " + s + "; depth=" + depth + "; map.size=" + progressMap.size()); } } From 52ef8ef0def227916dac734a99a8270be4d7e880 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 5 Aug 2011 19:56:27 +0400 Subject: [PATCH 27/77] DocPopup fixes --- .../codeInsight/documentation/DocumentationManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 80c8827325a2..017580f11dec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -62,7 +62,6 @@ import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.content.*; import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.NotLookupOrSearchCondition; -import com.intellij.ui.popup.PopupPositionManager; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.util.Alarm; import com.intellij.util.Consumer; @@ -912,7 +911,10 @@ public class DocumentationManager { } void showHint(final JBPopup hint) { - PopupPositionManager.positionPopupInBestPosition(hint, myEditor, true); + //todo[spleaner] please fix this in PopupPositionManager + //PopupPositionManager.positionPopupInBestPosition(hint, myEditor, true); + final Component focusOwner = IdeFocusManager.getInstance(myProject).getFocusOwner(); + hint.showInBestPositionFor(DataManager.getInstance().getDataContext(focusOwner)); } public void requestFocus() { From d15f53edd43fb929c4f76729c16bf9d76bd5486f Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 5 Aug 2011 13:32:22 +0400 Subject: [PATCH 28/77] moved markdownj to tasks-core --- .../lib}/markdownj-core-0.4.2-SNAPSHOT.jar | Bin plugins/tasks/tasks-core/tasks-core.iml | 10 +++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) rename {lib => plugins/tasks/tasks-core/lib}/markdownj-core-0.4.2-SNAPSHOT.jar (100%) diff --git a/lib/markdownj-core-0.4.2-SNAPSHOT.jar b/plugins/tasks/tasks-core/lib/markdownj-core-0.4.2-SNAPSHOT.jar similarity index 100% rename from lib/markdownj-core-0.4.2-SNAPSHOT.jar rename to plugins/tasks/tasks-core/lib/markdownj-core-0.4.2-SNAPSHOT.jar diff --git a/plugins/tasks/tasks-core/tasks-core.iml b/plugins/tasks/tasks-core/tasks-core.iml index 53a42e35c169..7053d49a0468 100644 --- a/plugins/tasks/tasks-core/tasks-core.iml +++ b/plugins/tasks/tasks-core/tasks-core.iml @@ -29,7 +29,15 @@ - + + + + + + + + +
From 966c30c9885c134632e332358a59b43c94ffe9ba Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 5 Aug 2011 13:49:11 +0400 Subject: [PATCH 29/77] advertisement for tasks competion --- .../intellij/tasks/impl/TaskCompletionContributor.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java index 9307b5633c7d..cd8832739570 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java @@ -4,6 +4,7 @@ import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProcessCanceledException; @@ -42,6 +43,14 @@ public class TaskCompletionContributor extends CompletionContributor { public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { PsiFile file = parameters.getOriginalFile(); final Consumer consumer = file.getUserData(KEY); + + if (CompletionService.getCompletionService().getAdvertisementText() == null) { + final String shortcut = getActionShortcut(IdeActions.ACTION_QUICK_JAVADOC); + if (shortcut != null) { + CompletionService.getCompletionService().setAdvertisementText("Pressing " + shortcut + " would show task description and comments"); + } + } + if (consumer != null) { result.stopHere(); From e4a8497c1ae0fed52fd45705c805e9abb6baa589 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 5 Aug 2011 20:21:35 +0400 Subject: [PATCH 30/77] IDEA-72952 improve import old config dialog --- .../application/ConfigImportHelper.java | 54 ++++++++++++++++--- .../openapi/application/ImportOldConfigs.form | 28 ++++++---- .../application/ImportOldConfigsPanel.java | 33 ++++++++---- .../src/messages/ApplicationBundle.properties | 12 +++-- .../openapi/application/PathManager.java | 2 +- 5 files changed, 96 insertions(+), 33 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java index 7dd65b1292fe..c021631b591d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java @@ -35,17 +35,20 @@ public class ConfigImportHelper { @NonNls private static final String BUILD_NUMBER_FILE = "build.txt"; @NonNls private static final String PLUGINS_PATH = "plugins"; @NonNls private static final String BIN_FOLDER = "bin"; + @NonNls private static final String OPTIONS_XML = "options/options.xml"; private ConfigImportHelper() {} public static void importConfigsTo(String newConfigPath) { + File oldConfigDir = findOldConfigDir(newConfigPath); + do { ImportOldConfigsPanel dlg; if (UIUtil.hasJdk6Dialogs()) { - dlg = new ImportOldConfigsPanel(); + dlg = new ImportOldConfigsPanel(oldConfigDir); } else { - dlg = new ImportOldConfigsPanel(JOptionPane.getRootFrame()); + dlg = new ImportOldConfigsPanel(oldConfigDir, JOptionPane.getRootFrame()); } UIUtil.setToolkitModal(dlg); @@ -53,7 +56,7 @@ public class ConfigImportHelper { dlg.setVisible(true); if (dlg.isImportEnabled()) { File instHome = dlg.getSelectedFile(); - File oldConfigDir = getOldConfigDir(instHome); + oldConfigDir = getOldConfigDir(instHome); if (!validateOldConfigDir(instHome, oldConfigDir)) continue; doImport(newConfigPath, oldConfigDir); @@ -64,6 +67,33 @@ public class ConfigImportHelper { while (true); } + private static File findOldConfigDir(String newConfigPath) { + final File configDir = new File(newConfigPath); + final File selectorDir = SystemInfo.isMac ? configDir : configDir.getParentFile(); + final File parent = selectorDir.getParentFile(); + if (parent == null || !parent.exists()) return null; + File maxFile = null; + long lastModified = 0; + final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName(); + for (File file : parent.listFiles(new FilenameFilter() { + @Override + public boolean accept(File file, String name) { + return name.length() == selector.length() && + name.startsWith(selector.replaceAll("\\d","")); + + } + })) { + final File options = new File(file, OPTIONS_XML); + if (!options.exists()) continue; + final long modified = options.lastModified(); + if (modified > lastModified) { + lastModified = modified; + maxFile = file; + } + } + return maxFile; + } + public static void doImport(final String newConfigPath, final File oldConfigDir) { try { xcopy(oldConfigDir, new File(newConfigPath)); @@ -77,9 +107,13 @@ public class ConfigImportHelper { public static boolean validateOldConfigDir(final File instHome, final File oldConfigDir) { if (oldConfigDir == null) { + final String message = !instHome.equals(oldConfigDir) ? + ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(), + ApplicationNamesInfo.getInstance().getFullProductName()) : + ApplicationBundle.message("error.invalid.config.folder", instHome.getAbsolutePath(), + ApplicationNamesInfo.getInstance().getFullProductName()) ; JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), - ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(), - ApplicationNamesInfo.getInstance().getFullProductName())); + message); return false; } @@ -113,6 +147,12 @@ public class ConfigImportHelper { @Nullable public static File getOldConfigDir(File oldInstallHome) { + if (oldInstallHome == null) return null; + // check if it's already config dir + if (new File(oldInstallHome, OPTIONS_XML).exists()) { + return oldInstallHome; + } + int oldBuildNumber = getBuildNumber(oldInstallHome); if (oldBuildNumber != -1 && oldBuildNumber <= 600) { // Pandora @@ -252,7 +292,9 @@ public class ConfigImportHelper { return dir; } - public static boolean isInstallationHome(String installationHome) { + public static boolean isInstallationHomeOrConfig(String installationHome) { + if (new File(installationHome, OPTIONS_XML).exists()) return true; + String mainJarName = StringUtil.toLowerCase(ApplicationNamesInfo.getInstance().getProductName()) + ".jar"; //noinspection HardCodedStringLiteral boolean quickTest = new File(new File(installationHome, "lib"), mainJarName).exists() && diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigs.form b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigs.form index 015c85ab8ec5..a51e5f14288a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigs.form +++ b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigs.form @@ -3,7 +3,7 @@ - + @@ -41,7 +41,7 @@ - + @@ -65,14 +65,6 @@
- - - - - - - - @@ -108,6 +100,22 @@ + + + + + + + + + + + + + + + + diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java index 9db136488469..b933518256ec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ImportOldConfigsPanel.java @@ -19,6 +19,7 @@ import com.intellij.openapi.MnemonicHelper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.SystemProperties; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -41,16 +42,19 @@ public class ImportOldConfigsPanel extends JDialog { private JButton myOkButton; private JLabel mySuggestLabel; private JLabel myHomeLabel; + private JRadioButton myRbImportAuto; + private final File myGuessedOldConfig; - public ImportOldConfigsPanel(final Frame owner) { + public ImportOldConfigsPanel(final File guessedOldConfig, final Frame owner) { super(owner, true); + myGuessedOldConfig = guessedOldConfig; init(); } - public ImportOldConfigsPanel() { + public ImportOldConfigsPanel(final File guessedOldConfig) { super((Dialog) null, true); - + myGuessedOldConfig = guessedOldConfig; init(); } @@ -60,12 +64,19 @@ public class ImportOldConfigsPanel extends JDialog { ButtonGroup group = new ButtonGroup(); group.add(myRbDoNotImport); group.add(myRbImport); + group.add(myRbImportAuto); myRbDoNotImport.setSelected(true); final ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance(); final String productName = namesInfo.getProductName().equals("IDEA") ? namesInfo.getFullProductName() : namesInfo.getProductName(); mySuggestLabel.setText(ApplicationBundle.message("label.you.can.import", productName)); myRbDoNotImport.setText(ApplicationBundle.message("radio.do.not.import", productName)); + if(myGuessedOldConfig != null) { + myRbImportAuto.setText(ApplicationBundle.message("radio.import.auto", myGuessedOldConfig.getAbsolutePath().replace(SystemProperties.getUserHome(), "~"))); + myRbImportAuto.setSelected(true); + } else { + myRbImportAuto.setVisible(false); + } myHomeLabel.setText(ApplicationBundle.message("editbox.installation.home", productName)); myRbImport.addChangeListener(new ChangeListener() { @@ -74,7 +85,9 @@ public class ImportOldConfigsPanel extends JDialog { } }); - if (SystemInfo.isMac) { + if (myGuessedOldConfig != null) { + myPrevInstallation.setText(myGuessedOldConfig.getParent()); + } if (SystemInfo.isMac) { myPrevInstallation.setText(findPreviousInstallationMac(productName)); } else if (SystemInfo.isWindows) { @@ -91,9 +104,7 @@ public class ImportOldConfigsPanel extends JDialog { fc = new JFileChooser(myLastSelection); } - if (!SystemInfo.isMac) { - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - } + fc.setFileSelectionMode(SystemInfo.isMac ? JFileChooser.FILES_AND_DIRECTORIES : JFileChooser.DIRECTORIES_ONLY); int returnVal = fc.showOpenDialog(ImportOldConfigsPanel.this); if (returnVal == JFileChooser.APPROVE_OPTION){ @@ -184,7 +195,7 @@ public class ImportOldConfigsPanel extends JDialog { return; } - if (!ConfigImportHelper.isInstallationHome(instHome)) { + if (myRbImport.isSelected() && !ConfigImportHelper.isInstallationHomeOrConfig(instHome)) { JOptionPane.showMessageDialog(this, ApplicationBundle.message("error.does.not.appear.to.be.installation.home", instHome, productWithVendor), @@ -204,11 +215,11 @@ public class ImportOldConfigsPanel extends JDialog { } public boolean isImportEnabled() { - return myRbImport.isSelected(); + return myRbImport.isSelected() || myRbImportAuto.isSelected(); } public File getSelectedFile() { - return new File(myPrevInstallation.getText()); + return myRbImportAuto.isSelected() ? myGuessedOldConfig : new File(myPrevInstallation.getText()); } private void update() { @@ -216,7 +227,7 @@ public class ImportOldConfigsPanel extends JDialog { } public static void main(String[] args) { - ImportOldConfigsPanel dlg = new ImportOldConfigsPanel(); + ImportOldConfigsPanel dlg = new ImportOldConfigsPanel(null); dlg.setVisible(true); } } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index ef7630cba3e7..0a2f48bbd8cd 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -1,18 +1,20 @@ error.invalid.installation.home=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} installation home. +error.invalid.config.folder=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} config folder. error.no.settings.path=Unable to import settings. {0} does not exist. title.settings.import.failed=Settings Import Failed error.unable.to.import.settings=Unable to import settings. {0} title.complete.installation=Complete Installation -title.installation.home.required=Installation Home Required -error.please.select.previous.installation.home=Please select previous {0} installation home +title.installation.home.required=Config Folder or Installation Home Required +error.please.select.previous.installation.home=Please select previous {0} config folder or installation home error.selected.current.installation.home=You have selected current {0} installation home.\nPlease select previous {1} installation home -error.does.not.appear.to.be.installation.home={0} does not appear to be {1} installation home +error.does.not.appear.to.be.installation.home={0} does not appear to be {1} config folder or installation home error.no.read.permissions=You do not have read permissions to {0} radio.do.not.import=I do not have a previous version of {0} or I do not want to import my settings -radio.import=I want to import my settings +radio.import.auto=I want to import my settings from previous version ({0}) +radio.import=I want to import my settings from custom location label.you.can.import=You can import your settings from the previous version of {0}. button.ok=OK -editbox.installation.home=Specify installation home of the previous version of {0} +editbox.installation.home=Specify config folder or installation home of the previous version of {0} title.code.completion=Code Completion editbox.lookup.height=Lookup height (items): editbox.autopopup.javadoc.in.ms=Autopopup documentation in (ms): diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index adf10abd6f80..e5b6053402e4 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -183,7 +183,7 @@ public class PathManager { return ourConfigPath; } - private static String getPathsSelector() { + public static String getPathsSelector() { return System.getProperty(PROPERTY_PATHS_SELECTOR); } From 80edf993d292f2f8eb974e206f2a7763ad84fec5 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 19:15:38 +0200 Subject: [PATCH 31/77] more info in assertions --- .../util/src/com/intellij/openapi/util/RecursionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index 8606cbbd86da..b2ee9a918824 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -208,7 +208,7 @@ public class RecursionManager { Integer depth = ourDepth.get(); if (depth != progressMap.size()) { ourDepth.set(progressMap.size()); - throw new AssertionError("Inconsistent depth " + s + "; depth=" + depth + "; map.size=" + progressMap.size()); + throw new AssertionError("Inconsistent depth " + s + "; depth=" + depth + "; map=" + progressMap); } } From f5f7a96b2494d849db9c630f9d394d0fb6f0ffaf Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 18:29:26 +0400 Subject: [PATCH 32/77] inplace introduce: suggest unique names --- .../InplaceIntroduceConstantPopup.java | 14 ++--------- .../InplaceIntroduceFieldPopup.java | 2 +- .../IntroduceConstantDialog.java | 16 ++++++++++--- .../introduceField/IntroduceFieldDialog.java | 14 +++++++++-- .../IntroduceParameterHandler.java | 5 +++- .../conflictingConstantName_after.java | 4 ++-- .../noConflictingConstantName.java | 21 ++++++++++++++++ .../noConflictingConstantName_after.java | 24 +++++++++++++++++++ .../InplaceIntroduceConstantTest.java | 10 +++++++- 9 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName.java create mode 100644 java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java index 8ecf97fe1563..d3923151789d 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java @@ -15,35 +15,24 @@ */ package com.intellij.refactoring.introduceField; -import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.codeInsight.template.impl.TemplateManagerImpl; -import com.intellij.codeInsight.template.impl.TemplateState; -import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.JavaRefactoringSettings; -import com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer; -import com.intellij.refactoring.introduceParameter.VisibilityListener; -import com.intellij.refactoring.move.moveMembers.MoveMembersImpl; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.refactoring.util.occurences.OccurenceManager; -import com.intellij.ui.StateRestoringCheckBox; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -165,7 +154,8 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField @Override protected String[] suggestNames(PsiType defaultType, String propName) { - return IntroduceConstantDialog.createNameSuggestionGenerator(propName, myExpr, JavaCodeStyleManager.getInstance(myProject), null) + return IntroduceConstantDialog.createNameSuggestionGenerator(propName, myExpr, JavaCodeStyleManager.getInstance(myProject), null, + myParentClass) .getSuggestedNameInfo(defaultType).names; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java index bdcde0e3c30a..f71d7bdbca43 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceFieldPopup.java @@ -107,7 +107,7 @@ public class InplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPop @Override protected String[] suggestNames(PsiType defaultType, String propName) { - return IntroduceFieldDialog.createGenerator(myStatic, (PsiLocalVariable)getLocalVariable(), myExpr, getLocalVariable() != null, null) + return IntroduceFieldDialog.createGenerator(myStatic, (PsiLocalVariable)getLocalVariable(), myExpr, getLocalVariable() != null, null, myParentClass) .getSuggestedNameInfo(defaultType).names; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java index 71afee8cf615..262e41d7c366 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java @@ -34,6 +34,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.impl.source.PsiClassImpl; import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.HelpID; @@ -225,7 +226,7 @@ class IntroduceConstantDialog extends DialogWrapper { } final NameSuggestionsManager nameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, createNameSuggestionGenerator(propertyName, myInitializerExpression, - myCodeStyleManager, myEnteredName)); + myCodeStyleManager, myEnteredName, myParentClass)); nameSuggestionsManager.setLabelsFor(myTypeLabel, myNameSuggestionLabel); ////////// @@ -292,11 +293,20 @@ class IntroduceConstantDialog extends DialogWrapper { protected static NameSuggestionsGenerator createNameSuggestionGenerator(final String propertyName, final PsiExpression psiExpression, final JavaCodeStyleManager codeStyleManager, - final String enteredName) { + final String enteredName, final PsiClass parentClass) { return new NameSuggestionsGenerator() { public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { - final SuggestedNameInfo nameInfo = + SuggestedNameInfo nameInfo = codeStyleManager.suggestVariableName(VariableKind.STATIC_FINAL_FIELD, propertyName, psiExpression, type); + if (psiExpression != null) { + String[] names = nameInfo.names; + for (int i = 0, namesLength = names.length; i < namesLength; i++) { + String name = names[i]; + if (parentClass.findFieldByName(name, false) != null) { + names[i] = codeStyleManager.suggestUniqueVariableName(name, psiExpression, true); + } + } + } final String[] strings = JavaCompletionUtil .completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo); return new SuggestedNameInfo.Delegate(enteredName != null ? ArrayUtil.mergeArrays(new String[]{enteredName}, strings): strings, nameInfo); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java index fc25708fd35b..fb202a3d5aea 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java @@ -177,7 +177,8 @@ class IntroduceFieldDialog extends DialogWrapper { namePrompt.setLabelFor(myNameField.getFocusableComponent()); myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, - createGenerator(myWillBeDeclaredStatic, myLocalVariable, myInitializerExpression, myIsInvokedOnDeclaration, myEnteredName)); + createGenerator(myWillBeDeclaredStatic, myLocalVariable, myInitializerExpression, myIsInvokedOnDeclaration, myEnteredName, + myParentClass)); myNameSuggestionsManager.setLabelsFor(type, namePrompt); return panel; @@ -200,7 +201,7 @@ class IntroduceFieldDialog extends DialogWrapper { static NameSuggestionsGenerator createGenerator(final boolean willBeDeclaredStatic, final PsiLocalVariable localVariable, final PsiExpression initializerExpression, - final boolean isInvokedOnDeclaration, final String enteredName) { + final boolean isInvokedOnDeclaration, final String enteredName, final PsiClass parentClass) { return new NameSuggestionsGenerator() { private final JavaCodeStyleManager myCodeStyleManager = JavaCodeStyleManager.getInstance(localVariable != null ? localVariable.getProject() : initializerExpression.getProject()); @@ -212,6 +213,15 @@ class IntroduceFieldDialog extends DialogWrapper { propertyName = myCodeStyleManager.variableNameToPropertyName(localVariable.getName(), VariableKind.LOCAL_VARIABLE); } final SuggestedNameInfo nameInfo = myCodeStyleManager.suggestVariableName(variableKind, propertyName, initializerExpression, type); + if (initializerExpression != null) { + String[] names = nameInfo.names; + for (int i = 0, namesLength = names.length; i < namesLength; i++) { + String name = names[i]; + if (parentClass.findFieldByName(name, false) != null) { + names[i] = myCodeStyleManager.suggestUniqueVariableName(name, initializerExpression, true); + } + } + } final String[] strings = JavaCompletionUtil.completeVariableNameForRefactoring(myCodeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo); return new SuggestedNameInfo.Delegate(enteredName != null ? ArrayUtil.mergeArrays(new String[]{enteredName}, strings) : strings, nameInfo); } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java index 07496986e261..a96489adbbdb 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java @@ -272,7 +272,10 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R return new NameSuggestionsGenerator() { public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); - final SuggestedNameInfo info = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, propName, expr, type); + SuggestedNameInfo info = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, propName, expr, type); + if (expr != null) { + info = codeStyleManager.suggestUniqueVariableName(info, expr, true); + } final String[] strings = JavaCompletionUtil .completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, info); return new SuggestedNameInfo.Delegate(enteredName != null ? ArrayUtil.mergeArrays(new String[]{enteredName}, strings): strings, info); diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/conflictingConstantName_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/conflictingConstantName_after.java index f82ba57fedbb..208461b6ab48 100644 --- a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/conflictingConstantName_after.java +++ b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/conflictingConstantName_after.java @@ -15,10 +15,10 @@ */ class Test { private static final String FOO = "foo"; - public static final String BAR = "foo"; + public static final String FOO1 = "foo"; public void method(Map args) { System.out.println(FOO); - System.out.println(BAR); + System.out.println(FOO1); } } diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName.java b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName.java new file mode 100644 index 000000000000..5cf132e47b10 --- /dev/null +++ b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName.java @@ -0,0 +1,21 @@ +/* + * 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. + */ +class Test { + public void method(String FOO) { + System.out.println(FOO); + System.out.println("foo"); + } +} diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName_after.java new file mode 100644 index 000000000000..527c41a2e6ce --- /dev/null +++ b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/noConflictingConstantName_after.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +class Test { + + public static final String FOO = "foo"; + + public void method(String FOO) { + System.out.println(FOO); + System.out.println(Test.FOO); + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceConstantTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceConstantTest.java index 5216655a6edd..411bc9fdc0b3 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceConstantTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceConstantTest.java @@ -60,7 +60,15 @@ public class InplaceIntroduceConstantTest extends AbstractInplaceIntroduceTest { doTest(new Pass() { @Override public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) { - type("BAR"); + } + }); + } + + public void testNoConflictingConstantName() throws Exception { + + doTest(new Pass() { + @Override + public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) { } }); } From 28feded27cba288e7fb6a97e9c7561157409a49a Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 19:52:32 +0400 Subject: [PATCH 33/77] scopes: fix generated include pattern (IDEA-72937) --- .../intellij/packageDependencies/ui/PackagePatternProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java b/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java index b2770d7735d5..de6483ad38db 100644 --- a/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java +++ b/java/java-impl/src/com/intellij/packageDependencies/ui/PackagePatternProvider.java @@ -85,7 +85,7 @@ public class PackagePatternProvider extends PatternDialectProvider { pattern += recursively ? "..*" : ".*"; } else { - pattern = recursively ? "*..*" : ".*"; + pattern = recursively ? "*..*" : "*"; } return new PatternPackageSet(pattern, scope, getModulePattern(node)); From 9fadf49e64ed09c837fcd64a0fe14ea3177c5957 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 20:25:03 +0400 Subject: [PATCH 34/77] scopes: show full name for content roots when necessary --- .../packageDependencies/ui/DirectoryNode.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java index c6a39f56c211..74bc05803bfd 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java @@ -75,6 +75,10 @@ public class DirectoryNode extends PackageDependenciesNode { myFQName = VfsUtil.getRelativePath(myVDirectory, contentRoot, '/'); } } + + if (contentRoots.length > 1 && ProjectRootsUtil.isModuleContentRoot(myVDirectory, project)) { + myFQName = getContentRootName(baseDir, myFQName); + } } else { myFQName = FilePatternPackageSet.getLibRelativePath(myVDirectory, index); @@ -82,23 +86,28 @@ public class DirectoryNode extends PackageDependenciesNode { dirName = myFQName; } else { if (contentRoots.length > 1 && ProjectRootsUtil.isModuleContentRoot(myVDirectory, project)) { - if (baseDir != null) { - if (myVDirectory != baseDir) { - if (VfsUtil.isAncestor(baseDir, myVDirectory, false)) { - dirName = VfsUtil.getRelativePath(myVDirectory, baseDir, '/'); - } else { - dirName = myVDirectory.getPresentableUrl(); - } - } - } else { - dirName = myVDirectory.getPresentableUrl(); - } + dirName = getContentRootName(baseDir, dirName); } } myDirName = dirName; myCompactPackages = compactPackages; } + private String getContentRootName(final VirtualFile baseDir, final String dirName) { + if (baseDir != null) { + if (myVDirectory != baseDir) { + if (VfsUtil.isAncestor(baseDir, myVDirectory, false)) { + return VfsUtil.getRelativePath(myVDirectory, baseDir, '/'); + } else { + return myVDirectory.getPresentableUrl(); + } + } + } else { + return myVDirectory.getPresentableUrl(); + } + return dirName; + } + public void fillFiles(Set set, boolean recursively) { super.fillFiles(set, recursively); int count = getChildCount(); From 51e841211505dcd8025689fb911cc7fe5487d04a Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 20:41:18 +0400 Subject: [PATCH 35/77] scopes: restore selected view after scope pattern update (IDEA-72942) --- .../lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java index 184b94eabefd..a0d21181ca7e 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java @@ -73,8 +73,10 @@ public class ScopeViewPane extends AbstractProjectViewPane { refreshProjectViewAlarm.addRequest(new Runnable(){ public void run() { if (myProject.isDisposed()) return; + String subId = getSubId(); myProjectView.removeProjectPane(ScopeViewPane.this); myProjectView.addProjectPane(ScopeViewPane.this); + myProjectView.changeView(getId(), subId); } },10); } From cd375080d83bf1ae7b5c70818f8c97c03b0dd696 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 16:23:21 +0200 Subject: [PATCH 36/77] custom buttons in updates.xml (IDEA-72542) --- .../updateSettings/impl/BuildInfo.java | 17 ++++- .../updateSettings/impl/ButtonInfo.java | 39 ++++++++++ .../updateSettings/impl/UpdateInfoDialog.java | 74 ++++++++++++++----- 3 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ButtonInfo.java diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/BuildInfo.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/BuildInfo.java index 54c5e086c5af..0d138d19b9a6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/BuildInfo.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/BuildInfo.java @@ -14,11 +14,9 @@ * limitations under the License. */ -/* - * @author max - */ package com.intellij.openapi.updateSettings.impl; +import com.google.common.collect.ImmutableList; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.BuildNumber; @@ -31,12 +29,16 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +/** + * @author max + */ public class BuildInfo implements Comparable { private final BuildNumber myNumber; private final String myVersion; private final String myMessage; private final Date myReleaseDate; private final List myPatches; + private final List myButtons; private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.BuildInfo"); @@ -60,6 +62,11 @@ public class BuildInfo implements Comparable { for (Object patchNode : node.getChildren("patch")) { myPatches.add(new PatchInfo((Element)patchNode)); } + + myButtons = new ArrayList(); + for (Object buttonNode : node.getChildren("button")) { + myButtons.add(new ButtonInfo((Element) buttonNode)); + } Element messageTag = node.getChild("message"); myMessage = messageTag != null ? messageTag.getValue() : ""; @@ -94,6 +101,10 @@ public class BuildInfo implements Comparable { return null; } + public List getButtons() { + return ImmutableList.copyOf(myButtons); + } + @Override public String toString() { return "BuildInfo(number=" + myNumber + ")"; diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ButtonInfo.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ButtonInfo.java new file mode 100644 index 000000000000..82820fc66cc0 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ButtonInfo.java @@ -0,0 +1,39 @@ +/* + * 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.openapi.updateSettings.impl; + +import org.jdom.Element; + +/** + * @author yole + */ +public class ButtonInfo { + private final String myName; + private final String myUrl; + + public ButtonInfo(Element element) { + myName = element.getAttributeValue("name"); + myUrl = element.getAttributeValue("url"); + } + + public String getName() { + return myName; + } + + public String getUrl() { + return myUrl; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java index b5581605202e..77a828c068f4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java @@ -27,6 +27,7 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.event.ActionEvent; +import java.util.ArrayList; import java.util.List; /** @@ -49,23 +50,40 @@ class UpdateInfoDialog extends AbstractUpdateDialog { @Override protected Action[] createActions() { - AbstractAction ignore = new AbstractAction("&Ignore This Update") { - @Override - public void actionPerformed(ActionEvent e) { - UpdateSettings.getInstance().getIgnoredBuildNumbers().add(myLatestBuild.getNumber().asStringWithoutProductCode()); - doCancelAction(); - } - }; - if (hasPatch()) { - AbstractAction moreInfo = new AbstractAction(IdeBundle.message("updates.more.info.button")) { - public void actionPerformed(ActionEvent e) { - openDownloadPage(); - } - }; - return new Action[]{getOKAction(), moreInfo, getCancelAction(), ignore }; - } + List actions = new ArrayList(); + actions.add(getOKAction()); - return new Action[] { getOKAction(), getCancelAction(), ignore }; + final List buttons = myLatestBuild.getButtons(); + + if (hasPatch()) { + if (buttons.isEmpty()) { + actions.add(new AbstractAction(IdeBundle.message("updates.more.info.button")) { + public void actionPerformed(ActionEvent e) { + openDownloadPage(); + } + }); + } + else { + for (ButtonInfo info : buttons) { + actions.add(new ButtonAction(info)); + } + } + } + else { + for (int i = 1; i < buttons.size(); i++) { + actions.add(new ButtonAction(buttons.get(i))); + } + } + actions.add(getCancelAction()); + actions.add(new AbstractAction("&Ignore This Update") { + @Override + public void actionPerformed(ActionEvent e) { + UpdateSettings.getInstance().getIgnoredBuildNumbers().add(myLatestBuild.getNumber().asStringWithoutProductCode()); + doCancelAction(); + } + }); + + return actions.toArray(new Action[buttons.size()]); } private void openDownloadPage() { @@ -78,6 +96,9 @@ class UpdateInfoDialog extends AbstractUpdateDialog { ? IdeBundle.message("updates.download.and.install.patch.button.restart") : IdeBundle.message("updates.download.and.install.patch.button"); } + else if (myLatestBuild.getButtons().size() > 0) { + return myLatestBuild.getButtons().get(0).getName(); + } else { return IdeBundle.message("updates.more.info.button"); } @@ -100,7 +121,12 @@ class UpdateInfoDialog extends AbstractUpdateDialog { return; } - openDownloadPage(); + if (myLatestBuild.getButtons().size() > 0) { + BrowserUtil.launchBrowser(myLatestBuild.getButtons().get(0).getUrl()); + } + else { + openDownloadPage(); + } super.doOKAction(); } @@ -124,6 +150,20 @@ class UpdateInfoDialog extends AbstractUpdateDialog { private boolean hasPatch() { return myLatestBuild.findPatchForCurrentBuild() != null; } + + private static class ButtonAction extends AbstractAction { + private ButtonInfo myInfo; + + private ButtonAction(ButtonInfo info) { + super(info.getName()); + myInfo = info; + } + + @Override + public void actionPerformed(ActionEvent e) { + BrowserUtil.launchBrowser(myInfo.getUrl()); + } + } private class UpdateInfoPanel { private JPanel myPanel; From be967340fad021f673fca5675ae5409a488dd99e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 16:30:56 +0200 Subject: [PATCH 37/77] don't allow to save live template if no context is checked (IDEA-71486) --- .../template/impl/EditTemplateDialog.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditTemplateDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditTemplateDialog.java index 765af5c70b11..27140e73aeee 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditTemplateDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditTemplateDialog.java @@ -619,6 +619,22 @@ public class EditTemplateDialog extends DialogWrapper { } + boolean anyChecked = false; + for (JCheckBox contextCheckBox : myCbContextMap.values()) { + if (contextCheckBox.isSelected()) { + anyChecked = true; + break; + } + } + if (!anyChecked) { + Messages.showMessageDialog(getContentPane(), + "Please enable at least one context checkbox. Otherwise the live template will never ber active.", + CodeInsightBundle.message("dialog.edit.template.error.title"), + Messages.getErrorIcon() + ); + return; + } + super.doOKAction(); } } From 63ba56bea534954733c1688c519163b083558485 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 16:56:15 +0200 Subject: [PATCH 38/77] more fine-grained usage types (IDEA-69152) --- .../usages/impl/rules/JavaUsageTypeProvider.java | 11 ++++++++++- .../src/messages/UsageView.properties | 2 ++ .../src/com/intellij/usages/impl/rules/UsageType.java | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java index 475c6b92fc2a..2c442e3b4530 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java @@ -155,6 +155,10 @@ public class JavaUsageTypeProvider implements UsageTypeProvider { if (referenceList.getParent() instanceof PsiClass) return UsageType.CLASS_EXTENDS_IMPLEMENTS_LIST; if (referenceList.getParent() instanceof PsiMethod) return UsageType.CLASS_METHOD_THROWS_LIST; } + if (PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class) != null || + PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class) != null) { + return UsageType.TYPE_PARAMETER; + } PsiTypeCastExpression castExpression = PsiTreeUtil.getParentOfType(element, PsiTypeCastExpression.class); if (castExpression != null) { @@ -203,7 +207,12 @@ public class JavaUsageTypeProvider implements UsageTypeProvider { final PsiNewExpression psiNewExpression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class); if (psiNewExpression != null) { final PsiJavaCodeReferenceElement classReference = psiNewExpression.getClassReference(); - if (classReference != null && PsiTreeUtil.isAncestor(classReference, element, false)) return UsageType.CLASS_NEW_OPERATOR; + if (classReference != null && PsiTreeUtil.isAncestor(classReference, element, false)) { + if (psiNewExpression.getArrayDimensions().length > 0) { + return UsageType.CLASS_NEW_ARRAY; + } + return UsageType.CLASS_NEW_OPERATOR; + } } return null; diff --git a/platform/platform-resources-en/src/messages/UsageView.properties b/platform/platform-resources-en/src/messages/UsageView.properties index d56bef6b840f..3d3564e13fde 100644 --- a/platform/platform-resources-en/src/messages/UsageView.properties +++ b/platform/platform-resources-en/src/messages/UsageView.properties @@ -52,7 +52,9 @@ usage.target.xml.tag.of.file={0} of file {1} usage.target.package.in.directory={0} (in {1}) usage.target.exception=Exception usage.type.new=New instance creation +usage.type.new.array=New array creation usage.type.annotation=Annotation +usage.type.type.parameter=Type parameter usage.type.read=Value read usage.type.write=Value write preview.usages.action.text=Preview Usages diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java index 3a720fd16a3e..2845da6623b8 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java @@ -31,7 +31,9 @@ public final class UsageType { public static final UsageType CLASS_CATCH_CLAUSE_PARAMETER_DECLARATION = new UsageType(UsageViewBundle.message("usage.type.catch.declaration")); public static final UsageType CLASS_METHOD_RETURN_TYPE = new UsageType(UsageViewBundle.message("usage.type.return")); public static final UsageType CLASS_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new")); + public static final UsageType CLASS_NEW_ARRAY = new UsageType(UsageViewBundle.message("usage.type.new.array")); public static final UsageType ANNOTATION = new UsageType(UsageViewBundle.message("usage.type.annotation")); + public static final UsageType TYPE_PARAMETER = new UsageType(UsageViewBundle.message("usage.type.type.parameter")); public static final UsageType READ = new UsageType(UsageViewBundle.message("usage.type.read")); public static final UsageType WRITE = new UsageType(UsageViewBundle.message("usage.type.write")); From 24ea1f72098ff63406bdd0cce0c0470474fcc895 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 17:12:41 +0200 Subject: [PATCH 39/77] VM has options, program has arguments (IDEA-69255) --- .../src/messages/ExecutionBundle.properties | 6 +++--- plugins/devkit/src/DevKitBundle.properties | 4 ++-- .../plugins/groovy/mvc/MvcRunConfigurationEditor.form | 2 +- .../plugins/groovy/mvc/MvcRunConfigurationEditor.java | 2 +- .../jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.form | 2 +- .../plugins/groovy/runner/GroovyRunConfigurationEditor.form | 2 +- .../plugins/groovy/runner/GroovyRunConfigurationEditor.java | 2 +- .../idea/maven/execution/MavenRunnerConfigurable.java | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 5b37f7ee305c..7f8507365c07 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -146,8 +146,8 @@ junit.tests.in.progress.label=Tests in Progress junit.auto.scroll.to.source.action.name=Auto Scroll to Source junit.open.text.in.editor.action.name=Open selected test in editor -run.configuration.java.vm.parameters.label=&VM parameters: -run.configuration.program.parameters=Program pa&rameters: +run.configuration.java.vm.parameters.label=&VM options: +run.configuration.program.parameters=Program a&rguments: run.configuration.working.directory.label=&Working directory: run.configuration.use.alternate.jre.checkbox=Use alternative &JRE: run.configuration.select.alternate.jre.label=Select Alternative JRE @@ -175,7 +175,7 @@ applet.configuration.width.label= &Width: applet.configuration.url.html.file.label=URL/HTML &file: applet.configuration.url.border=URL applet.configuration.use.classpath.and.jdk.of.module.label=Use classpath and JDK of m&odule: -applet.configuration.vm.parameters.for.appletviewer.label=&VM parameters for appletviewer: +applet.configuration.vm.parameters.for.appletviewer.label=&VM options for appletviewer: applet.configuration.policy.file.label=&Policy file: applet.configuration.parameter.name.column=Name applet.configuration.parameter.value.column=Value diff --git a/plugins/devkit/src/DevKitBundle.properties b/plugins/devkit/src/DevKitBundle.properties index f5212567be0b..9080c75d785f 100644 --- a/plugins/devkit/src/DevKitBundle.properties +++ b/plugins/devkit/src/DevKitBundle.properties @@ -15,8 +15,8 @@ manifest.use.user.defined=Use user manifest: deployment.view.delete=Delete {0}? deployment.view.meta-inf.label=Path to {0} suggest.to.delete=Do you want to delete ''{0}''? -vm.parameters=&VM Parameters -program.parameters=&Program Parameters +vm.parameters=&VM Options +program.parameters=&Program Arguments #Prepare for deployment action select.plugin.modules.title=Select modules diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.form index 15c8988f4a95..c01ba6251cfe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.form @@ -13,7 +13,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.java index e8ffd9a4ebb9..dfe620ea5337 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfigurationEditor.java @@ -55,7 +55,7 @@ public class MvcRunConfigurationEditor extends Se protected void resetEditorFrom(T configuration) { myFramework = configuration.getFramework(); - myVMParameters.setDialogCaption("VM Parameters"); + myVMParameters.setDialogCaption("VM Options"); myVMParameters.setText(configuration.vmParams); myVMParamsLabel.setLabelFor(myVMParameters); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.form index 53d1fb9d6be8..621cade9bc6b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.form @@ -58,7 +58,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.form index 6dac68a900e5..f7d1ad3f51cf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.form @@ -79,7 +79,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java index 2467ed7b511b..4779d4d3f952 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java @@ -75,7 +75,7 @@ public class GroovyRunConfigurationEditor extends SettingsEditor Date: Fri, 5 Aug 2011 17:30:30 +0200 Subject: [PATCH 40/77] FilePrompt macro for external tools (IDEA-68788) --- .../intellij/ide/macro/FilePromptMacro.java | 59 +++++++++++ .../com/intellij/ide/macro/MacroManager.java | 1 + .../application/options/PathMacrosImpl.java | 100 +++++++++--------- .../src/messages/IdeBundle.properties | 1 + 4 files changed, 110 insertions(+), 51 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/ide/macro/FilePromptMacro.java diff --git a/platform/lang-impl/src/com/intellij/ide/macro/FilePromptMacro.java b/platform/lang-impl/src/com/intellij/ide/macro/FilePromptMacro.java new file mode 100644 index 000000000000..a6096602a02e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/macro/FilePromptMacro.java @@ -0,0 +1,59 @@ +/* + * 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.ide.macro; + +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.fileChooser.FileChooserDialog; +import com.intellij.openapi.fileChooser.FileChooserFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; + +/** + * @author yole + */ +public class FilePromptMacro extends Macro implements SecondQueueExpandMacro { + @Override + public String getName() { + return "FilePrompt"; + } + + @Override + public String getDescription() { + return "Shows a file chooser dialog"; + } + + @Override + public String expand(DataContext dataContext) throws ExecutionCancelledException { + Project project = PlatformDataKeys.PROJECT.getData(dataContext); + final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleLocalFileDescriptor(); + final FileChooserDialog fileChooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project); + final VirtualFile[] result = fileChooser.choose(null, project); + if (result.length != 1) { + throw new ExecutionCancelledException(); + } + return FileUtil.toSystemDependentName(result [0].getPath()); + } + + @Override + public void cachePreview(DataContext dataContext) { + myCachedPreview = IdeBundle.message("macro.fileprompt.preview"); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java b/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java index e2230cf6ec3d..1cfccc09c07d 100644 --- a/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java +++ b/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java @@ -57,6 +57,7 @@ public final class MacroManager { registerMacro(new FilePathRelativeToSourcepathMacro()); registerMacro(new JdkPathMacro()); registerMacro(new PromptMacro()); + registerMacro(new FilePromptMacro()); registerMacro(new SourcepathEntryMacro()); registerMacro(new ProjectFileDirMacro()); registerMacro(new ProjectNameMacro()); diff --git a/platform/platform-impl/src/com/intellij/application/options/PathMacrosImpl.java b/platform/platform-impl/src/com/intellij/application/options/PathMacrosImpl.java index a28055b8527f..07af537be382 100644 --- a/platform/platform-impl/src/com/intellij/application/options/PathMacrosImpl.java +++ b/platform/platform-impl/src/com/intellij/application/options/PathMacrosImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.application.options; +import com.google.common.collect.ImmutableSet; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathMacros; import com.intellij.openapi.components.ApplicationComponent; @@ -75,57 +76,54 @@ public class PathMacrosImpl extends PathMacros implements ApplicationComponent, SYSTEM_MACROS.add(USER_HOME_MACRO_NAME); } - private static final Set ourToolsMacros = new HashSet(); - - static { - ourToolsMacros.addAll(Arrays.asList( - "ClasspathEntry", - "Classpath", - "ColumnNumber", - "FileClass", - "FileDir", - "FileDirRelativeToProjectRoot", - "/FileDirRelativeToProjectRoot", - "FileDirRelativeToSourcepath", - "/FileDirRelativeToSourcepath", - "FileExt", - "FileFQPackage", - "FileName", - "FileNameWithoutExtension", - "FilePackage", - "FilePath", - "FilePathRelativeToProjectRoot", - "/FilePathRelativeToProjectRoot", - "FilePathRelativeToSourcepath", - "/FilePathRelativeToSourcepath", - "FileRelativeDir", - "/FileRelativeDir", - "FileRelativePath", - "/FileRelativePath", - "JavaDocPath", - "JDKPath", - "LineNumber", - "ModuleFileDir", - "ModuleFilePath", - "ModuleName", - "ModuleSourcePath", - "OutputPath", - "PhpExecutable", - "ProjectFileDir", - "ProjectFilePath", - "ProjectName", - "Projectpath", - "Prompt", - "SourcepathEntry", - "Sourcepath", - "SHOW_CHANGES", - "SelectedText", - "SelectionStartLine", - "SelectionEndLine", - "SelectionStartColumn", - "SelectionEndColumn" - )); - } + private static final Set ourToolsMacros = ImmutableSet.of( + "ClasspathEntry", + "Classpath", + "ColumnNumber", + "FileClass", + "FileDir", + "FileDirRelativeToProjectRoot", + "/FileDirRelativeToProjectRoot", + "FileDirRelativeToSourcepath", + "/FileDirRelativeToSourcepath", + "FileExt", + "FileFQPackage", + "FileName", + "FileNameWithoutExtension", + "FilePackage", + "FilePath", + "FilePathRelativeToProjectRoot", + "/FilePathRelativeToProjectRoot", + "FilePathRelativeToSourcepath", + "/FilePathRelativeToSourcepath", + "FilePrompt", + "FileRelativeDir", + "/FileRelativeDir", + "FileRelativePath", + "/FileRelativePath", + "JavaDocPath", + "JDKPath", + "LineNumber", + "ModuleFileDir", + "ModuleFilePath", + "ModuleName", + "ModuleSourcePath", + "OutputPath", + "PhpExecutable", + "ProjectFileDir", + "ProjectFilePath", + "ProjectName", + "Projectpath", + "Prompt", + "SourcepathEntry", + "Sourcepath", + "SHOW_CHANGES", + "SelectedText", + "SelectionStartLine", + "SelectionEndLine", + "SelectionStartColumn", + "SelectionEndColumn" + ); public PathMacrosImpl() { //setMacro(USER_HOME_MACRO_NAME, FileUtil.toSystemIndependentName(SystemProperties.getUserHome())); diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 5f8e78577085..b99582401fa1 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -470,6 +470,7 @@ macro.prompt=Displays a string input dialog prompt.enter.parameters=Enter parameters: title.input=Input macro.prompt.preview= +macro.fileprompt.preview= macro.sourcepath.entry=Entry in the sourcepath the element belongs to macro.project.sourcepath=Project's sourcepath error.plugins.should.not.have.cyclic.dependencies=Plugins should not have cyclic dependencies:\n From b50df6d173feb5b927362e37aa1f477b906be76a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 17:37:04 +0200 Subject: [PATCH 41/77] remove unnecessary preferred height declaration for ignored file types text field (IDEA-66528) --- .../src/com/intellij/openapi/fileTypes/impl/FileTypePanel.form | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypePanel.form b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypePanel.form index cc4cfbdf055d..0a53012e2f4e 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypePanel.form +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypePanel.form @@ -34,8 +34,7 @@ - - + From fd325eeadd493b5a8b16ed4150500c673255100d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 17:56:27 +0200 Subject: [PATCH 42/77] rename button (IDEA-62636) --- .../src/com/intellij/ide/plugins/PluginManagerMain.form | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form index 18691d57f234..1b4f0545dff6 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form @@ -290,7 +290,7 @@ - + From 5f0e940919130c7d57cec96e1c1e10b782d564ec Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 18:25:05 +0200 Subject: [PATCH 43/77] more general code for rebuilding file structure popup when filter checkbox is toggled (IDEA-65005) --- .../src/com/intellij/ide/util/FileStructureDialog.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java index 00819c5c31ca..db96f42c2a8e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java @@ -23,7 +23,6 @@ import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.ide.structureView.StructureViewModel; import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; -import com.intellij.ide.structureView.impl.common.PsiTreeElementBase; import com.intellij.ide.structureView.newStructureView.TreeActionsOwner; import com.intellij.ide.structureView.newStructureView.TreeModelWrapper; import com.intellij.ide.util.treeView.AbstractTreeNode; @@ -271,8 +270,11 @@ public class FileStructureDialog extends DialogWrapper { if (builder != null) { final AbstractTreeNode parentNode = builder.getParentNode(); final Object value = parentNode.getValue(); - if (value instanceof PsiTreeElementBase) { - currentParent = ((PsiTreeElementBase) value).getValue(); + if (value instanceof StructureViewTreeElement) { + final Object elementValue = ((StructureViewTreeElement)value).getValue(); + if (elementValue instanceof PsiElement) { + currentParent = (PsiElement) elementValue; + } } } myTreeActionsOwner.setFilterIncluded(fileStructureFilter, !chkFilter.isSelected()); From d66e1845caa10db1f2b162eacf1726a77c1d90ef Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 5 Aug 2011 18:42:51 +0200 Subject: [PATCH 44/77] configure scopes from within hierarchy browser (IDEA-63404) --- .../ide/hierarchy/HierarchyBrowserBaseEx.java | 58 ++++++++++++++----- .../util/scopeChooser/EditScopesDialog.java | 5 +- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBaseEx.java b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBaseEx.java index 06564bc056d2..634cf9545236 100644 --- a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBaseEx.java +++ b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBaseEx.java @@ -26,6 +26,7 @@ import com.intellij.ide.dnd.DnDManager; import com.intellij.ide.dnd.DnDSource; import com.intellij.ide.dnd.aware.DnDAwareTree; import com.intellij.ide.projectView.impl.TransferableWrapper; +import com.intellij.ide.util.scopeChooser.EditScopesDialog; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; @@ -604,20 +605,42 @@ public abstract class HierarchyBrowserBaseEx extends HierarchyBrowserBase implem protected final DefaultActionGroup createPopupActionGroup(final JComponent button) { final DefaultActionGroup group = new DefaultActionGroup(); - group.add(new MenuAction(SCOPE_PROJECT)); - group.add(new MenuAction(SCOPE_TEST)); - group.add(new MenuAction(SCOPE_ALL)); - group.add(new MenuAction(SCOPE_CLASS)); + for(String name: getValidScopeNames()) { + group.add(new MenuAction(name)); + } + + group.add(new ConfigureScopesAction()); + + return group; + } + + private Collection getValidScopeNames() { + List result = new ArrayList(); + result.add(SCOPE_PROJECT); + result.add(SCOPE_TEST); + result.add(SCOPE_ALL); + result.add(SCOPE_CLASS); final NamedScopesHolder[] holders = NamedScopesHolder.getAllNamedScopeHolders(myProject); for (NamedScopesHolder holder : holders) { NamedScope[] scopes = holder.getEditableScopes(); //predefined scopes already included for (NamedScope scope : scopes) { - group.add(new MenuAction(scope.getName())); + result.add(scope.getName()); } } + return result; + } - return group; + private void selectScope(final String scopeType) { + myType2ScopeMap.put(myCurrentViewType, scopeType); + HierarchyBrowserManager.getInstance(myProject).getState().SCOPE = scopeType; + + // invokeLater is called to update state of button before long tree building operation + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + doRefresh(true); // scope is kept per type so other builders doesn't need to be refreshed + } + }); } public final JComponent createCustomComponent(final Presentation presentation) { @@ -638,18 +661,23 @@ public abstract class HierarchyBrowserBaseEx extends HierarchyBrowserBase implem } public final void actionPerformed(final AnActionEvent e) { - myType2ScopeMap.put(myCurrentViewType, myScopeType); - HierarchyBrowserManager.getInstance(myProject).getState().SCOPE = myScopeType; - - // invokeLater is called to update state of button before long tree building operation - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - doRefresh(true); // scope is kept per type so other builders doesn't need to be refreshed - } - }); + selectScope(myScopeType); } } + + private final class ConfigureScopesAction extends AnAction { + private ConfigureScopesAction() { + super("Configure..."); + } + @Override + public void actionPerformed(AnActionEvent e) { + EditScopesDialog.editConfigurable(myProject, null); + if (!getValidScopeNames().contains(myType2ScopeMap.get(myCurrentViewType))) { + selectScope(SCOPE_ALL); + } + } + } } } diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java index dfaa3192c84d..4db891566d2e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java @@ -25,6 +25,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.packageDependencies.DependencyValidationManager; import com.intellij.psi.search.scope.packageSet.NamedScope; import com.intellij.psi.search.scope.packageSet.PackageSet; +import org.jetbrains.annotations.Nullable; /** * User: anna @@ -76,11 +77,11 @@ public class EditScopesDialog extends SingleConfigurableEditor { } - public static EditScopesDialog editConfigurable(final Project project, final Runnable advancedInitialization){ + public static EditScopesDialog editConfigurable(final Project project, @Nullable final Runnable advancedInitialization){ return editConfigurable(project, advancedInitialization, false); } - public static EditScopesDialog editConfigurable(final Project project, final Runnable advancedInitialization, final boolean checkShared){ + public static EditScopesDialog editConfigurable(final Project project, @Nullable final Runnable advancedInitialization, final boolean checkShared){ final EditScopesDialog dialog = new EditScopesDialog(project, checkShared); if (advancedInitialization != null) { advancedInitialization.run(); From 500e2034a54cf11f1a2408020b340e24346a7860 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 21:46:37 +0400 Subject: [PATCH 45/77] scopes: add separate setting for modules in scope view (IDEA-72947) --- .../ide/projectView/impl/PackageViewPane.java | 29 +++--------- .../projectView/impl/ShowModulesAction.java | 45 +++++++++++++++++++ .../ide/scopeView/ScopeTreeViewPanel.java | 2 + .../intellij/ide/scopeView/ScopeViewPane.java | 12 +++-- 4 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java index e07528c38d05..8cd27169478f 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java @@ -148,28 +148,6 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane { return super.getSelectedDirectories(); } - private final class ShowModulesAction extends ToggleAction { - private ShowModulesAction() { - super(IdeBundle.message("action.show.modules"), IdeBundle.message("action.description.show.modules"), IconLoader.getIcon("/objectBrowser/showModules.png")); - } - - public boolean isSelected(AnActionEvent event) { - return ProjectView.getInstance(myProject).isShowModules(getId()); - } - - public void setSelected(AnActionEvent event, boolean flag) { - final ProjectViewImpl projectView = (ProjectViewImpl)ProjectView.getInstance(myProject); - projectView.setShowModules(flag, getId()); - } - - public void update(AnActionEvent e) { - super.update(e); - final Presentation presentation = e.getPresentation(); - final ProjectViewImpl projectView = (ProjectViewImpl)ProjectView.getInstance(myProject); - presentation.setVisible(projectView.getCurrentProjectViewPane() == PackageViewPane.this); - } - } - private final class ShowLibraryContentsAction extends ToggleAction { private ShowLibraryContentsAction() { super(IdeBundle.message("action.show.libraries.contents"), IdeBundle.message("action.show.hide.library.contents"), IconLoader.getIcon("/objectBrowser/showLibraryContents.png")); @@ -193,7 +171,12 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane { } public void addToolbarActions(DefaultActionGroup actionGroup) { - actionGroup.addAction(new ShowModulesAction()).setAsSecondary(true); + actionGroup.addAction(new ShowModulesAction(myProject){ + @Override + protected String getId() { + return PackageViewPane.this.getId(); + } + }).setAsSecondary(true); actionGroup.addAction(new ShowLibraryContentsAction()).setAsSecondary(true); } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java new file mode 100644 index 000000000000..21cde88973b3 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java @@ -0,0 +1,45 @@ +package com.intellij.ide.projectView.impl; + +import com.intellij.ide.IdeBundle; +import com.intellij.ide.projectView.ProjectView; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.IconLoader; + +/** +* Created by IntelliJ IDEA. +* User: anna +* Date: 8/5/11 +* Time: 9:33 PM +* To change this template use File | Settings | File Templates. +*/ +public abstract class ShowModulesAction extends ToggleAction { + private Project myProject; + + public ShowModulesAction(Project project) { + super(IdeBundle.message("action.show.modules"), IdeBundle.message("action.description.show.modules"), IconLoader + .getIcon("/objectBrowser/showModules.png")); + myProject = project; + } + + public boolean isSelected(AnActionEvent event) { + return ProjectView.getInstance(myProject).isShowModules(getId()); + } + + protected abstract String getId(); + + public void setSelected(AnActionEvent event, boolean flag) { + final ProjectViewImpl projectView = (ProjectViewImpl)ProjectView.getInstance(myProject); + projectView.setShowModules(flag, getId()); + } + + public void update(AnActionEvent e) { + super.update(e); + final Presentation presentation = e.getPresentation(); + final ProjectViewImpl projectView = (ProjectViewImpl)ProjectView.getInstance(myProject); + presentation.setVisible(Comparing.strEqual(projectView.getCurrentViewId(), getId())); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java index 2a293c7e50c4..ffcd576132fa 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java @@ -277,6 +277,8 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { final ProjectView projectView = ProjectView.getInstance(myProject); settings.UI_FLATTEN_PACKAGES = projectView.isFlattenPackages(ScopeViewPane.ID); settings.UI_COMPACT_EMPTY_MIDDLE_PACKAGES = projectView.isHideEmptyMiddlePackages(ScopeViewPane.ID); + settings.UI_SHOW_MODULES = projectView.isShowModules(ScopeViewPane.ID); + settings.UI_SHOW_MODULE_GROUPS = projectView.isShowModules(ScopeViewPane.ID); myBuilder = new FileTreeModelBuilder(myProject, new Marker() { public boolean isMarked(VirtualFile file) { return packageSet != null && (packageSet instanceof PackageSetBase ? ((PackageSetBase)packageSet).contains(file, holder) : packageSet.contains(PackageSetBase.getPsiFile(file, holder), holder)); diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java index a0d21181ca7e..1aaed1d7b195 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java @@ -20,10 +20,8 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.SelectInTarget; import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.projectView.impl.AbstractProjectViewPane; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.ide.projectView.impl.ShowModulesAction; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; @@ -137,6 +135,12 @@ public class ScopeViewPane extends AbstractProjectViewPane { public void addToolbarActions(DefaultActionGroup actionGroup) { actionGroup.add(ActionManager.getInstance().getAction("ScopeView.EditScopes")); + actionGroup.addAction(new ShowModulesAction(myProject){ + @Override + protected String getId() { + return ScopeViewPane.this.getId(); + } + }).setAsSecondary(true); } public ActionCallback updateFromRoot(boolean restoreExpandedPaths) { From d2516381254397f3a6f3283305c69d8ae33f45f8 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 5 Aug 2011 21:51:30 +0400 Subject: [PATCH 46/77] scopes: show progress on update to stop being busy --- .../com/intellij/ide/scopeView/ScopeTreeViewPanel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java index ffcd576132fa..25df91aa7905 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java @@ -215,7 +215,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { } public void selectScope(final NamedScope scope) { - refreshScope(scope, true); + refreshScope(scope); if (scope != DefaultScopesProvider.getAllScope()) { CURRENT_SCOPE_NAME = scope.getName(); } @@ -262,7 +262,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { return PsiElement.EMPTY_ARRAY; } - private void refreshScope(@Nullable NamedScope scope, boolean showProgress) { + private void refreshScope(@Nullable NamedScope scope) { FileTreeModelBuilder.clearCaches(myProject); if (scope == null || scope.getValue() == null) { //was deleted scope = DefaultScopesProvider.getAllScope(); @@ -289,7 +289,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { myTree.getEmptyText().setText("Loading..."); myActionCallback = new ActionCallback(); myTree.putClientProperty(TreeState.CALLBACK, new WeakReference(myActionCallback)); - myTree.setModel(myBuilder.build(myProject, showProgress, new Runnable(){ + myTree.setModel(myBuilder.build(myProject, true, new Runnable(){ @Override public void run() { myTree.setPaintBusy(false); @@ -598,7 +598,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { myUpdateQueue.cancelAllUpdates(); queueUpdate(new Runnable() { public void run() { - refreshScope(scope, true); + refreshScope(scope); } }, false); } @@ -652,7 +652,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { myUpdateQueue.cancelAllUpdates(); myUpdateQueue.queue(new Update("RootsChanged") { public void run() { - refreshScope(getCurrentScope(), false); + refreshScope(getCurrentScope()); } public boolean isExpired() { From e8e59672eab7594f08f07e773288225414d0d781 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Aug 2011 16:49:35 +0400 Subject: [PATCH 47/77] class name fixed --- java/compiler/impl/src/com/intellij/compiler/SymbolTable.java | 3 ++- .../intellij/compiler/impl/generic/GenericCompilerCache.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/SymbolTable.java b/java/compiler/impl/src/com/intellij/compiler/SymbolTable.java index 279e423d0866..48603f534ad2 100644 --- a/java/compiler/impl/src/com/intellij/compiler/SymbolTable.java +++ b/java/compiler/impl/src/com/intellij/compiler/SymbolTable.java @@ -25,6 +25,7 @@ import com.intellij.compiler.make.CacheCorruptedException; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.containers.SLRUCache; +import com.intellij.util.io.PersistentEnumerator; import com.intellij.util.io.PersistentStringEnumerator; import org.jetbrains.annotations.NotNull; @@ -69,7 +70,7 @@ public class SymbolTable { } myTrie = new PersistentStringEnumerator(file); } - catch (PersistentStringEnumerator.CorruptedException e) { + catch (PersistentEnumerator.CorruptedException e) { throw new CacheCorruptedException(CompilerBundle.message("error.compiler.caches.corrupted"), e); } catch (IOException e) { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java b/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java index b89143ec77ad..5741b9cf7949 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.Processor; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.PersistentEnumerator; import com.intellij.util.io.PersistentHashMap; import org.jetbrains.annotations.NotNull; @@ -49,7 +50,7 @@ public class GenericCompilerCache { myPersistentMap = new PersistentHashMap, PersistentStateData>(myCacheFile, new SourceItemDataDescriptor(myCompiler.getItemKeyDescriptor()), new PersistentStateDataExternalizer(myCompiler)); } - catch (PersistentHashMap.CorruptedException e) { + catch (PersistentEnumerator.CorruptedException e) { FileUtil.delete(myCacheFile); throw e; } From 229b755f8986f9524d3f96c489561f143791d0f6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Aug 2011 17:57:33 +0400 Subject: [PATCH 48/77] btree enumerator is default for 32 bit jdk + it is changeable via idea.use.btree command line property --- .../util/io/PersistentBTreeEnumerator.java | 95 +++++++------ .../util/io/PersistentEnumerator.java | 43 +++--- .../util/io/PersistentEnumeratorBase.java | 47 ++++--- .../util/io/PersistentEnumeratorDelegate.java | 79 +++++++++++ .../intellij/util/io/PersistentHashMap.java | 127 ++++++++++-------- .../util/io/PersistentStringEnumerator.java | 34 +---- 6 files changed, 255 insertions(+), 170 deletions(-) create mode 100644 platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index 1766c7f0f14d..a45ea6ae409a 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -44,7 +44,6 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase dataDescriptor, int initialSize) throws IOException { - super(file, new MappedFileSimpleStorage(file, initialSize, 1024 * 1024, false), dataDescriptor, initialSize, ourVersion); + this(file, dataDescriptor, initialSize, new RecordBufferHandler()); + } - myInlineKeysNoMapping = myDataDescriptor instanceof InlineKeyDescriptor && !wantInlineKeyMapping(); - myBuffer = new byte[getRecordSize()]; + public PersistentBTreeEnumerator(File file, KeyDescriptor dataDescriptor, int initialSize, + PersistentEnumeratorBase.RecordBufferHandler recordBufferHandler) throws IOException { + super(file, new MappedFileSimpleStorage(file, initialSize, 1024 * 1024, false), dataDescriptor, initialSize, + ourVersion, recordBufferHandler); - if (btree == null) { - synchronized (ourLock) { - storeVars(false); - initBtree(false); - storeBTreeVars(false); + myInlineKeysNoMapping = myDataDescriptor instanceof InlineKeyDescriptor && !wantInlineKeyMapping(); + + if (btree == null) { + synchronized (ourLock) { + storeVars(false); + initBtree(false); + storeBTreeVars(false); + } } } - } protected boolean wantInlineKeyMapping() { return false; @@ -211,7 +215,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase extends PersistentEnumeratorBase btree.pageSize) { - assert myDataPageOffset + 4 <= btree.pageSize; - int prevDataPageStart = myDataPageStart + btree.pageSize - 4; - myDataPageStart = allocPage(); - myStorage.putInt(prevDataPageStart, myDataPageStart); - myDataPageOffset = 0; - } - - int recordWriteOffset = myDataPageOffset; - assert recordWriteOffset + buf.length + 4 <= btree.pageSize; - myDataPageOffset += buf.length; - return recordWriteOffset + myDataPageStart; - } - private int nextDuplicatedValueRecord() { if (myDuplicatedValuesPageStart == -1 || myDuplicatedValuesPageOffset == btree.pageSize) { myDuplicatedValuesPageStart = allocPage(); @@ -390,19 +370,46 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase { + private byte[] myBuffer; + + @Override + int recordWriteOffset(PersistentBTreeEnumerator enumerator, byte[] buf) { + if (enumerator.myFirstPageStart == -1) { + enumerator.myFirstPageStart = enumerator.myDataPageStart = enumerator.allocPage(); + } + if (enumerator.myDataPageOffset + buf.length + 4 > enumerator.btree.pageSize) { + assert enumerator.myDataPageOffset + 4 <= enumerator.btree.pageSize; + int prevDataPageStart = enumerator.myDataPageStart + enumerator.btree.pageSize - 4; + enumerator.myDataPageStart = enumerator.allocPage(); + enumerator.myStorage.putInt(prevDataPageStart, enumerator.myDataPageStart); + enumerator.myDataPageOffset = 0; + } + + int recordWriteOffset = enumerator.myDataPageOffset; + assert recordWriteOffset + buf.length + 4 <= enumerator.btree.pageSize; + enumerator.myDataPageOffset += buf.length; + return recordWriteOffset + enumerator.myDataPageStart; + } + + @Override + byte[] getRecordBuffer(PersistentBTreeEnumerator enumerator) { + if (myBuffer == null) { + myBuffer = new byte[enumerator.myInlineKeysNoMapping ? 0:RECORD_SIZE]; + } + return myBuffer; + } + + @Override + void setupRecord(PersistentBTreeEnumerator enumerator, int hashCode, int dataOffset, byte[] buf) { + if (!enumerator.myInlineKeysNoMapping) Bits.putInt(buf, 0, dataOffset); + } + } } diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentEnumerator.java index d6ed9b8f43fb..f93de01772a6 100644 --- a/platform/util/src/com/intellij/util/io/PersistentEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentEnumerator.java @@ -44,8 +44,6 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { private static final int FIRST_LEVEL_MASK = SLOTS_PER_FIRST_VECTOR - 1; private static final byte[] FIRST_VECTOR = new byte[SLOTS_PER_FIRST_VECTOR * 4]; - private final byte[] myBuffer = new byte[RECORD_SIZE]; - private static final int COLLISION_OFFSET = 0; private static final int KEY_HASHCODE_OFFSET = COLLISION_OFFSET + 4; private static final int KEY_REF_OFFSET = KEY_HASHCODE_OFFSET + 4; @@ -54,7 +52,8 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { private static final Version ourVersion = new Version(CORRECTLY_CLOSED_MAGIC, DIRTY_MAGIC); public PersistentEnumerator(File file, KeyDescriptor dataDescriptor, int initialSize) throws IOException { - super(file, new MappedFileSimpleStorage(file, initialSize), dataDescriptor, initialSize, ourVersion); + super(file, new MappedFileSimpleStorage(file, initialSize), dataDescriptor, initialSize, ourVersion, + new RecordBufferHandler()); } protected void setupEmptyFile() throws IOException { @@ -182,17 +181,12 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { int id = super.writeData(value, hashCode); ++valuesCount; - if (valuesCount % 20000 == 0 && IOStatistics.DEBUG) { + if (valuesCount % 50000 == 0 && IOStatistics.DEBUG) { IOStatistics.dump("Index " + myFile + ", values " + valuesCount + ", storage size:" + myStorage.length()); } return id; } - @Override - protected int recordWriteOffset(byte[] buf) { - return (int)myStorage.length(); - } - private static int hcByte(int hashcode, int byteN) { if (byteN == 0) { return hashcode & FIRST_LEVEL_MASK; @@ -214,16 +208,6 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { return -myStorage.getInt(idx); } - protected byte[] getRecordBuffer() { - return myBuffer; - } - - protected void setupRecord(int hashCode, final int dataOffset, final byte[] buf) { - Bits.putInt(buf, COLLISION_OFFSET, 0); - Bits.putInt(buf, KEY_HASHCODE_OFFSET, hashCode); - Bits.putInt(buf, KEY_REF_OFFSET, dataOffset); - } - private int hashCodeOf(int idx) throws IOException { return myStorage.getInt(idx + KEY_HASHCODE_OFFSET); } @@ -233,8 +217,23 @@ public class PersistentEnumerator extends PersistentEnumeratorBase { return myStorage.getInt(idx + KEY_REF_OFFSET); } - @Override - protected int getRecordSize() { - return RECORD_SIZE; + private static class RecordBufferHandler extends PersistentEnumeratorBase.RecordBufferHandler { + private final byte[] myBuffer = new byte[RECORD_SIZE]; + + protected int recordWriteOffset(PersistentEnumerator enumerator, byte[] buf) { + return (int)enumerator.myStorage.length(); + } + + @Override + byte[] getRecordBuffer(PersistentEnumerator t) { + return myBuffer; + } + + @Override + void setupRecord(PersistentEnumerator enumerator, int hashCode, int dataOffset, byte[] buf) { + Bits.putInt(buf, COLLISION_OFFSET, 0); + Bits.putInt(buf, KEY_HASHCODE_OFFSET, hashCode); + Bits.putInt(buf, KEY_REF_OFFSET, dataOffset); + } } } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java index e8219288c820..0e8ed002d641 100644 --- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java +++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java @@ -23,6 +23,7 @@ import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.containers.SLRUMap; import com.intellij.util.containers.ShareableKey; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -55,7 +56,9 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { private boolean myCorrupted = false; private final MyDataIS myKeyReadStream; private final Version myVersion; + private RecordBufferHandler myRecordHandler; private volatile boolean myDirtyStatusUpdateInProgress; + private Flushable myMarkCleanCallback; public static class Version { private final int correctlyClosedMagic; @@ -67,6 +70,12 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { assert correctlyClosedMagic != dirtyMagic; } } + + public static abstract class RecordBufferHandler { + abstract int recordWriteOffset(T enumerator, byte[] buf); + abstract @NotNull byte[] getRecordBuffer(T enumerator); + abstract void setupRecord(T enumerator, int hashCode, final int dataOffset, final byte[] buf); + } private static class CacheKey implements ShareableKey { public PersistentEnumeratorBase owner; @@ -126,10 +135,12 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } } - public PersistentEnumeratorBase(File file, ISimpleStorage storage, KeyDescriptor dataDescriptor, int initialSize, Version version) throws IOException { + public PersistentEnumeratorBase(File file, ISimpleStorage storage, KeyDescriptor dataDescriptor, int initialSize, + Version version, RecordBufferHandler recordBufferHandler) throws IOException { myDataDescriptor = dataDescriptor; myFile = file; myVersion = version; + myRecordHandler = (RecordBufferHandler)recordBufferHandler; if (!file.exists()) { FileUtil.delete(keystreamFile()); @@ -194,6 +205,18 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { protected abstract void setupEmptyFile() throws IOException; + public final RecordBufferHandler getRecordHandler() { + return myRecordHandler; + } + + public final void setRecordHandler(RecordBufferHandler recordHandler) { + myRecordHandler = recordHandler; + } + + public void setMarkCleanCallback(Flushable markCleanCallback) { + myMarkCleanCallback = markCleanCallback; + } + protected int tryEnumerate(Data value) throws IOException { synchronized (ourEnumerationCache) { final Integer cachedId = ourEnumerationCache.get(sharedKey(value, this)); @@ -293,7 +316,8 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { markDirty(true); final int dataOff = myKeyStorage != null ? (int)myKeyStorage.length() : ((InlineKeyDescriptor)myDataDescriptor).toInt(value); - byte[] buf = prepareEntryRecordBuf(hashCode, dataOff); + final byte[] buf = myRecordHandler.getRecordBuffer(this); + myRecordHandler.setupRecord(this, hashCode, dataOff, buf); if (myKeyStorage != null) { final BufferExposingByteArrayOutputStream bos = new BufferExposingByteArrayOutputStream(); @@ -302,7 +326,7 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { myKeyStorage.put(dataOff, bos.getInternalBuffer(), 0, bos.size()); } - final int pos = recordWriteOffset(buf); + final int pos = myRecordHandler.recordWriteOffset(this, buf); myStorage.put(pos, buf, 0, buf.length); return pos; @@ -312,18 +336,6 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } } - protected abstract int recordWriteOffset(byte[] buf); - - private byte[] prepareEntryRecordBuf(int hashCode, int dataOffset) { - final byte[] buf = getRecordBuffer(); - setupRecord(hashCode, dataOffset, buf); - return buf; - } - - protected abstract byte[] getRecordBuffer(); - - protected abstract void setupRecord(int hashCode, final int dataOffset, final byte[] buf); - protected boolean iterateData(final Processor processor) throws IOException { if (myKeyStorage == null) { throw new UnsupportedOperationException("Iteration over InlineIntegerKeyDescriptors is not supported"); @@ -377,8 +389,6 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { protected abstract int indexToAddr(int idx); - protected abstract int getRecordSize(); - private static class MyDataIS extends DataInputStream { private MyDataIS(ResizeableMappedFile raf) { super(new MyBufferedIS(new MappedFileInputStream(raf, 0, 0))); @@ -492,7 +502,8 @@ abstract class PersistentEnumeratorBase implements Forceable, Closeable { } } - protected void markClean() throws IOException { + private void markClean() throws IOException { + if (myMarkCleanCallback != null) myMarkCleanCallback.flush(); if (!myCorrupted) { myStorage.putInt(0, myVersion.correctlyClosedMagic); myDirty = false; diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java new file mode 100644 index 000000000000..3d1dc843943d --- /dev/null +++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.io; + +import com.intellij.openapi.Forceable; +import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.Nullable; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.util.Collection; + +public class PersistentEnumeratorDelegate implements Closeable, Forceable { + protected final PersistentEnumeratorBase myEnumerator; + + public PersistentEnumeratorDelegate(final File file, KeyDescriptor dataDescriptor, final int initialSize) throws IOException { + myEnumerator = useBtree() ? new PersistentBTreeEnumerator(file, dataDescriptor, initialSize) : + new PersistentEnumerator(file, dataDescriptor, initialSize); + } + + private boolean useBtree() { + String property = System.getProperty("idea.use.btree"); + if (property == null) property = Boolean.toString(SystemInfo.is32Bit); + return "true".equals(property); + } + + @Override + public void close() throws IOException { + myEnumerator.close(); + } + + public boolean isClosed() { + return myEnumerator.isClosed(); + } + + @Override + public boolean isDirty() { + return myEnumerator.isDirty(); + } + + @Override + public void force() { + myEnumerator.force(); + } + + public Data valueOf(int id) throws IOException { + return myEnumerator.valueOf(id); + } + + public int enumerate(Data name) throws IOException { + return myEnumerator.enumerate(name); + } + + public int tryEnumerate(Data name) throws IOException { + return myEnumerator.tryEnumerate(name); + } + + public boolean traverseAllRecords(PersistentEnumeratorBase.RecordsProcessor recordsProcessor) throws IOException { + return myEnumerator.traverseAllRecords(recordsProcessor); + } + + public Collection getAllDataObjects(@Nullable final PersistentEnumeratorBase.DataFilter filter) throws IOException { + return myEnumerator.getAllDataObjects(filter); + } +} diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index 513730fc1391..75b109db745a 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -36,7 +36,7 @@ import java.util.List; * @author Eugene Zhuravlev * Date: Dec 18, 2007 */ -public class PersistentHashMap extends PersistentEnumerator{ +public class PersistentHashMap extends PersistentEnumeratorDelegate{ private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.PersistentHashMap"); private PersistentHashMapValueStorage myValueStorage; private final DataExternalizer myValueExternalizer; @@ -120,7 +120,7 @@ public class PersistentHashMap extends PersistentEnumerator{ public void force() { //System.out.println("Flushing caches: " + myFile.getPath()); synchronized (PersistentHashMap.this) { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { clearAppenderCaches(); } } @@ -133,13 +133,44 @@ public class PersistentHashMap extends PersistentEnumerator{ public PersistentHashMap(final File file, KeyDescriptor keyDescriptor, DataExternalizer valueExternalizer, final int initialSize) throws IOException { super(checkDataFiles(file), keyDescriptor, initialSize); - myParentValueRefOffset = getRecordSize(); + + final PersistentEnumeratorBase.RecordBufferHandler recordHandler = myEnumerator.getRecordHandler(); + myParentValueRefOffset = recordHandler.getRecordBuffer(myEnumerator).length; myRecordBuffer = new byte[myParentValueRefOffset + 8 + 4]; + + myEnumerator.setRecordHandler(new PersistentEnumeratorBase.RecordBufferHandler() { + @Override + int recordWriteOffset(PersistentEnumeratorBase enumerator, byte[] buf) { + return recordHandler.recordWriteOffset(enumerator, buf); + } + + @Override + byte[] getRecordBuffer(PersistentEnumeratorBase enumerator) { + return myRecordBuffer; + } + + @Override + void setupRecord(PersistentEnumeratorBase enumerator, int hashCode, int dataOffset, byte[] buf) { + recordHandler.setupRecord(enumerator, hashCode, dataOffset, buf); + for (int i = myParentValueRefOffset; i < myRecordBuffer.length; i++) { + buf[i] = 0; + } + } + }); + + myEnumerator.setMarkCleanCallback( + new Flushable() { + @Override + public void flush() throws IOException { + myEnumerator.putMetaData(myGarbageSize); + } + } + ); try { myValueExternalizer = valueExternalizer; myValueStorage = PersistentHashMapValueStorage.create(getDataFile(file).getPath()); - myGarbageSize = getMetaData(); + myGarbageSize = myEnumerator.getMetaData(); if (makesSenseToCompact()) { compact(); @@ -150,7 +181,7 @@ public class PersistentHashMap extends PersistentEnumerator{ } catch (Throwable t) { LOG.error(t); - throw new CorruptedException(file); + throw new PersistentEnumerator.CorruptedException(file); } } @@ -159,11 +190,11 @@ public class PersistentHashMap extends PersistentEnumerator{ } public File getBaseFile() { - return myFile; + return myEnumerator.myFile; } private boolean makesSenseToCompact() { - final long fileSize = getDataFile(myFile).length(); + final long fileSize = getDataFile(myEnumerator.myFile).length(); return fileSize > 5 * 1024 * 1024 && myGarbageSize * 2 > fileSize; // file is longer than 5MB and more than 50% of data is garbage } @@ -193,8 +224,8 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized void put(Key key, Value value) throws IOException { - synchronized (ourLock) { - markDirty(true); + synchronized (PersistentEnumerator.ourLock) { + myEnumerator.markDirty(true); myAppendCache.remove(key); final int id = enumerate(key); @@ -217,8 +248,8 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized void appendData(Key key, ValueDataAppender appender) throws IOException { - synchronized (ourLock) { - markDirty(true); + synchronized (PersistentEnumerator.ourLock) { + myEnumerator.markDirty(true); final AppendStream stream = myAppendCache.get(key); appender.append(stream); @@ -230,9 +261,9 @@ public class PersistentHashMap extends PersistentEnumerator{ * {@link #processKeysWithExistingMapping(com.intellij.util.Processor)} to process only keys with existing mappings */ public synchronized boolean processKeys(Processor processor) throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { myAppendCache.clear(); - return iterateData(processor); + return myEnumerator.iterateData(processor); } } @@ -243,8 +274,8 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized boolean processKeysWithExistingMapping(Processor processor) throws IOException { - synchronized (ourLock) { - return processAllDataObject(processor, new DataFilter() { + synchronized (PersistentEnumerator.ourLock) { + return myEnumerator.processAllDataObject(processor, new PersistentEnumerator.DataFilter() { public boolean accept(final int id) { return readValueId(id).address != NULL_ADDR; } @@ -253,21 +284,21 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized Value get(Key key) throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); - if (id == NULL_ID) { + if (id == PersistentEnumerator.NULL_ID) { return null; } final HeaderRecord header = readValueId(id); - if (header.address == NULL_ID) { + if (header.address == PersistentEnumerator.NULL_ID) { return null; } byte[] data = new byte[header.size]; long newAddress = myValueStorage.readBytes(header.address, data); if (newAddress != header.address) { - markDirty(true); + myEnumerator.markDirty(true); header.address = newAddress; updateValueId(id, header); myGarbageSize += header.size; @@ -284,25 +315,25 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized boolean containsMapping(Key key) throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); - if (id == NULL_ID) { + if (id == PersistentEnumerator.NULL_ID) { return false; } - return readValueId(id).address != NULL_ID; + return readValueId(id).address != PersistentEnumerator.NULL_ID; } } public synchronized void remove(Key key) throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); - if (id == NULL_ID) { + if (id == PersistentEnumerator.NULL_ID) { return; } - markDirty(true); + myEnumerator.markDirty(true); final HeaderRecord record = readValueId(id); myGarbageSize += record.size; @@ -312,16 +343,11 @@ public class PersistentHashMap extends PersistentEnumerator{ } public final synchronized void markDirty() throws IOException { - markDirty(true); - } - - protected void markClean() throws IOException { - putMetaData(myGarbageSize); - super.markClean(); + myEnumerator.markDirty(true); } public synchronized void force() { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { try { clearAppenderCaches(); } @@ -337,7 +363,7 @@ public class PersistentHashMap extends PersistentEnumerator{ } public synchronized void close() throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { try { myAppendCacheFlusher.stop(); myAppendCache.clear(); @@ -351,13 +377,13 @@ public class PersistentHashMap extends PersistentEnumerator{ // made public for tests public synchronized void compact() throws IOException { - synchronized (ourLock) { + synchronized (PersistentEnumerator.ourLock) { final long now = System.currentTimeMillis(); - final String newPath = getDataFile(myFile).getPath() + ".new"; + final String newPath = getDataFile(myEnumerator.myFile).getPath() + ".new"; final PersistentHashMapValueStorage newStorage = PersistentHashMapValueStorage.create(newPath); myValueStorage.switchToCompactionMode(); - traverseAllRecords(new RecordsProcessor() { + traverseAllRecords(new PersistentEnumerator.RecordsProcessor() { public boolean process(final int keyId) throws IOException { final HeaderRecord record = readValueId(keyId); if (record.address != NULL_ADDR) { @@ -373,38 +399,25 @@ public class PersistentHashMap extends PersistentEnumerator{ myValueStorage.dispose(); newStorage.dispose(); - FileUtil.rename(new File(newPath), getDataFile(myFile)); + FileUtil.rename(new File(newPath), getDataFile(myEnumerator.myFile)); - myValueStorage = PersistentHashMapValueStorage.create(getDataFile(myFile).getPath()); - LOG.info("Compacted " + myFile.getPath() + " in " + (System.currentTimeMillis() - now) + "ms."); + myValueStorage = PersistentHashMapValueStorage.create(getDataFile(myEnumerator.myFile).getPath()); + LOG.info("Compacted " + myEnumerator.myFile.getPath() + " in " + (System.currentTimeMillis() - now) + "ms."); myGarbageSize = 0; - putMetaData(0); + myEnumerator.putMetaData(0); } } private HeaderRecord readValueId(final int keyId) { HeaderRecord result = new HeaderRecord(); - result.address = myStorage.getLong(keyId + myParentValueRefOffset); - result.size = myStorage.getInt(keyId + myParentValueRefOffset + 8); + result.address = myEnumerator.myStorage.getLong(keyId + myParentValueRefOffset); + result.size = myEnumerator.myStorage.getInt(keyId + myParentValueRefOffset + 8); return result; } private void updateValueId(final int keyId, HeaderRecord value) { - myStorage.putLong(keyId + myParentValueRefOffset, value.address); - myStorage.putInt(keyId + myParentValueRefOffset + 8, value.size); - } - - @Override - protected byte[] getRecordBuffer() { - return myRecordBuffer; - } - - @Override - protected void setupRecord(final int hashCode, final int dataOffset, final byte[] buf) { - super.setupRecord(hashCode, dataOffset, buf); - for (int i = myParentValueRefOffset; i < myRecordBuffer.length; i++) { - buf[i] = 0; - } + myEnumerator.myStorage.putLong(keyId + myParentValueRefOffset, value.address); + myEnumerator.myStorage.putInt(keyId + myParentValueRefOffset + 8, value.size); } private static class HeaderRecord { diff --git a/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java index 1ebfcf642894..a5b38e92f721 100644 --- a/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java @@ -20,7 +20,7 @@ import com.intellij.util.containers.SLRUMap; import java.io.File; import java.io.IOException; -public class PersistentStringEnumerator extends PersistentEnumerator{ +public class PersistentStringEnumerator extends PersistentEnumeratorDelegate{ private final SLRUMap myIdToStringCache; private final SLRUMap myHashcodeToIdCache; @@ -70,20 +70,13 @@ public class PersistentStringEnumerator extends PersistentEnumerator{ myHashcodeToIdCache.put(value.hashCode(), enumerate); } } - return enumerate; - } - - @Override - protected int enumerateImpl(String value, boolean saveNewValue) throws IOException { - int idx = super.enumerateImpl(value, saveNewValue); if (myIdToStringCache != null) { synchronized (myIdToStringCache) { - myIdToStringCache.put(idx, value); + myIdToStringCache.put(enumerate, value); } } - - return idx; + return enumerate; } @Override @@ -98,25 +91,8 @@ public class PersistentStringEnumerator extends PersistentEnumerator{ } @Override - protected void markCorrupted() { - super.markCorrupted(); - - if (myIdToStringCache != null) { - synchronized (myIdToStringCache) { - myIdToStringCache.clear(); - } - } - - if (myHashcodeToIdCache != null) { - synchronized (myHashcodeToIdCache) { - myHashcodeToIdCache.clear(); - } - } - } - - @Override - protected void doClose() throws IOException { - super.doClose(); + public void close() throws IOException { + super.close(); if (myIdToStringCache != null) { synchronized (myIdToStringCache) { From 150cb5e967099f20ec81236bbd9a9a1124f04efa Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Aug 2011 18:23:05 +0400 Subject: [PATCH 49/77] common factor for statistics --- platform/util/src/com/intellij/util/io/IOStatistics.java | 3 ++- .../src/com/intellij/util/io/PersistentBTreeEnumerator.java | 2 +- .../util/src/com/intellij/util/io/PersistentEnumerator.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/IOStatistics.java b/platform/util/src/com/intellij/util/io/IOStatistics.java index 883c7f0e6b28..82a0a152ec13 100644 --- a/platform/util/src/com/intellij/util/io/IOStatistics.java +++ b/platform/util/src/com/intellij/util/io/IOStatistics.java @@ -5,7 +5,8 @@ import com.intellij.openapi.diagnostic.Logger; class IOStatistics { static final boolean DEBUG = System.getProperty("io.access.debug") != null; static final int MIN_IO_TIME_TO_REPORT = 100; - public static final Logger LOG = Logger.getInstance("#com.intellij.io.IOStatistics"); + static final Logger LOG = Logger.getInstance("#com.intellij.io.IOStatistics"); + static final int KEYS_FACTOR = 50000; static void dump(String msg) { LOG.info(msg); diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index a45ea6ae409a..2def302f2331 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -302,7 +302,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase { int id = super.writeData(value, hashCode); ++valuesCount; - if (valuesCount % 50000 == 0 && IOStatistics.DEBUG) { + if (valuesCount % IOStatistics.KEYS_FACTOR == 0 && IOStatistics.DEBUG) { IOStatistics.dump("Index " + myFile + ", values " + valuesCount + ", storage size:" + myStorage.length()); } return id; From a0e3a54a60f62ce855c6aac3778436f6523715c0 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 5 Aug 2011 21:55:58 +0200 Subject: [PATCH 50/77] more assertions --- .../intellij/openapi/util/RecursionManager.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index b2ee9a918824..214e7c720416 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.util; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.reference.SoftReference; import com.intellij.util.containers.SoftHashMap; import org.jetbrains.annotations.NonNls; @@ -46,6 +47,7 @@ import java.util.Map; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class RecursionManager { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.RecursionManager"); private static final Object NULL = new Object(); private static final ThreadLocal ourStamp = new ThreadLocal() { @Override @@ -114,11 +116,17 @@ public class RecursionManager { checkDepth("1"); + int sizeBefore = progressMap.size(); progressMap.put(realKey, ourStamp.get()); ourDepth.set(ourDepth.get() + 1); checkDepth("2"); + int sizeAfter = progressMap.size(); + if (sizeAfter != sizeBefore + 1) { + LOG.error("Key doesn't lead to the map size increase: " + sizeBefore + " " + sizeAfter + " " + key); + } + int startStamp = ourMemoizationStamp.get(); try { @@ -131,9 +139,17 @@ public class RecursionManager { return result; } finally { + if (sizeAfter != progressMap.size()) { + LOG.error("Map size changed: " + progressMap.size() + " " + sizeAfter + " " + key); + } + ourDepth.set(ourDepth.get() - 1); Integer value = progressMap.remove(realKey); + if (sizeBefore != progressMap.size()) { + LOG.error("Map size doesn't decrease: " + progressMap.size() + " " + sizeBefore + " " + key); + } + if (value == null) { throw new AssertionError(key + " has changed its equals/hashCode"); } From fe816d1e242b5c356866b3d3cf80310a7c9271a7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 5 Aug 2011 21:10:55 +0400 Subject: [PATCH 51/77] GitRepositoryManager implement VfsListener instead of GitRootsListener GitRootsListener is called in more cases, than needed, and is not called, when a root is removed. --- .../src/git4idea/repo/GitRepositoryManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java index aafac9e7e8c3..cdaafed03226 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java @@ -21,10 +21,10 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsListener; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import git4idea.GitVcs; -import git4idea.vfs.GitRootsListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,7 +35,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * GitRepositoryManager initializes and stores {@link GitRepository GitRepositories} for Git roots defined in the project. * @author Kirill Likhodedov */ -public final class GitRepositoryManager extends AbstractProjectComponent implements Disposable, GitRootsListener { +public final class GitRepositoryManager extends AbstractProjectComponent implements Disposable, VcsListener { private final GitVcs myVcs; private final ProjectLevelVcsManager myVcsManager; @@ -58,7 +58,7 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme @Override public void initComponent() { - myVcs.addGitRootsListener(this); + myProject.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, this); Disposer.register(myProject, this); } @@ -138,7 +138,7 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme // note: we are not calling this method during the project startup - it is called anyway by the GitRootTracker @Override - public void gitRootsChanged() { + public void directoryMappingChanged() { try { REPO_LOCK.writeLock().lock(); final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(myVcs); @@ -157,7 +157,7 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme } } finally { - REPO_LOCK.writeLock().unlock(); + REPO_LOCK.writeLock().unlock(); } } From 99ff5b40d42340f3696c47898f79130acb36c83f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 6 Aug 2011 12:36:58 +0400 Subject: [PATCH 52/77] IDEA-59835 Add .git/ to watch roots * Move "watching" stuff from GitRepositoryFiles to GitRepositoryUpdater. * Add .git/ as a watch root => no need to getChildren(). --- .../git4idea/src/git4idea/repo/GitRepositoryFiles.java | 4 ---- .../git4idea/src/git4idea/repo/GitRepositoryUpdater.java | 9 ++++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java index 806133e6733a..8225ff3039e9 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java @@ -45,10 +45,6 @@ public class GitRepositoryFiles { // add .git/ and .git/refs/heads to the VFS VirtualFile gitDir = root.findChild(".git"); assert gitDir != null; - gitDir.getChildren(); - final VirtualFile refsHeadsDir = gitDir.findFileByRelativePath("refs/heads"); - assert refsHeadsDir != null; - refsHeadsDir.getChildren(); // save paths of the files, that we will watch String gitDirPath = GitFileUtils.stripFileProtocolPrefix(gitDir.getPath()); diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java index 9852cac2fce4..2368989733a8 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java @@ -17,6 +17,7 @@ package git4idea.repo; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; @@ -38,7 +39,13 @@ final class GitRepositoryUpdater implements Disposable, BulkFileListener { GitRepositoryUpdater(GitRepository repository) { myRepository = repository; - myRepositoryFiles = GitRepositoryFiles.getInstance(repository.getRoot()); + VirtualFile root = repository.getRoot(); + + VirtualFile gitDir = root.findChild(".git"); + assert gitDir != null; + LocalFileSystem.getInstance().addRootToWatch(gitDir.getPath(), true); + + myRepositoryFiles = GitRepositoryFiles.getInstance(root); myMessageBusConnection = repository.getProject().getMessageBus().connect(); myMessageBusConnection.subscribe(VirtualFileManager.VFS_CHANGES, this); } From 0b5f33ad43d5014dea70f1f1334ee51dd78ad04e Mon Sep 17 00:00:00 2001 From: peter Date: Sat, 6 Aug 2011 11:12:15 +0200 Subject: [PATCH 53/77] fix FlexCssCompletionTest --- .../codeInsight/completion/BasicToClassNameDelegator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java index 32414a444ef6..11fe1b25cc70 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/BasicToClassNameDelegator.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.StdLanguages; -import com.intellij.lang.xml.XMLLanguage; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -35,7 +34,7 @@ public class BasicToClassNameDelegator extends AbstractBasicToClassNameDelegator return JavaCompletionContributor.isClassNamePossible(position); } - return file.getLanguage() instanceof XMLLanguage; + return file.getLanguage().isKindOf(StdLanguages.XML); } @Override From 3a7b126fc4fcc2894e8db9863a004acc89037991 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 6 Aug 2011 19:05:56 +0400 Subject: [PATCH 54/77] Messages: fixed swapped message<->title --- .../platform-api/src/com/intellij/openapi/ui/Messages.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index fae5466b4425..1d500eb5893a 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -213,7 +213,7 @@ public class Messages { */ public static int showYesNoDialog(Project project, String message, String title, String yesText, String noText, @Nullable Icon icon) { if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { - return MacMessages.showYesNoDialog(message, title, yesText, noText, WindowManager.getInstance().suggestParentWindow(project)); + return MacMessages.showYesNoDialog(title, message, yesText, noText, WindowManager.getInstance().suggestParentWindow(project)); } return showDialog(project, message, title, new String[]{yesText, noText}, 0, icon); @@ -224,7 +224,7 @@ public class Messages { */ public static int showYesNoDialog(Project project, String message, String title, @Nullable Icon icon) { if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { - return MacMessages.showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); + return MacMessages.showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, WindowManager.getInstance().suggestParentWindow(project)); } return showYesNoDialog(project, message, title, YES_BUTTON, NO_BUTTON, icon); @@ -235,7 +235,7 @@ public class Messages { */ public static int showYesNoDialog(Component parent, String message, String title, @Nullable Icon icon) { if (SystemInfo.isMac && !isApplicationInUnitTestOrHeadless()) { - return MacMessages.showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent)); + return MacMessages.showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent)); } return showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon); From bd7da8df79bdb7d1061ba5ad03759db4f7952f88 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 6 Aug 2011 17:29:47 +0200 Subject: [PATCH 55/77] IDEA-39600 (Import into CVS dialog: Select directory to import into: expanding tree nodes with keyboard moves focus off the tree panel) --- .../cvsSupport2/cvsBrowser/CvsElement.java | 20 ++++++++++++------- .../cvsSupport2/cvsBrowser/CvsTree.java | 11 +++++----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsElement.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsElement.java index 9100c5dc51c0..7ee00f638073 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsElement.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -20,6 +20,7 @@ import com.intellij.cvsSupport2.ui.CvsTabbedWindow; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Alarm; import javax.swing.*; @@ -124,7 +125,8 @@ public class CvsElement extends DefaultMutableTreeNode implements CvsTabbedWindo getModel().insertNodeInto(loadingNode, this, 0); myLoading = true; - myModel.getCvsTree().getTree().setEnabled(false); + final CvsTree cvsTree = myModel.getCvsTree(); + cvsTree.setEnabled(false); myLoadingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { myDataProvider.fillContentFor(CvsElement.this, myProject, new MyGetContentCallback(loadingNode)); @@ -142,7 +144,7 @@ public class CvsElement extends DefaultMutableTreeNode implements CvsTabbedWindo } }; myPeriodAlarm.addRequest(periodRequest, 200); - myModel.getCvsTree().addListener(this); + cvsTree.addListener(this); } return children; @@ -239,20 +241,24 @@ public class CvsElement extends DefaultMutableTreeNode implements CvsTabbedWindo remove(myLoadingNode); } getModel().reload(CvsElement.this); - getModel().getCvsTree().getTree().expandPath(new TreePath(getModel().getPathToRoot(CvsElement.this))); + final Tree tree = getModel().getCvsTree().getTree(); + final TreePath path = new TreePath(getModel().getPathToRoot(CvsElement.this)); + tree.expandPath(path); + tree.setSelectionPath(path); } }); } public void finished() { if (getParent() == null) { - getModel().selectRoot(); + myModel.selectRoot(); } - myModel.getCvsTree().removeListener(this); + final CvsTree cvsTree = myModel.getCvsTree(); + cvsTree.removeListener(this); myLoading = false; myPeriodAlarm.cancelAllRequests(); - myModel.getCvsTree().getTree().setEnabled(true); + cvsTree.getTree().setEnabled(true); myLoadingThreadFuture = null; SwingUtilities.invokeLater(new Runnable() { public void run() { diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java index a89049e6564c..ea9e2d72c067 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -77,8 +77,8 @@ public class CvsTree extends JPanel implements CvsTabbedWindow.DeactivateListene private void setCurrentSelection(TreePath[] paths) { ArrayList selection = new ArrayList(); if (paths != null) { - for (int i = 0; i < paths.length; i++) { - Object selectedObject = paths[i].getLastPathComponent(); + for (TreePath path : paths) { + Object selectedObject = path.getLastPathComponent(); if (!(selectedObject instanceof CvsElement)) continue; CvsElement cvsElement = (CvsElement)selectedObject; if (cvsElement.getElementPath().equals(".") && (!myAllowRootSelection)) continue; @@ -91,8 +91,7 @@ public class CvsTree extends JPanel implements CvsTabbedWindow.DeactivateListene private CvsElement createRoot(Project project) { String rootName = myCvsRootConfiguration.toString(); - CvsElement result = CvsElementFactory.FOLDER_ELEMENT_FACTORY - .createElement(rootName, myCvsRootConfiguration, project); + CvsElement result = CvsElementFactory.FOLDER_ELEMENT_FACTORY.createElement(rootName, myCvsRootConfiguration, project); result.setName(rootName); result.setDataProvider(new RootDataProvider(myCvsRootConfiguration, myShowFiles, myShowModules)); result.setPath("."); @@ -145,7 +144,7 @@ public class CvsTree extends JPanel implements CvsTabbedWindow.DeactivateListene myTree.requestFocus(); } - class AlwaysNotificatedObservable extends Observable{ + static class AlwaysNotificatedObservable extends Observable{ public void notifyObservers(Object arg) { setChanged(); super.notifyObservers(arg); From 87a56ed9efb70f7935d82e91e1f8363d36b37a66 Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Fri, 5 Aug 2011 21:37:47 +0400 Subject: [PATCH 56/77] minor cleanup --- .../src/com/intellij/diagnostic/GroupedLogMessage.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java b/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java index 2570b35688c0..39752c247c09 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java @@ -30,10 +30,9 @@ public class GroupedLogMessage extends AbstractMessage { } public String getThrowableText() { - StringBuffer result = new StringBuffer(); - for (int i = 0; i < myMessages.size(); i++) { - AbstractMessage each = myMessages.get(i); - result.append(each.getThrowableText() + "\n\n\n"); + StringBuilder result = new StringBuilder(); + for (AbstractMessage each : myMessages) { + result.append(each.getThrowableText()).append("\n\n\n"); } return result.toString(); } From 5377c8c8a8347ce4c9543a301e8bd1a22a046302 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sun, 7 Aug 2011 22:03:46 +0200 Subject: [PATCH 57/77] Analyze Stacktrace understands output from ThreadMXBean (IDEA-22189) --- .../src/com/intellij/unscramble/ThreadDumpParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java index 1e07fef6f831..63fa6fe01b0d 100644 --- a/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java +++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; * @author yole */ public class ThreadDumpParser { - private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+prio=\\d+ tid=[^\\s]+ nid=[^\\s]+ ([^\\[]+)"); + private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+(prio=\\d+ tid=[^\\s]+ nid=[^\\s]+|Id=\\d+) ([^\\[]+)"); private static final Pattern ourThreadStatePattern = Pattern.compile("java\\.lang\\.Thread\\.State: (.+) \\((.+)\\)"); private static final Pattern ourThreadStatePattern2 = Pattern.compile("java\\.lang\\.Thread\\.State: (.+)"); private static final Pattern ourWaitingForLockPattern = Pattern.compile("- waiting (on|to lock) <(.+)>"); @@ -185,7 +185,7 @@ public class ThreadDumpParser { private static ThreadState tryParseThreadStart(final String line) { Matcher m = ourThreadStartPattern.matcher(line); if (m.find()) { - final ThreadState state = new ThreadState(m.group(1), m.group(2)); + final ThreadState state = new ThreadState(m.group(1), m.group(3)); if (line.contains(" daemon ")) { state.setDaemon(true); } From e54d37bb191b1147d625be5e610d0c26f7841e82 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sun, 7 Aug 2011 22:12:43 +0200 Subject: [PATCH 58/77] accept spaces before thread start marker (IDEA-21322) --- .../java-impl/src/com/intellij/unscramble/ThreadDumpParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java index 63fa6fe01b0d..809077130dbf 100644 --- a/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java +++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpParser.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; * @author yole */ public class ThreadDumpParser { - private static final Pattern ourThreadStartPattern = Pattern.compile("^\"(.+)\".+(prio=\\d+ tid=[^\\s]+ nid=[^\\s]+|Id=\\d+) ([^\\[]+)"); + private static final Pattern ourThreadStartPattern = Pattern.compile("^\\s*\"(.+)\".+(prio=\\d+ tid=[^\\s]+ nid=[^\\s]+|Id=\\d+) ([^\\[]+)"); private static final Pattern ourThreadStatePattern = Pattern.compile("java\\.lang\\.Thread\\.State: (.+) \\((.+)\\)"); private static final Pattern ourThreadStatePattern2 = Pattern.compile("java\\.lang\\.Thread\\.State: (.+)"); private static final Pattern ourWaitingForLockPattern = Pattern.compile("- waiting (on|to lock) <(.+)>"); From 43dde86b5f2da0fb810c07ee152327d1322722ae Mon Sep 17 00:00:00 2001 From: Maxim Mossienko Date: Mon, 8 Aug 2011 03:05:03 +0400 Subject: [PATCH 59/77] no btree by default --- .../src/com/intellij/util/io/PersistentEnumeratorDelegate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java index 3d1dc843943d..4472091ab38d 100644 --- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java +++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java @@ -34,7 +34,7 @@ public class PersistentEnumeratorDelegate implements Closeable, Forceable private boolean useBtree() { String property = System.getProperty("idea.use.btree"); - if (property == null) property = Boolean.toString(SystemInfo.is32Bit); + //if (property == null) property = Boolean.toString(SystemInfo.is32Bit); return "true".equals(property); } From 36f48595f6345021ac62e7e72c5151ab1ddda7a3 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 8 Aug 2011 11:23:33 +0400 Subject: [PATCH 60/77] new toolwindow shortcuts --- .../platform-impl/src/com/intellij/ide/actions/Switcher.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 23a78496207c..e979e9bf666e 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -92,12 +92,13 @@ public class Switcher extends AnAction implements DumbAware { static { TW_KEYMAP.put("Messages", 0); TW_KEYMAP.put("Project", 1); - TW_KEYMAP.put("Commander", 2); + TW_KEYMAP.put("Favorites", 2); TW_KEYMAP.put("Find", 3); TW_KEYMAP.put("Run", 4); TW_KEYMAP.put("Debug", 5); TW_KEYMAP.put("TODO", 6); TW_KEYMAP.put("Structure", 7); + TW_KEYMAP.put("Hierarchy", 8); TW_KEYMAP.put("Changes", 9); IdeEventQueue.getInstance().addPostprocessor(new IdeEventQueue.EventDispatcher() { From 93daa28c5d5ecbf7c98b7b905adc428e9c565f34 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 8 Aug 2011 09:44:14 +0200 Subject: [PATCH 61/77] Local History: more logging --- .../history/core/ChangeListStorageImpl.java | 18 +++++++++++++----- .../history/core/LocalHistoryStorage.java | 8 ++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java index c6e69d74e360..db5ca3d6e47a 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java @@ -26,6 +26,7 @@ import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; @@ -130,7 +131,7 @@ public class ChangeListStorageImpl implements ChangeListStorage { "Local History is broken", message + "
" + "
" + - "Please attach log files from " +logFile + "
" + + "Please attach log files from " + logFile + "
" + "to the YouTrack issue", NotificationType.ERROR, new NotificationListener() { @@ -171,13 +172,15 @@ public class ChangeListStorageImpl implements ChangeListStorage { String message = null; if (prevId != 0) { try { + Pair prevOS = myStorage.getOffsetAndSize(prevId); long prevRecordTimestamp = myStorage.getTimestamp(prevId); int lastRecord = myStorage.getLastRecord(); + Pair lastOS = myStorage.getOffsetAndSize(lastRecord); long lastRecordTimestamp = myStorage.getTimestamp(lastRecord); - message = "invalid record is: " + prevId + message = "invalid record is: " + prevId + " offset: " + prevOS.first + " size: " + prevOS.second + " (created " + DateFormat.getDateTimeInstance().format(prevRecordTimestamp) + ") " - + "last record is: " + lastRecord + + "last record is: " + lastRecord + " offset: " + lastOS.first + " size: " + lastOS.second + " (created " + DateFormat.getDateTimeInstance().format(lastRecordTimestamp) + ")"; } catch (Exception e1) { @@ -216,9 +219,11 @@ public class ChangeListStorageImpl implements ChangeListStorage { myStorage.setLastId(myLastId); myStorage.force(); - LocalHistoryLog.LOG.info("Block was written: " + id); + // todo remove this when bug is found + Pair os = myStorage.getOffsetAndSize(id); + LocalHistoryLog.LOG.info("Block was written: " + id + " offset: " + os.first + " size: " + os.second); - // todo remove this check when buf is found + // todo remove this when bug is found if (ApplicationManagerEx.getApplicationEx().isInternal()) { try { doReadBlock(id); @@ -246,6 +251,9 @@ public class ChangeListStorageImpl implements ChangeListStorage { while (eachBlockId != 0) { processor.consume(doReadBlock(eachBlockId).changeSet); + // todo remove this when bug is found + Pair os = myStorage.getOffsetAndSize(eachBlockId); + LocalHistoryLog.LOG.info("Block was deleted: " + eachBlockId + " offset: " + os.first + " size: " + os.second); eachBlockId = doReadPrevSafely(eachBlockId, recursionGuard); } myStorage.deleteRecordsUpTo(firstObsoleteId); diff --git a/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryStorage.java b/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryStorage.java index 2ff826f2ab92..d9565154ec99 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryStorage.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryStorage.java @@ -16,6 +16,7 @@ package com.intellij.history.core; import com.intellij.openapi.util.Clock; +import com.intellij.openapi.util.Pair; import com.intellij.util.io.PagePool; import com.intellij.util.io.storage.AbstractRecordsTable; import com.intellij.util.io.storage.AbstractStorage; @@ -91,6 +92,13 @@ public class LocalHistoryStorage extends AbstractStorage { } } + public Pair getOffsetAndSize(int id) { + synchronized (myLock) { + return Pair.create(myRecordsTable.getAddress(id), myRecordsTable.getSize(id)); + } + + } + public int createNextRecord() throws IOException { synchronized (myLock) { LocalHistoryRecordsTable table = (LocalHistoryRecordsTable)myRecordsTable; From cdfff644a943e2d3f9cf992fbb04154c542fd746 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 8 Aug 2011 12:03:53 +0400 Subject: [PATCH 62/77] open in browser: 'shift' modifier allows to open local URL for all providers; dumb aware --- .../src/META-INF/XmlPlugin.xml | 3 +- .../browsers/HtmlWebBrowserUrlProvider.java | 51 --------- .../ide/browsers/OpenFileInBrowserAction.java | 50 +++++---- .../browsers/impl/WebBrowserServiceImpl.java | 102 ++++++++++++++++++ .../src/com/intellij/xml/util/HtmlUtil.java | 2 +- .../ide/browsers/WebBrowserService.java | 39 +++++++ .../ide/browsers/WebBrowserUrlProvider.java | 20 +++- .../ide/browsers/WebBrowserUrlProviders.java | 4 +- 8 files changed, 197 insertions(+), 74 deletions(-) delete mode 100644 xml/impl/src/com/intellij/ide/browsers/HtmlWebBrowserUrlProvider.java create mode 100644 xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java create mode 100644 xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 7ec6829ce90d..c8e36eb35968 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -286,7 +286,8 @@ - + diff --git a/xml/impl/src/com/intellij/ide/browsers/HtmlWebBrowserUrlProvider.java b/xml/impl/src/com/intellij/ide/browsers/HtmlWebBrowserUrlProvider.java deleted file mode 100644 index adc2543d664b..000000000000 --- a/xml/impl/src/com/intellij/ide/browsers/HtmlWebBrowserUrlProvider.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ide.browsers; - -import com.intellij.lang.Language; -import com.intellij.lang.html.HTMLLanguage; -import com.intellij.lang.xhtml.XHTMLLanguage; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; - -/** - * @author spleaner - */ -public class HtmlWebBrowserUrlProvider extends WebBrowserUrlProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.HtmlWebBrowserUrlProvider"); - - @NotNull - public String getUrl(@NotNull final PsiElement element, final boolean shiftDown) throws Exception { - final PsiFile file = element instanceof PsiFile ? (PsiFile) element : element.getContainingFile(); - final VirtualFile virtualFile = file.getVirtualFile(); - LOG.assertTrue(virtualFile != null); - return virtualFile.getUrl(); - } - - @Override - public boolean canHandleElement(@NotNull final PsiElement element) { - final PsiFile file = element instanceof PsiFile ? (PsiFile) element : element.getContainingFile(); - return file != null && isHtmlFile(file); - } - - protected static boolean isHtmlFile(@NotNull final PsiFile file) { - final Language language = file.getLanguage(); - return language instanceof HTMLLanguage || language instanceof XHTMLLanguage; - } -} diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java index 364a9717eafe..2326b1ce4af2 100644 --- a/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/OpenFileInBrowserAction.java @@ -1,6 +1,7 @@ package com.intellij.ide.browsers; import com.intellij.ide.BrowserUtil; +import com.intellij.ide.browsers.impl.WebBrowserServiceImpl; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -8,6 +9,9 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiFile; import com.intellij.xml.XmlBundle; +import com.intellij.xml.util.HtmlUtil; + +import java.awt.event.InputEvent; public class OpenFileInBrowserAction extends DumbAwareAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.OpenFileInBrowserAction"); @@ -17,23 +21,31 @@ public class OpenFileInBrowserAction extends DumbAwareAction { final PsiFile file = LangDataKeys.PSI_FILE.getData(dataContext); final Presentation presentation = e.getPresentation(); - if (file != null) { + if (file != null && file.getVirtualFile() != null) { presentation.setVisible(true); - final WebBrowserUrlProvider browserUrlProvider = WebBrowserUrlProviders.getProvider(file); - presentation.setEnabled(browserUrlProvider != null); + final WebBrowserUrlProvider browserUrlProvider = WebBrowserServiceImpl.getProvider(file); + final boolean isHtmlFile = HtmlUtil.isHtmlFile(file); + presentation.setEnabled(browserUrlProvider != null || isHtmlFile); + String text = getTemplatePresentation().getText(); + String description = getTemplatePresentation().getDescription(); if (browserUrlProvider != null) { - final String actionText = browserUrlProvider.getOpenInBrowserActionText(file); - if (actionText != null) { - presentation.setText(actionText); + final String customText = browserUrlProvider.getOpenInBrowserActionText(file); + if (customText != null) { + text = customText; } - final String description = browserUrlProvider.getOpenInBrowserActionDescription(file); - if (description != null) { - presentation.setDescription(description); + final String customDescription = browserUrlProvider.getOpenInBrowserActionDescription(file); + if (customDescription != null) { + description = customDescription; + } + if (isHtmlFile) { + description += " (hold Shift to open URL of local file)"; } } + presentation.setText(text); + presentation.setDescription(description); if (ActionPlaces.isPopupPlace(e.getPlace())) { presentation.setVisible(presentation.isEnabled()); } @@ -47,19 +59,19 @@ public class OpenFileInBrowserAction extends DumbAwareAction { final DataContext dataContext = e.getDataContext(); final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext); LOG.assertTrue(psiFile != null); - final WebBrowserUrlProvider provider = WebBrowserUrlProviders.getProvider(psiFile); - if (provider != null) { - try { - final String url = provider.getUrl(psiFile, false); + try { + final InputEvent event = e.getInputEvent(); + final String url = WebBrowserService.getInstance().getUrlToOpen(psiFile, event != null && event.isShiftDown()); + if (url != null) { ApplicationManager.getApplication().saveAll(); BrowserUtil.launchBrowser(url); } - catch (WebBrowserUrlProvider.BrowserException e1) { - Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error")); - } - catch (Exception e1) { - LOG.error(e1); - } + } + catch (WebBrowserUrlProvider.BrowserException e1) { + Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error")); + } + catch (Exception e1) { + LOG.error(e1); } } } diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java new file mode 100644 index 000000000000..53851c1cff5c --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java @@ -0,0 +1,102 @@ +/* + * 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.ide.browsers.impl; + +import com.intellij.ide.browsers.WebBrowserService; +import com.intellij.ide.browsers.WebBrowserUrlProvider; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.impl.http.HttpVirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.xml.util.HtmlUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; + +/** + * @author nik + */ +public class WebBrowserServiceImpl extends WebBrowserService { + @Override + public boolean canOpenInBrowser(@NotNull PsiElement psiElement) { + final PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile(); + return psiFile != null && psiFile.getVirtualFile() != null && getProvider(psiElement) != null; + } + + @Override + @Nullable + public String getUrlToOpen(@NotNull PsiElement psiElement, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException { + final PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile(); + if (psiFile == null) { + return null; + } + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile == null) { + return null; + } + final String localUrl = virtualFile.getUrl(); + if (virtualFile instanceof HttpVirtualFile) { + return localUrl; + } + + if (preferLocalUrl && HtmlUtil.isHtmlFile(psiFile)) { + return localUrl; + } + + final WebBrowserUrlProvider provider = getProvider(psiElement); + if (provider == null) { + return localUrl; + } + try { + return provider.getUrl(psiElement); + } + catch (WebBrowserUrlProvider.BrowserException e) { + if (HtmlUtil.isHtmlFile(psiFile)) { + return localUrl; + } + throw e; + } + } + + @Nullable + public String getUrlToOpen(@NotNull PsiElement psiElement) { + try { + return getUrlToOpen(psiElement, false); + } + catch (WebBrowserUrlProvider.BrowserException e) { + return null; + } + } + + @Nullable + public static WebBrowserUrlProvider getProvider(@Nullable PsiElement element) { + if (element == null) { + return null; + } + + final List allProviders = Arrays.asList(WebBrowserUrlProvider.EP_NAME.getExtensions()); + for (WebBrowserUrlProvider urlProvider : DumbService.getInstance(element.getProject()).filterByDumbAwareness(allProviders)) { + if (urlProvider.canHandleElement(element)) { + return urlProvider; + } + } + + return null; + } +} diff --git a/xml/impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java index 948d6f78b84f..c7e0c3c3b601 100644 --- a/xml/impl/src/com/intellij/xml/util/HtmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java @@ -547,7 +547,7 @@ public class HtmlUtil { return false; } - private static boolean isHtmlFile(final PsiFile file) { + public static boolean isHtmlFile(final PsiFile file) { final Language language = file.getLanguage(); if (language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE) { return true; diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java new file mode 100644 index 000000000000..040d6372fcf6 --- /dev/null +++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java @@ -0,0 +1,39 @@ +/* + * 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.ide.browsers; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author nik + */ +public abstract class WebBrowserService { + public static WebBrowserService getInstance() { + return ServiceManager.getService(WebBrowserService.class); + } + + public abstract boolean canOpenInBrowser(@NotNull PsiElement psiElement); + + @Nullable + public abstract String getUrlToOpen(@NotNull PsiElement psiElement); + + @Nullable + public abstract String getUrlToOpen(@NotNull PsiElement psiElement, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException; + +} diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java index 01a2084c0f0e..117f0ecc70d7 100644 --- a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java +++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java @@ -40,7 +40,25 @@ public abstract class WebBrowserUrlProvider { * Invariant: element has not null containing psi file with not null virtual file */ @NotNull - public abstract String getUrl(@NotNull PsiElement element, boolean shiftDown) throws Exception; + public String getUrl(@NotNull PsiElement element) throws BrowserException { + try { + return getUrl(element, false); + } + catch (BrowserException e) { + throw e; + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * @deprecated override {@link #getUrl(com.intellij.psi.PsiElement)} instead + */ + @NotNull + public String getUrl(@NotNull PsiElement element, boolean shiftDown) throws Exception { + throw new UnsupportedOperationException(); + } /** * Invariant: element has not null containing psi file with not null virtual file diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProviders.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProviders.java index ddc1c2b8252b..b545197945bc 100644 --- a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProviders.java +++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProviders.java @@ -20,6 +20,8 @@ import org.jetbrains.annotations.Nullable; /** * @author spleaner + * + * @deprecated use {@link WebBrowserService} instead */ public class WebBrowserUrlProviders { private WebBrowserUrlProviders() { @@ -30,7 +32,7 @@ public class WebBrowserUrlProviders { if (element == null) { return null; } - + final WebBrowserUrlProvider[] urlProviders = WebBrowserUrlProvider.EP_NAME.getExtensions(); for (WebBrowserUrlProvider urlProvider : urlProviders) { if (urlProvider.canHandleElement(element)) { From 8d956e321b838051bb42e8b2dd880985d781bdad Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Aug 2011 11:58:23 +0400 Subject: [PATCH 63/77] show formatting blocks CheckBox added --- .../internal/psiView/PsiViewerDialog.form | 17 ++++++++++-- .../internal/psiView/PsiViewerDialog.java | 26 ++++++++++++++++--- .../internal/psiView/PsiViewerSettings.java | 1 + 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.form b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.form index 4020064780e3..96be700ca69e 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.form +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.form @@ -155,12 +155,14 @@
- + - + + + @@ -246,6 +248,17 @@ + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java index 128e708f2ee3..d7abfff7b943 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java @@ -119,7 +119,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp private Tree myBlockTree; private JPanel myBlockStructurePanel; private JSplitPane myBlockRefSplitPane; - private TitledSeparatorWithMnemonic myTextSeparator; + private JCheckBox myShowBlocksCheckBox; + private TitledSeparatorWithMnemonic myTextSeparator; private TitledSeparatorWithMnemonic myPsiTreeSeparator; private TitledSeparatorWithMnemonic myRefsSeparator; private TitledSeparatorWithMnemonic myBlockTreeSeparator; @@ -233,6 +234,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp final Document document = EditorFactory.getInstance().createDocument(""); editor = (EditorEx)EditorFactory.getInstance().createEditor(document, myProject); } + editor.getSettings().setLineMarkerAreaShown(false); myEditor = editor; init(); if (myCurrentFile != null) { @@ -423,7 +425,20 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp psiTreeStructure.setShowWhiteSpaces(settings.showWhiteSpaces); myShowTreeNodesCheckBox.setSelected(settings.showTreeNodes); psiTreeStructure.setShowTreeNodes(settings.showTreeNodes); - + myShowBlocksCheckBox.setSelected(settings.showBlocks); + myBlockStructurePanel.setVisible(settings.showBlocks); + myShowBlocksCheckBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!myShowBlocksCheckBox.isSelected()) { + settings.blockRefDividerLocation = myBlockRefSplitPane.getDividerLocation(); + } + else { + myBlockRefSplitPane.setDividerLocation(settings.blockRefDividerLocation); + } + myBlockStructurePanel.setVisible(myShowBlocksCheckBox.isSelected()); + myBlockStructurePanel.repaint(); + } + }); myTextPanel.setLayout(new BorderLayout()); myTextPanel.add(myEditor.getComponent(), BorderLayout.CENTER); @@ -747,7 +762,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp } @Nullable - private static Block buildBlocks(@NotNull PsiElement rootElement) { + private Block buildBlocks(@NotNull PsiElement rootElement) { FormattingModelBuilder formattingModelBuilder = LanguageFormatting.INSTANCE.forContext(rootElement); CodeStyleSettings settings = new CodeStyleSettings(); if (formattingModelBuilder != null) { @@ -991,7 +1006,10 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp settings.dialect = myDialectComboBox.isVisible() && selectedDialect != null ? selectedDialect.toString() : ""; settings.textDividerLocation = myTextSplit.getDividerLocation(); settings.treeDividerLocation = myTreeSplit.getDividerLocation(); - settings.blockRefDividerLocation = myBlockRefSplitPane.getDividerLocation(); + settings.showBlocks = myShowBlocksCheckBox.isSelected(); + if( myShowBlocksCheckBox.isSelected()) { + settings.blockRefDividerLocation = myBlockRefSplitPane.getDividerLocation(); + } super.doCancelAction(); } diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerSettings.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerSettings.java index 27f63cf29937..d0cce0d4cd9c 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerSettings.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerSettings.java @@ -36,6 +36,7 @@ public class PsiViewerSettings implements PersistentStateComponent Date: Mon, 8 Aug 2011 14:56:05 +0400 Subject: [PATCH 64/77] IDEA-72929 quickdoc positioning is broken, when invoked without editor --- .../documentation/DocumentationManager.java | 6 +- .../actions/ShowImplementationsAction.java | 3 +- .../ide/util/gotoByName/ChooseByNameBase.java | 2 +- .../ui/popup/PopupPositionManager.java | 115 ++++++++++-------- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 017580f11dec..c5313f80e967 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -62,6 +62,7 @@ import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.content.*; import com.intellij.ui.popup.AbstractPopup; import com.intellij.ui.popup.NotLookupOrSearchCondition; +import com.intellij.ui.popup.PopupPositionManager; import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.util.Alarm; import com.intellij.util.Consumer; @@ -911,10 +912,9 @@ public class DocumentationManager { } void showHint(final JBPopup hint) { - //todo[spleaner] please fix this in PopupPositionManager - //PopupPositionManager.positionPopupInBestPosition(hint, myEditor, true); final Component focusOwner = IdeFocusManager.getInstance(myProject).getFocusOwner(); - hint.showInBestPositionFor(DataManager.getInstance().getDataContext(focusOwner)); + DataContext dataContext = DataManager.getInstance().getDataContext(focusOwner); + PopupPositionManager.positionPopupInBestPosition(hint, null, dataContext); } public void requestFocus() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 8806e04e43d8..fd2e03e5eadc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.hint.ImplementationViewComponent; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.navigation.ImplementationSearcher; import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditor; @@ -194,7 +195,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { .setTitle(title) .createPopup(); - PopupPositionManager.positionPopupInBestPosition(popup, editor, invokedFromEditor); + PopupPositionManager.positionPopupInBestPosition(popup, editor, DataManager.getInstance().getDataContext()); component.setHint(popup, title); myPopupRef = new WeakReference(popup); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 3ff493c744c1..053c9b38f608 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -308,7 +308,7 @@ public abstract class ChooseByNameBase { public void repositionHint() { if (myHint == null || !myHint.isVisible()) return; - PopupPositionManager.positionPopupInBestPosition(myHint, null, true); + PopupPositionManager.positionPopupInBestPosition(myHint, null, null); } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java b/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java index 9994f20503b1..af5d35d334fc 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java @@ -28,7 +28,9 @@ public class PopupPositionManager { private PopupPositionManager() { } - public static void positionPopupInBestPosition(final JBPopup hint, @Nullable final Editor editor, final boolean invokedFromEditor) { + public static void positionPopupInBestPosition(final JBPopup hint, + @Nullable final Editor editor, + @Nullable DataContext dataContext) { final LookupEx lookup = LookupManager.getActiveLookup(editor); if (lookup != null && lookup.getCurrentItem() != null) { new PositionAdjuster(lookup.getComponent()).adjust(hint); @@ -43,38 +45,45 @@ public class PopupPositionManager { return; } - if (invokedFromEditor && editor != null && editor.getComponent().isShowing()) { + final PositionAdjuster positionAdjuster = createPositionAdjuster(); + if (positionAdjuster != null) { + positionAdjuster.adjust(hint); + return; + } + + if (editor != null && editor.getComponent().isShowing()) { hint.showInBestPositionFor(editor); return; } - final PositionAdjuster positionAdjuster = createPositionAdjuster(); - if (positionAdjuster != null) positionAdjuster.adjust(hint); + if (dataContext != null) { + hint.showInBestPositionFor(dataContext); + } } private static Component discoverPopup(final DataKey datakey, Component focusOwner) { if (focusOwner == null) { focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); } - + if (focusOwner == null) return null; - + final DataContext dataContext = DataManager.getInstance().getDataContext(focusOwner); if (dataContext == null) return null; - + final JBPopup popup = datakey.getData(dataContext); if (popup != null && popup.isVisible()) { return popup.getContent(); } - + return null; } - + @Nullable private static PositionAdjuster createPositionAdjuster() { final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); if (focusOwner == null) return null; - + if (focusOwner instanceof JBList) { return new PositionAdjuster(SwingUtilities.getWindowAncestor(focusOwner)); } @@ -84,10 +93,11 @@ public class PopupPositionManager { return new PositionAdjuster2(existing, discoverPopup(LangDataKeys.CHOOSE_BY_NAME_POPUP, focusOwner)); } - final Window window = SwingUtilities.getWindowAncestor(focusOwner); - return window == null ? null : new PositionAdjuster(window); + //final Window window = SwingUtilities.getWindowAncestor(focusOwner); + //return window == null ? null : new PositionAdjuster(window); + return null; } - + private static class PositionAdjuster2 extends PositionAdjuster { private Component myTopComponent; @@ -102,10 +112,10 @@ public class PopupPositionManager { return myTopComponent.getLocationOnScreen().y; } } - + private static class PositionAdjuster { - private static final int GAP = 5; - + private static final int GAP = 5; + private Component myRelativeTo; private Point myRelativeOnScreen; private Rectangle myScreenRect; @@ -115,35 +125,35 @@ public class PopupPositionManager { myRelativeOnScreen = relativeTo.getLocationOnScreen(); myScreenRect = ScreenUtil.getScreenRectangle(myRelativeOnScreen); } - + protected Rectangle positionRight(final Dimension d) { - return new Rectangle(myRelativeOnScreen.x + myRelativeTo.getWidth() + GAP, myRelativeOnScreen.y, d.width, + return new Rectangle(myRelativeOnScreen.x + myRelativeTo.getWidth() + GAP, myRelativeOnScreen.y, d.width, d.height); } - + protected Rectangle positionLeft(final Dimension d) { return new Rectangle(myRelativeOnScreen.x - GAP - d.width, myRelativeOnScreen.y, d.width, d.height); } - + protected Rectangle positionAbove(final Dimension d) { return new Rectangle(myRelativeOnScreen.x, getYForTopPositioning() - GAP - d.height, d.width, d.height); } - + protected Rectangle positionUnder(final Dimension d) { return new Rectangle(myRelativeOnScreen.x, myRelativeOnScreen.y + GAP + myRelativeTo.getHeight(), d.width, d.height); } - + protected int getYForTopPositioning() { return myRelativeOnScreen.y; } - + /** * Try to position: * 1. to the right * 2. to the left * 3. above * 4. under - * + * * @param popup */ public void adjust(final JBPopup popup) { @@ -153,51 +163,53 @@ public class PopupPositionManager { Rectangle r = positionRight(d); if (myScreenRect.contains(r)) { popupRect = r; - } - + } + if (popupRect == null) { r = positionLeft(d); if (myScreenRect.contains(r)) { popupRect = r; } - } - + } + if (popupRect == null) { r = positionAbove(d); if (myScreenRect.contains(r)) { popupRect = r; } - } - + } + if (popupRect == null) { r = positionUnder(d); if (myScreenRect.contains(r)) { popupRect = r; } - } - + } + if (popupRect != null) { if (popup.isVisible()) { popup.setLocation(new Point(r.x, r.y)); - } else { + } + else { final Point p = new Point(r.x - myRelativeOnScreen.x, r.y - myRelativeOnScreen.y); popup.show(new RelativePoint(myRelativeTo, p)); } - } else { + } + else { // ok, popup does not fit, will try to resize it final List boxes = new ArrayList(); // right boxes.add(crop(myScreenRect, new Rectangle(myRelativeOnScreen.x + myRelativeTo.getWidth() + GAP, myRelativeOnScreen.y, myScreenRect.width, myScreenRect.height))); - + // left boxes.add(crop(myScreenRect, new Rectangle(myScreenRect.x, myRelativeOnScreen.y, myRelativeOnScreen.x - myScreenRect.x - GAP, myScreenRect.height))); - + // top boxes.add(crop(myScreenRect, new Rectangle(myRelativeOnScreen.x, myScreenRect.y, myScreenRect.width, getYForTopPositioning() - myScreenRect.y - GAP))); - + // bottom boxes.add(crop(myScreenRect, new Rectangle(myRelativeOnScreen.x, myRelativeOnScreen.y + myRelativeTo.getHeight() + GAP, myScreenRect.width, myScreenRect.height))); @@ -211,44 +223,47 @@ public class PopupPositionManager { }); final Rectangle suitableBox = boxes.get(boxes.size() - 1); - final Rectangle crop = crop(suitableBox, - new Rectangle(suitableBox.x < myRelativeOnScreen.x ? suitableBox.x + suitableBox.width - d.width : - suitableBox.x, suitableBox.y < myRelativeOnScreen.y ? suitableBox.y + suitableBox.height - d.height : suitableBox.y, + final Rectangle crop = crop(suitableBox, + new Rectangle(suitableBox.x < myRelativeOnScreen.x ? suitableBox.x + suitableBox.width - d.width : + suitableBox.x, suitableBox.y < myRelativeOnScreen.y + ? suitableBox.y + suitableBox.height - d.height + : suitableBox.y, d.width, d.height)); popup.setSize(crop.getSize()); if (popup.isVisible()) { popup.setLocation(crop.getLocation()); - } else { + } + else { popup.show(new RelativePoint(myRelativeTo, new Point(crop.getLocation().x - myRelativeOnScreen.x, crop.getLocation().y - myRelativeOnScreen.y))); } } } - + private static Rectangle crop(final Rectangle source, final Rectangle toCrop) { final Rectangle result = new Rectangle(toCrop); if (toCrop.x < source.x) { result.width -= source.x - toCrop.x; result.x = source.x; } - + if (toCrop.y < source.y) { result.height -= source.y - toCrop.y; result.y = source.y; } - + if (result.x + result.width > source.x + source.width) { - result.width = source.x + source.width - result.x; + result.width = source.x + source.width - result.x; } - + if (result.y + result.height > source.y + source.height) { - result.height = source.y + source.height - result.y; + result.height = source.y + source.height - result.y; } return result; } - + protected static Dimension getPopupSize(final JBPopup popup) { Dimension size = null; if (popup instanceof AbstractPopup) { @@ -261,8 +276,8 @@ public class PopupPositionManager { if (size == null) { size = popup.getContent().getPreferredSize(); } - + return size; - } + } } } From c421333913d020a3ff21859baed1e2234d40e023 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 5 Aug 2011 19:48:37 +0400 Subject: [PATCH 65/77] too many range markers in completion --- .../codeInsight/completion/OffsetMap.java | 11 +++++++ .../completion/CodeCompletionHandlerBase.java | 16 +++++++--- .../CompletionProgressIndicator.java | 29 +++++++++++++++---- .../template/impl/TemplateState.java | 1 + 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java index 0aaa29a88fea..9b2291475399 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java @@ -75,6 +75,8 @@ public class OffsetMap { myModified.add(key); } + RangeMarker old = myMap.get(key); + if (old != null) old.dispose(); final RangeMarker marker = myDocument.createRangeMarker(offset, offset); marker.setGreedyToRight(key.isMoveableToRight()); myMap.put(key, marker); @@ -82,6 +84,9 @@ public class OffsetMap { public void removeOffset(OffsetKey key) { myModified.add(key); + RangeMarker old = myMap.get(key); + if (old != null) old.dispose(); + myMap.remove(key); } @@ -101,4 +106,10 @@ public class OffsetMap { public boolean wasModified(OffsetKey key) { return myModified.contains(key); } + + public void dispose() { + for (RangeMarker rangeMarker : myMap.values()) { + rangeMarker.dispose(); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 9ac45d80c11b..c5c853efc7fc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -260,6 +260,8 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { freezeSemaphore.down(); final CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, parameters, this, freezeSemaphore, initContext.getOffsetMap(), hasModifiers); + indicator.addMapToDispose(hostMap); + indicator.addMapToDispose(context.getOffsetMap()); boolean sync = (invokedExplicitly || ApplicationManager.getApplication().isUnitTestMode()) && !CompletionAutoPopupHandler.ourTestingAutopopup; @@ -520,7 +522,8 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap); } }); - } else { + } + else { PsiDocumentManager.getInstance(hostFile.getProject()).commitDocument(hostDocument); doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap); @@ -627,13 +630,18 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { if (!context.getProject().isDisposed()) { runnable.run(); } + indicator.disposeOffsetMaps(); } }; - if (!ApplicationManager.getApplication().isUnitTestMode()) { - ApplicationManager.getApplication().invokeLater(runnable1); - } else { + if (ApplicationManager.getApplication().isUnitTestMode()) { runnable1.run(); } + else { + ApplicationManager.getApplication().invokeLater(runnable1); + } + } + else { + indicator.disposeOffsetMaps(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index d08349197f0b..d35f238a94ed 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -60,6 +60,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; +import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -71,6 +72,7 @@ import java.awt.event.KeyEvent; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; /** @@ -94,7 +96,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private final CopyOnWriteArrayList>> myRestartingPrefixConditions = ContainerUtil.createEmptyCOWList(); private final LookupAdapter myLookupListener = new LookupAdapter() { public void itemSelected(LookupEvent event) { - finishCompletionProcess(); + finishCompletionProcess(false); LookupElement item = event.getItem(); if (item == null) return; @@ -108,13 +110,14 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement public void lookupCanceled(final LookupEvent event) { - finishCompletionProcess(); + finishCompletionProcess(true); } }; private volatile int myCount; private final ConcurrentHashMap myItemSorters = new ConcurrentHashMap(TObjectHashingStrategy.IDENTITY); private final LinkedList myDelayQueue = new LinkedList(); private volatile boolean myProcessingDelayedActions; + private final Set myMapsToDispose = new THashSet(); public CompletionProgressIndicator(final Editor editor, CompletionParameters parameters, CodeCompletionHandlerBase handler, Semaphore freezeSemaphore, final OffsetMap offsetMap, boolean hasModifiers) { @@ -134,6 +137,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement ApplicationManager.getApplication().assertIsDispatchThread(); registerItself(); + addMapToDispose(offsetMap); if (ApplicationManager.getApplication().isUnitTestMode()) { return; @@ -407,7 +411,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement Lookup lookup = LookupManager.getActiveLookup(myEditor); LOG.assertTrue(lookup == myLookup, lookup + "; " + this); myLookup.removeLookupListener(myLookupListener); - finishCompletionProcess(); + finishCompletionProcess(true); CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass()); if (hideLookup) { @@ -415,7 +419,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } - private void finishCompletionProcess() { + private void finishCompletionProcess(boolean disposeOffsetMap) { cancel(); ApplicationManager.getApplication().assertIsDispatchThread(); @@ -427,13 +431,23 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement CompletionServiceImpl.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class, CompletionPhase.Restarted.class); CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); + if (disposeOffsetMap) { + disposeOffsetMaps(); + } + } + + void disposeOffsetMaps() { + for (OffsetMap map : myMapsToDispose) { + map.dispose(); + } + myMapsToDispose.clear(); } @TestOnly public static void cleanupForNextTest() { CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); if (currentCompletion != null) { - currentCompletion.finishCompletionProcess(); + currentCompletion.finishCompletionProcess(true); CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass()); } else { CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); @@ -718,4 +732,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } } + + public void addMapToDispose(OffsetMap map) { + myMapsToDispose.add(map); + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index cd1aa05ddffc..dc53052aef74 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -549,6 +549,7 @@ public class TemplateState implements Disposable { } }.execute(); } + offsetMap.dispose(); if (completionChar == '.') { EditorModificationUtil.insertStringAtCaret(myEditor, "."); From 5b1d45a7b4632e77d8236af7227cda4254ae943b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 5 Aug 2011 19:53:03 +0400 Subject: [PATCH 66/77] cleanup --- .../src/com/intellij/lang/folding/FoldingDescriptor.java | 3 ++- .../src/com/intellij/lang/folding/LanguageFolding.java | 2 +- .../com/intellij/codeInsight/folding/impl/FoldingUpdate.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java index 23512c1545ce..5810e725fe88 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java @@ -40,7 +40,7 @@ public class FoldingDescriptor { private final ASTNode myElement; private final TextRange myRange; @Nullable private final FoldingGroup myGroup; - private Set myDependencies; + private final Set myDependencies; private final boolean myNeverExpands; /** @@ -150,6 +150,7 @@ public class FoldingDescriptor { return myNeverExpands; } + @SuppressWarnings("HardCodedStringLiteral") @Override public String toString() { return myRange + " for AST: " + myElement; diff --git a/platform/lang-api/src/com/intellij/lang/folding/LanguageFolding.java b/platform/lang-api/src/com/intellij/lang/folding/LanguageFolding.java index 4a2a4238c4c0..289d2d5c4716 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/LanguageFolding.java +++ b/platform/lang-api/src/com/intellij/lang/folding/LanguageFolding.java @@ -55,7 +55,7 @@ public class LanguageFolding extends LanguageExtension { } } else { - return (extensions.size() == 1) ? extensions.get(0) : new CompositeFoldingBuilder(extensions); + return extensions.size() == 1 ? extensions.get(0) : new CompositeFoldingBuilder(extensions); } l.putUserData(getLanguageCache(), result); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java index 971046d9c384..d2c9838bb2f9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java @@ -157,11 +157,11 @@ public class FoldingUpdate { @NotNull FoldingMap elementsToFoldMap, boolean quick) { final FileViewProvider viewProvider = file.getViewProvider(); + TextRange docRange = TextRange.from(0, document.getTextLength()); for (final Language language : viewProvider.getLanguages()) { final PsiFile psi = viewProvider.getPsi(language); final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(language); if (psi != null && foldingBuilder != null) { - TextRange docRange = TextRange.from(0, document.getTextLength()); for (FoldingDescriptor descriptor : LanguageFolding.buildFoldingDescriptors(foldingBuilder, psi, document, quick)) { TextRange range = descriptor.getRange(); if (!docRange.contains(range)) { From 28b5b3020b19742aaf8d602e929e8793ab504c15 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 8 Aug 2011 12:30:54 +0400 Subject: [PATCH 67/77] IDEA-71895 --- .../tree/injected/InjectedLanguageUtil.java | 34 +++++++++---------- .../tree/injected/MultiHostRegistrarImpl.java | 23 ------------- 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 92d6608366a8..42262afee0fe 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -308,7 +308,6 @@ public class InjectedLanguageUtil { } private static final Key> INJECTED_DOCS_KEY = Key.create("INJECTED_DOCS_KEY"); - private static final Key> INJECTED_REGIONS_KEY = Key.create("INJECTED_REGIONS_KEY"); @NotNull public static List getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) { // modification of cachedInjectedDocuments must be under PsiLock only @@ -323,26 +322,36 @@ public class InjectedLanguageUtil { } public static void commitAllInjectedDocuments(Document hostDocument, Project project) { - List injected = getCachedInjectedRegions(hostDocument); - if (injected.isEmpty()) return; - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); PsiFile hostPsiFile = documentManager.getPsiFile(hostDocument); if (hostPsiFile == null) return; - for (RangeMarker rangeMarker : injected) { + + List injected = getCachedInjectedDocuments(hostPsiFile); + if (injected.isEmpty()) return; + + for (int i = injected.size() - 1; i >= 0; i--) { + DocumentWindow documentWindow = injected.get(i); ProgressManager.checkCanceled(); + RangeMarker rangeMarker = documentWindow.getHostRanges()[0]; PsiElement element = rangeMarker.isValid() ? hostPsiFile.findElementAt(rangeMarker.getStartOffset()) : null; if (element == null) { - injected.remove(rangeMarker); + injected.remove(i); continue; } - ProgressManager.checkCanceled(); + final DocumentWindow[] stillInjectedDocument = {null}; // it is here where the reparse happens and old file contents replaced enumerate(element, hostPsiFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { - PsiDocumentManagerImpl.checkConsistency(injectedPsi, injectedPsi.getViewProvider().getDocument()); + stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument(); + PsiDocumentManagerImpl.checkConsistency(injectedPsi, stillInjectedDocument[0]); } }, true); + if (stillInjectedDocument[0] == null) { + injected.remove(i); + } + else if (stillInjectedDocument[0] != documentWindow) { + injected.set(i,stillInjectedDocument[0]); + } } EditorWindow.disposeInvalidEditors(); // in write action @@ -380,15 +389,6 @@ public class InjectedLanguageUtil { } - static List getCachedInjectedRegions(Document hostDocument) { - List injectedRegions = hostDocument.getUserData(INJECTED_REGIONS_KEY); - if (injectedRegions == null) { - injectedRegions = ((UserDataHolderEx)hostDocument).putUserDataIfAbsent(INJECTED_REGIONS_KEY, - ContainerUtil.createEmptyCOWList()); - } - return injectedRegions; - } - public static Editor openEditorFor(PsiFile file, Project project) { Document document = PsiDocumentManager.getInstance(project).getDocument(file); // may return editor injected in current selection in the host editor, not for the file passed as argument diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java index eb9eb8cd01fb..5e58c0147b70 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java @@ -435,32 +435,9 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar { } injected.add(documentWindow); - cacheInjectedRegion(documentWindow, hostDocument); return injectedPsi; } - private static void cacheInjectedRegion(DocumentWindowImpl documentWindow, DocumentEx hostDocument) { - List injectedRegions = InjectedLanguageUtil.getCachedInjectedRegions(hostDocument); - RangeMarker newMarker = documentWindow.getHostRanges()[0]; - TextRange newRange = ProperTextRange.create(newMarker); - for (int i = 0; i < injectedRegions.size(); i++) { - RangeMarker stored = injectedRegions.get(i); - if (!stored.isValid()) continue; - TextRange storedRange = ProperTextRange.create(stored); - if (storedRange.intersects(newRange)) { - injectedRegions.set(i, newMarker); - break; - } - if (storedRange.getStartOffset() > newRange.getEndOffset()) { - injectedRegions.add(i, newMarker); - break; - } - } - if (injectedRegions.isEmpty() || newRange.getStartOffset() > injectedRegions.get(injectedRegions.size()-1).getEndOffset()) { - injectedRegions.add(newMarker); - } - } - // returns lexer element types with corresponding ranges in encoded (injection host based) PSI private static List> obtainHighlightTokensFromLexer(Language language, From 6b60b90c7c829859a930dd24d6adef6c5676060a Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 5 Aug 2011 19:12:03 +0400 Subject: [PATCH 68/77] Set proper help id (PY-4176). --- .../com/intellij/execution/RunContentExecutor.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/RunContentExecutor.java b/platform/lang-impl/src/com/intellij/execution/RunContentExecutor.java index f0943def7629..7a431d38937e 100644 --- a/platform/lang-impl/src/com/intellij/execution/RunContentExecutor.java +++ b/platform/lang-impl/src/com/intellij/execution/RunContentExecutor.java @@ -36,6 +36,7 @@ public class RunContentExecutor { private Runnable myRerun; private Runnable myAfterCompletion; private String myTitle = "Output"; + private String myHelpId = null; public RunContentExecutor(Project project, ProcessHandler process) { myProject = project; @@ -62,6 +63,11 @@ public class RunContentExecutor { return this; } + public RunContentExecutor withHelpId(String helpId) { + myHelpId = helpId; + return this; + } + private ConsoleView createConsole(Project project, ProcessHandler processHandler) { TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project); for (Filter filter : myFilterList) { @@ -76,6 +82,9 @@ public class RunContentExecutor { FileDocumentManager.getInstance().saveAllDocuments(); ConsoleView view = createConsole(myProject, myProcess); + if (myHelpId != null) { + view.setHelpId(myHelpId); + } Executor executor = ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID); DefaultActionGroup actions = new DefaultActionGroup(); @@ -104,7 +113,7 @@ public class RunContentExecutor { myProcess.startNotify(); } - private static JComponent createConsolePanel(ConsoleView view, ActionGroup actions) { + private static JComponent createConsolePanel(ConsoleView view, ActionGroup actions) { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.add(view.getComponent(), BorderLayout.CENTER); From 7ac48a447411d819bc051a3bc66668c1b2275ac0 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 8 Aug 2011 15:07:50 +0400 Subject: [PATCH 69/77] don't reparse open files --- .../src/com/intellij/lang/LanguagePerFileMappings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/lang/LanguagePerFileMappings.java b/platform/lang-impl/src/com/intellij/lang/LanguagePerFileMappings.java index 525fdd2b7110..9e1b1e5a8c14 100644 --- a/platform/lang-impl/src/com/intellij/lang/LanguagePerFileMappings.java +++ b/platform/lang-impl/src/com/intellij/lang/LanguagePerFileMappings.java @@ -129,7 +129,7 @@ public abstract class LanguagePerFileMappings implements PersistentStateCompo } } final List files = ContainerUtil.createMaybeSingletonList(file); - handleMappingChange(files, files, true); + handleMappingChange(files, files, false); } private void handleMappingChange(final Collection files, Collection oldFiles, final boolean includeOpenFiles) { From 2662492e1ba65c8b1d5e36522ae7ba1e2b99fcd6 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Mon, 8 Aug 2011 15:19:52 +0400 Subject: [PATCH 70/77] Caching stripe marks --- .../util/ui/ButtonlessScrollBarUI.java | 2 +- .../openapi/editor/impl/EditorImpl.java | 7 +- .../editor/impl/EditorMarkupModelImpl.java | 70 ++++++++++++++----- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index a65e7bcbca14..789ca1da713b 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -62,7 +62,7 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } if (scrollbar != null) { - scrollbar.repaint(); + scrollbar.repaint(((ButtonlessScrollBarUI)scrollbar.getUI()).getThumbBounds()); } } }; 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 3cf28f9643e3..e0ab15aa6933 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 @@ -321,7 +321,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int startLine = myDocument.getLineNumber(start); int endLine = end < myDocument.getTextLength() ? myDocument.getLineNumber(end) : myDocument.getLineCount() - 1; repaintLines(Math.max(0, startLine - 1), Math.min(endLine + 1, getDocument().getLineCount())); - ((EditorMarkupModelImpl)getMarkupModel()).markDirtied(); ((EditorMarkupModelImpl)getMarkupModel()).repaint(start, end); GutterIconRenderer renderer = highlighter.getGutterIconRenderer(); if (renderer != null) { @@ -2467,7 +2466,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } } - private void addContent(Graphics g, char[] _data, int _start, int _end, int _x, int _y, Color _color) { + private void addContent(Graphics g, char[] _data, int _start, int _end, int _x, int _y, @Nullable Color _color) { final int count = myCount; if (count > 0) { final int lastCount = count - 1; @@ -2706,8 +2705,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int end, Point position, Rectangle clip, - Color effectColor, - EffectType effectType, + @Nullable Color effectColor, + @Nullable EffectType effectType, int fontType, Color fontColor) { if (start >= end) return position.x; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index c665fe5f779f..fd4aabc7bdc6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -42,6 +42,7 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.TextRange; import com.intellij.ui.ColorUtil; import com.intellij.ui.HintHint; import com.intellij.ui.LightweightHint; @@ -59,6 +60,7 @@ import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; import java.util.*; import java.util.List; import java.util.Queue; @@ -79,6 +81,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark private int myEditorScrollbarTop = -1; private int myEditorTargetHeight = -1; private int myEditorSourceHeight = -1; + private TextRange myDirtyRange = null; @NotNull private ErrorStripTooltipRendererProvider myTooltipRendererProvider = new BasicTooltipRendererProvider(); @@ -283,7 +286,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } void repaint(int startOffset, int endOffset) { - markDirtied(); + markDirtied(startOffset, endOffset); ProperTextRange range = offsetToYPosition(startOffset, endOffset); @@ -331,6 +334,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark private class MyErrorPanel extends ButtonlessScrollBarUI implements MouseMotionListener, MouseListener { private PopupHandler myHandler; private ErrorStripeButton myErrorStripeButton; + private BufferedImage myCachedTrack; @Override protected JButton createDecreaseButton(int orientation) { @@ -376,22 +380,41 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark @Override protected void paintTrack(Graphics g, JComponent c, Rectangle bounds) { + Rectangle clip = g.getClipBounds().intersection(bounds); + if (clip.height == 0) return; + + final Rectangle componentBounds = c.getBounds(); + if (myCachedTrack == null || myCachedTrack.getHeight() != componentBounds.getHeight()) { + myCachedTrack = new BufferedImage(componentBounds.width, componentBounds.height, BufferedImage.TYPE_INT_ARGB); + myDirtyRange = TextRange.create(0, getEditor().getDocument().getTextLength()); + paintTrackBasement(myCachedTrack.getGraphics(), new Rectangle(0, 0, componentBounds.width, componentBounds.height)); + } + + if (myDirtyRange != null) { + final Graphics2D imageGraphics = myCachedTrack.createGraphics(); + + + ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart(); + + try { + repaint(imageGraphics, componentBounds.width, ERROR_ICON_WIDTH - 1, myDirtyRange.getStartOffset(), myDirtyRange.getEndOffset()); + myDirtyRange = null; + } + finally { + ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish(); + } + } + + ((Graphics2D)g).drawImage(myCachedTrack, null, 0, 0); + } + + private void paintTrackBasement(Graphics g, Rectangle bounds) { g.setColor(TRACK_BACKGROUND); g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); g.setColor(TRACK_BORDER); int border = isMirrored() ? bounds.x + bounds.width - 1 : bounds.x; g.drawLine(border, bounds.y, border, bounds.y + bounds.height); - - ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart(); - - try { - Rectangle clipBounds = g.getClipBounds(); - repaint(g, ERROR_ICON_WIDTH - 1, clipBounds); - } - finally { - ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish(); - } } @Override @@ -399,13 +422,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark return ColorUtil.withAlpha(ColorUtil.shift(super.adjustColor(c), 0.9), 0.85); } - private void repaint(final Graphics g, final int width, Rectangle clipBounds) { - Document document = myEditor.getDocument(); - int startOffset = yPositionToOffset(clipBounds.y, true); - int endOffset = yPositionToOffset(clipBounds.y + clipBounds.height, false); + private void repaint(final Graphics g, int gutterWidth, final int stripeWidth, int startOffset, int endOffset) { + final ProperTextRange yrange = offsetToYPosition(startOffset, endOffset); + final Rectangle clip = new Rectangle(0, yrange.getStartOffset(), gutterWidth, yrange.getLength() + getMinHeight()); + paintTrackBasement(g, clip); - drawMarkup(g, width, startOffset, endOffset, EditorMarkupModelImpl.this); - drawMarkup(g, width, startOffset, endOffset, (MarkupModelEx)document.getMarkupModel(myEditor.getProject())); + Document document = myEditor.getDocument(); + endOffset = yPositionToOffset(clip.y + clip.height, false); + + drawMarkup(g, stripeWidth, startOffset, endOffset, EditorMarkupModelImpl.this); + drawMarkup(g, stripeWidth, startOffset, endOffset, (MarkupModelEx)document.getMarkupModel(myEditor.getProject())); } private void drawMarkup(final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) { @@ -684,10 +710,18 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark LOG.assertTrue(success); } - public void markDirtied() { + public void markDirtied(int startOffset, int endOffset) { myEditorScrollbarTop = -1; myEditorSourceHeight = -1; myEditorTargetHeight = -1; + + final TextRange range = TextRange.create(startOffset, endOffset); + if (myDirtyRange == null) { + myDirtyRange = range; + } + else { + myDirtyRange = myDirtyRange.union(range); + } } public void setMinMarkHeight(final int minMarkHeight) { From 7e115e773a2ef0fa3a0dc1ef8a37dd3b18e663c7 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 8 Aug 2011 14:50:38 +0400 Subject: [PATCH 71/77] unmap / force buffers in order of pages --- .../intellij/util/io/PagedFileStorage.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index af0bb033b680..bb5704d5138c 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -28,9 +28,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author max @@ -58,7 +56,6 @@ public class PagedFileStorage implements Forceable { } private final StorageLock myLock; - private boolean myZeroWhenExpand; private int myLastPage = UNKNOWN_PAGE; private int myLastPage2 = UNKNOWN_PAGE; private MappedBufferWrapper myLastBuffer; @@ -175,15 +172,14 @@ public class PagedFileStorage implements Forceable { protected final int myPageSize; @NonNls private static final String RW = "rw"; - public PagedFileStorage(File file, StorageLock lock, int pageSize, boolean zeroWhenExpand) throws IOException { + public PagedFileStorage(File file, StorageLock lock, int pageSize) throws IOException { myFile = file; myLock = lock; myPageSize = Math.max(pageSize, Page.PAGE_SIZE); - myZeroWhenExpand = zeroWhenExpand; } public PagedFileStorage(File file, StorageLock lock) throws IOException { - this(file, lock, DEFAULT_BUFFER_SIZE, true); + this(file, lock, DEFAULT_BUFFER_SIZE); } public File getFile() { @@ -301,11 +297,14 @@ public class PagedFileStorage implements Forceable { } private void unmapAll() { - for (Map.Entry entry : myLock.myBuffersCache.entrySet()) { - if (entry.getKey().owner == this) { - myLock.myBuffersCache.remove(entry.getKey()); + final Map mineBuffers = getMineBuffersOrdered(); + + if (mineBuffers != null) { + for (PageKey key : mineBuffers.keySet()) { + myLock.myBuffersCache.remove(key); } } + myLastPage = UNKNOWN_PAGE; myLastPage2 = UNKNOWN_PAGE; myLastBuffer = null; @@ -325,7 +324,7 @@ public class PagedFileStorage implements Forceable { // it is not guaranteed that new partition will consist of null // after resize, so we should fill it manually int delta = newSize - oldSize; - if (delta > 0 && myZeroWhenExpand) fillWithZeros(oldSize, delta); + if (delta > 0) fillWithZeros(oldSize, delta); if (IOStatistics.DEBUG) { long finished = System.currentTimeMillis(); @@ -403,9 +402,11 @@ public class PagedFileStorage implements Forceable { public void force() { long started = IOStatistics.DEBUG ? System.currentTimeMillis():0; - for (Map.Entry entry : myLock.myBuffersCache.entrySet()) { - if (entry.getKey().owner == this) { - entry.getValue().flush(); + Map mineBuffers = getMineBuffersOrdered(); + + if (mineBuffers != null) { + for(MappedBufferWrapper buffer:mineBuffers.values()) { + buffer.flush(); } } isDirty = false; @@ -417,6 +418,23 @@ public class PagedFileStorage implements Forceable { } } + private @Nullable + Map getMineBuffersOrdered() { + Map mineBuffers = null; + for (Map.Entry entry : myLock.myBuffersCache.entrySet()) { + if (entry.getKey().owner == this) { + if (mineBuffers == null) mineBuffers = new TreeMap(new Comparator() { + @Override + public int compare(PageKey o1, PageKey o2) { + return o1.page - o2.page; + } + }); + mineBuffers.put(entry.getKey(), entry.getValue()); + } + } + return mineBuffers; + } + public boolean isDirty() { return isDirty; } From e186cf3aa9bb990e3ab1be9d4914ce8c60d603e9 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 8 Aug 2011 14:51:18 +0400 Subject: [PATCH 72/77] zeroing pages on demand does not pay out --- .../util/io/MappedFileSimpleStorage.java | 4 +- .../util/io/PersistentBTreeEnumerator.java | 78 +++++++------------ .../util/io/ResizeableMappedFile.java | 6 +- 3 files changed, 32 insertions(+), 56 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/MappedFileSimpleStorage.java b/platform/util/src/com/intellij/util/io/MappedFileSimpleStorage.java index 79dd723d2be8..186ce577a69a 100644 --- a/platform/util/src/com/intellij/util/io/MappedFileSimpleStorage.java +++ b/platform/util/src/com/intellij/util/io/MappedFileSimpleStorage.java @@ -13,9 +13,9 @@ final class MappedFileSimpleStorage implements ISimpleStorage { storage = new ResizeableMappedFile(file, initialSize, PersistentEnumeratorBase.ourLock); } - public MappedFileSimpleStorage(File file, int initialSize, int pageSize, boolean zeroPagesWhenExpand) throws IOException { + public MappedFileSimpleStorage(File file, int initialSize, int pageSize) throws IOException { FileUtil.createIfDoesntExist(file); - storage = new ResizeableMappedFile(file, initialSize, PersistentEnumeratorBase.ourLock, pageSize, zeroPagesWhenExpand); + storage = new ResizeableMappedFile(file, initialSize, PersistentEnumeratorBase.ourLock, pageSize); } @Override diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index 2def302f2331..27e972d447f2 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -46,7 +46,6 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase dataDescriptor, int initialSize) throws IOException { - this(file, dataDescriptor, initialSize, new RecordBufferHandler()); - } + super(file, new MappedFileSimpleStorage(file, initialSize, 1024 * 1024), dataDescriptor, initialSize, + ourVersion, new RecordBufferHandler()); - public PersistentBTreeEnumerator(File file, KeyDescriptor dataDescriptor, int initialSize, - PersistentEnumeratorBase.RecordBufferHandler recordBufferHandler) throws IOException { - super(file, new MappedFileSimpleStorage(file, initialSize, 1024 * 1024, false), dataDescriptor, initialSize, - ourVersion, recordBufferHandler); + myInlineKeysNoMapping = myDataDescriptor instanceof InlineKeyDescriptor && !wantInlineKeyMapping(); - myInlineKeysNoMapping = myDataDescriptor instanceof InlineKeyDescriptor && !wantInlineKeyMapping(); - - if (btree == null) { - synchronized (ourLock) { - storeVars(false); - initBtree(false); - storeBTreeVars(false); - } + if (btree == null) { + synchronized (ourLock) { + storeVars(false); + initBtree(false); + storeBTreeVars(false); } } + } + + private File indexFile(File file) { + return new File(file.getPath() + "_i"); + } protected boolean wantInlineKeyMapping() { return false; } - private void initBtree(boolean initial) { - btree = new IntToIntBtree(PAGE_SIZE, myRootNodeStart, myStorage, initial) { - - @Override - protected int allocEmptyPage() { - return PersistentBTreeEnumerator.this.allocPage(); - } - - @Override - void setRootAddress(int newRootAddress) { - super.setRootAddress(newRootAddress); - myRootNodeStart = newRootAddress; - } - }; + private void initBtree(boolean initial) throws IOException { + btree = new IntToIntBtree(PAGE_SIZE, indexFile(myFile), initial); } private void storeVars(boolean toDisk) { myLogicalFileLength = store(DATA_START, myLogicalFileLength, toDisk); - myRootNodeStart = store(DATA_START + 4, myRootNodeStart, toDisk); - myDataPageStart = store(DATA_START + 8, myDataPageStart, toDisk); - myDataPageOffset = store(DATA_START + 12, myDataPageOffset, toDisk); - myFirstPageStart = store(DATA_START + 16, myFirstPageStart, toDisk); - myDuplicatedValuesPageStart = store(DATA_START + 20, myDuplicatedValuesPageStart, toDisk); - myDuplicatedValuesPageOffset = store(DATA_START + 24, myDuplicatedValuesPageOffset, toDisk); - valuesCount = store(DATA_START + 28, valuesCount, toDisk); - collisions = store(DATA_START + 32, collisions, toDisk); + myDataPageStart = store(DATA_START + 4, myDataPageStart, toDisk); + myDataPageOffset = store(DATA_START + 8, myDataPageOffset, toDisk); + myFirstPageStart = store(DATA_START + 12, myFirstPageStart, toDisk); + myDuplicatedValuesPageStart = store(DATA_START + 16, myDuplicatedValuesPageStart, toDisk); + myDuplicatedValuesPageOffset = store(DATA_START + 20, myDuplicatedValuesPageOffset, toDisk); + valuesCount = store(DATA_START + 24, valuesCount, toDisk); + collisions = store(DATA_START + 28, collisions, toDisk); storeBTreeVars(toDisk); } private void storeBTreeVars(boolean toDisk) { if (btree != null) { - final int BTREE_DATA_START = DATA_START + 36; + final int BTREE_DATA_START = DATA_START + 32; btree.persistVars(new IntToIntBtree.BtreeDataStorage() { @Override public int persistInt(int offset, int value, boolean toDisk) { @@ -144,9 +129,6 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorBase processor, @Nullable final DataFilter filter) throws IOException { diff --git a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java index d4c85172ea91..39db983ab515 100644 --- a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java +++ b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java @@ -30,8 +30,8 @@ public class ResizeableMappedFile implements Forceable { private long myLogicalSize; private final PagedFileStorage myStorage; - public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock, int pageSize, boolean zeroWhenExpand) throws IOException { - myStorage = new PagedFileStorage(file, lock, pageSize, zeroWhenExpand); + public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock, int pageSize) throws IOException { + myStorage = new PagedFileStorage(file, lock, pageSize); if (!file.exists() || file.length() == 0) { writeLength(0); } @@ -45,7 +45,7 @@ public class ResizeableMappedFile implements Forceable { } public ResizeableMappedFile(final File file, int initialSize, PagedFileStorage.StorageLock lock) throws IOException { - this(file, initialSize, lock, PagedFileStorage.DEFAULT_BUFFER_SIZE, true); + this(file, initialSize, lock, PagedFileStorage.DEFAULT_BUFFER_SIZE); } public long length() { From 754e5ac71ce876586eadc925e9aedcb334035dc4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 8 Aug 2011 14:52:43 +0400 Subject: [PATCH 73/77] separate file for btree index, do not zero pages on demand --- .../com/intellij/util/io/IntToIntBtree.java | 70 +++++++------------ 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index a4c20d4599d2..6ac8f14224c5 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -1,8 +1,11 @@ package com.intellij.util.io; +import com.intellij.openapi.util.io.FileUtil; import gnu.trove.TIntIntHashMap; import org.jetbrains.annotations.Nullable; +import java.io.File; +import java.io.IOException; import java.util.Arrays; /** @@ -11,11 +14,10 @@ import java.util.Arrays; * Date: 7/12/11 * Time: 1:34 PM */ -abstract class IntToIntBtree { - static final int VERSION = 1; +class IntToIntBtree { + static final int VERSION = 2; static final boolean doSanityCheck = false; static final boolean doDump = false; - private static final int ROUND_FACTOR = 1048576; final int pageSize; private final short maxInteriorNodes; @@ -28,8 +30,6 @@ abstract class IntToIntBtree { private int hashSearchRequests; private int pagesCount; private int hashedPagesCount; - private int nextFreePage = -1; - private int nextFreePageCount = 0; private int count; private int movedMembersCount; @@ -45,13 +45,12 @@ abstract class IntToIntBtree { private TIntIntHashMap myCachedMappings; private final int myCachedMappingsSize; - public IntToIntBtree(int _pageSize, int rootAddress, ISimpleStorage _storage, boolean initial) { + public IntToIntBtree(int _pageSize, File file, boolean initial) throws IOException { pageSize = _pageSize; buffer = new byte[_pageSize]; - storage = _storage; root = new BtreeIndexNodeView(this); - root.setAddress(rootAddress); + root.setAddress(0); int i = (pageSize - BtreePage.RESERVED_META_PAGE_LEN) / BtreeIndexNodeView.INTERIOR_SIZE - 1; assert i < Short.MAX_VALUE && i % 2 == 0; @@ -82,7 +81,14 @@ abstract class IntToIntBtree { assert i > 0 && i % 2 == 0; maxLeafNodesInHash = (short) i; - pagesCount = 1; + if (initial) { + FileUtil.delete(file); + } + + storage = new MappedFileSimpleStorage(file, pageSize, 1024 * 1024); + if (initial) { + nextPage(); // allocate root + } ((BtreePage)root).load(); if (initial) { @@ -106,9 +112,8 @@ abstract class IntToIntBtree { count = storage.persistInt(16, count, toDisk); hashSearchRequests = storage.persistInt(20, hashSearchRequests, toDisk); totalHashStepsSearched = storage.persistInt(24, totalHashStepsSearched, toDisk); - nextFreePage = storage.persistInt(28, nextFreePage, toDisk); - nextFreePageCount = storage.persistInt(32, nextFreePageCount, toDisk); - hashedPagesCount = storage.persistInt(36, hashedPagesCount, toDisk); + hashedPagesCount = storage.persistInt(28, hashedPagesCount, toDisk); + root.setAddress(storage.persistInt(32, root.address, toDisk)); } interface BtreeDataStorage { @@ -124,34 +129,11 @@ abstract class IntToIntBtree { return true; } - protected abstract int allocEmptyPage(); - - private int nextPage(boolean root) { - int address; - - if (nextFreePageCount == 0) { - if ((height == 2 && root) || height >= 3) { // ensure more locality for index pages - nextFreePage = allocEmptyPage(); - nextFreePageCount = 1; - int freePage = nextFreePage + pageSize; - int numOfFullPages = 1; - - while(freePage % ROUND_FACTOR != 0 || numOfFullPages-- > 0) { - freePage = allocEmptyPage(); - ++nextFreePageCount; - } - } - } - - if (nextFreePageCount > 0) { - address = nextFreePage; - nextFreePage += pageSize; - --nextFreePageCount; - } else { - address = allocEmptyPage(); - } + private int nextPage() { + int pageStart = (int)storage.length(); + storage.putInt(pageStart + pageSize - 4, 0); ++pagesCount; - return address; + return pageStart; } public @Nullable Integer get(int key) { @@ -212,7 +194,7 @@ abstract class IntToIntBtree { int usedPercent2 = (int)((count * 100L) / leafNodesCapacity2); IOStatistics.dump("pagecount:" + pagesCount + ", height:" + height + ", movedMembers:"+movedMembersCount + ", hash steps:" + maxStepsSearchedInHash + ", avg search in hash:" + (hashSearchRequests != 0 ? totalHashStepsSearched / hashSearchRequests:0) + - ", leaf pages used:" + usedPercent + "%, leaf pages used if sorted: " + usedPercent2 + "%" ); + ", leaf pages used:" + usedPercent + "%, leaf pages used if sorted: " + usedPercent2 + "%, size:"+storage.length() ); } private void flushCachedMappings() { @@ -224,12 +206,14 @@ abstract class IntToIntBtree { } } - void cleanupOnClose() { + void doClose() throws IOException { myCachedMappings = null; + storage.close(); } void doFlush() { flushCachedMappings(); + storage.force(); } static void myAssert(boolean b) { @@ -552,7 +536,7 @@ abstract class IntToIntBtree { short maxIndex = (short)(getMaxChildrenCount() / 2); BtreeIndexNodeView newIndexNode = new BtreeIndexNodeView(btree); - newIndexNode.setAddress(btree.nextPage(false)); + newIndexNode.setAddress(btree.nextPage()); newIndexNode.setIndexLeaf(indexLeaf); @@ -668,7 +652,7 @@ abstract class IntToIntBtree { if (doSanityCheck) { btree.root.dump("Splitting root:"+medianKey); } - int newRootAddress = btree.nextPage(true); + int newRootAddress = btree.nextPage(); if (doSanityCheck) { System.out.println("Pages:"+btree.pagesCount+", elements:"+btree.count + ", average:" + (btree.height + 1)); } From 3cf16d7ec859e13c5110b48121d829b31e2eabd7 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Aug 2011 13:11:44 +0400 Subject: [PATCH 74/77] scopes: cache icon - no need to update (psi nodes are already recreated in collapse/expand phase on each psi modification) --- .../src/com/intellij/ide/scopeView/nodes/BasePsiNode.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/nodes/BasePsiNode.java b/platform/lang-impl/src/com/intellij/ide/scopeView/nodes/BasePsiNode.java index 42c6b7f3907d..456d1b07ddb5 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/nodes/BasePsiNode.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/nodes/BasePsiNode.java @@ -35,6 +35,7 @@ import java.awt.*; */ public class BasePsiNode extends PackageDependenciesNode { private final SmartPsiElementPointer myPsiElementPointer; + private Icon myIcon; public BasePsiNode(final T element) { super(element.getProject()); @@ -63,7 +64,10 @@ public class BasePsiNode extends PackageDependenciesNode { private Icon getIcon() { final PsiElement element = getPsiElement(); - return element != null && element.isValid() ? element.getIcon(Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS) : null; + if (myIcon == null) { + myIcon = element != null && element.isValid() ? element.getIcon(Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS) : null; + } + return myIcon; } @Nullable From 12c0e1cb57daa2811689ead866a183cca0572442 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Aug 2011 14:02:42 +0400 Subject: [PATCH 75/77] inspections results: do not update icon for created view --- .../codeInspection/ui/RefElementNode.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java index 9c3db7a42b60..32e262d04bf2 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java @@ -21,7 +21,9 @@ import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ex.InspectionTool; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.FileStatus; +import com.intellij.ui.ComputableIcon; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +37,16 @@ public class RefElementNode extends InspectionTreeNode { private boolean myHasDescriptorsUnder = false; private CommonProblemDescriptor mySingleDescriptor = null; protected InspectionTool myTool; + private ComputableIcon myIcon = new ComputableIcon(new Computable() { + @Override + public Icon compute() { + final RefEntity refEntity = getElement(); + if (refEntity == null) { + return null; + } + return refEntity.getIcon(false); + } + }); public RefElementNode(final Object userObject, final InspectionTool tool) { super(userObject); @@ -55,11 +67,7 @@ public class RefElementNode extends InspectionTreeNode { @Nullable public Icon getIcon(boolean expanded) { - final RefEntity refEntity = getElement(); - if (refEntity == null) { - return null; - } - return refEntity.getIcon(expanded); + return myIcon.getIcon(); } public int getProblemCount() { From 85eab5bccb73f75b0295d908b84197d9d1246104 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Aug 2011 15:23:18 +0400 Subject: [PATCH 76/77] plugins: support redirection (IDEA-70537) --- .../updateSettings/impl/PluginDownloader.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index fb0c344fbef8..4306ccdbc0d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -51,7 +51,7 @@ public class PluginDownloader { @NonNls private static final String FILENAME = "filename="; private final String myPluginId; - private final String myPluginUrl; + private String myPluginUrl; private String myPluginVersion; private String myFileName; @@ -197,14 +197,9 @@ public class PluginDownloader { pi.setText(IdeBundle.message("progress.connecting")); - final URLConnection connection = new URL(myPluginUrl).openConnection(); + URLConnection connection = null; try { - if (connection instanceof HttpURLConnection) { - final int responseCode = ((HttpURLConnection)connection).getResponseCode(); - if (responseCode != HttpURLConnection.HTTP_OK) { - throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); - } - } + connection = openConnection(myPluginUrl); final InputStream is = UrlConnectionUtil.getConnectionInputStream(connection, pi); if (is == null) { @@ -243,6 +238,31 @@ public class PluginDownloader { } } + private URLConnection openConnection(String url) throws IOException { + final URLConnection connection = new URL(url).openConnection(); + if (connection instanceof HttpURLConnection) { + final int responseCode = ((HttpURLConnection)connection).getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + String location = null; + if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { + location = connection.getHeaderField("Location"); + } + if (location == null) { + throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); + } else { + setPluginUrl(location); + ((HttpURLConnection)connection).disconnect(); + return openConnection(location); + } + } + } + return connection; + } + + private void setPluginUrl(String location) { + myPluginUrl = location; + } + private void guessFileName(final URLConnection connection, final File file) throws IOException { String contentDisposition = connection.getHeaderField("Content-Disposition"); if (contentDisposition == null || !contentDisposition.contains(FILENAME)) { From 0002ba9f31f1bd7354ec5b0b84137697002cb6f9 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Aug 2011 15:25:04 +0400 Subject: [PATCH 77/77] windows error codes for too long (IDEA-72931 ) --- .../src/com/intellij/execution/runners/ExecutionUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java index 2c222b02618a..a21c74312378 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java +++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java @@ -58,7 +58,7 @@ public class ExecutionUtil { String error = e.getMessage(); HyperlinkListener listener = null; - if (error.contains("87") && + if ((error.contains("87") || error.contains("111") || error.contains("206")) && e instanceof ProcessNotCreatedException && !PropertiesComponent.getInstance(project).isTrueValue("dynamic.classpath")) { final String commandLineString = ((ProcessNotCreatedException)e).getCommandLine().getCommandLineString();