From 86b6142e5116700e09ca8a1c5ace444af4aa59c3 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 1 Aug 2011 21:33:03 +0400 Subject: [PATCH 01/41] cache strings mapping in persistent string enumerator used for stubs processing to increase indexing speed --- .../psi/stubs/SerializationManagerImpl.java | 6 +- .../util/io/PersistentStringEnumerator.java | 107 +++++++++++++++++- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java index 528c752ebfe6..ecce3a64bec5 100644 --- a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java +++ b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java @@ -57,7 +57,9 @@ public class SerializationManagerImpl extends SerializationManager implements Ap public SerializationManagerImpl() { myFile.getParentFile().mkdirs(); try { - myNameStorage = new PersistentStringEnumerator(myFile); + // we need to cache last id -> String mappings due to StringRefs and stubs indexing that initially creates stubs (doing enumerate on String) + // and then index them (valueOf), also similar string items are expected to be enumerated during stubs processing + myNameStorage = new PersistentStringEnumerator(myFile, true); } catch (IOException e) { myNameStorageCrashed.set(true); @@ -94,7 +96,7 @@ public class SerializationManagerImpl extends SerializationManager implements Ap } } } - myNameStorage = new PersistentStringEnumerator(myFile); + myNameStorage = new PersistentStringEnumerator(myFile, true); mySerializerToId.clear(); myIdToSerializer.clear(); diff --git a/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java index 9720987d34ed..1ebfcf642894 100644 --- a/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentStringEnumerator.java @@ -15,16 +15,119 @@ */ package com.intellij.util.io; +import com.intellij.util.containers.SLRUMap; + import java.io.File; import java.io.IOException; public class PersistentStringEnumerator extends PersistentEnumerator{ + private final SLRUMap myIdToStringCache; + private final SLRUMap myHashcodeToIdCache; + public PersistentStringEnumerator(final File file) throws IOException { this(file, 1024 * 4); } - public PersistentStringEnumerator(final File file, final int initialSize) throws IOException { - super(file, new EnumeratorStringDescriptor(), initialSize); + public PersistentStringEnumerator(final File file, boolean cacheLastMappings) throws IOException { + this(file, 1024 * 4, cacheLastMappings); } + public PersistentStringEnumerator(final File file, final int initialSize) throws IOException { + this(file, initialSize, false); + } + + private PersistentStringEnumerator(final File file, final int initialSize, boolean cacheLastMappings) throws IOException { + super(file, new EnumeratorStringDescriptor(), initialSize); + if (cacheLastMappings) { + myIdToStringCache = new SLRUMap(8192, 8192); + myHashcodeToIdCache = new SLRUMap(8192, 8192); + } else { + myIdToStringCache = null; + myHashcodeToIdCache = null; + } + } + + @Override + public int enumerate(String value) throws IOException { + if (myHashcodeToIdCache != null && value != null) { + Integer cachedId; + synchronized (myHashcodeToIdCache) { + cachedId = myHashcodeToIdCache.get(value.hashCode()); + } + if (cachedId != null) { + String s; + synchronized (myIdToStringCache) { + s = myIdToStringCache.get(cachedId.intValue()); + } + if (s != null && value.equals(s)) return cachedId.intValue(); + } + } + + int enumerate = super.enumerate(value); + + if (myHashcodeToIdCache != null && value != null) { + synchronized (myHashcodeToIdCache) { + 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); + } + } + + return idx; + } + + @Override + public String valueOf(int idx) throws IOException { + if (myIdToStringCache != null) { + synchronized (myIdToStringCache) { + String s = myIdToStringCache.get(idx); + if (s != null) return s; + } + } + return super.valueOf(idx); + } + + @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(); + + if (myIdToStringCache != null) { + synchronized (myIdToStringCache) { + myIdToStringCache.clear(); + } + } + + if (myHashcodeToIdCache != null) { + synchronized (myHashcodeToIdCache) { + myHashcodeToIdCache.clear(); + } + } + } } From f4261d823b61fd4950c9a8e1fa8e5ff0d6e4d3d7 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 2 Aug 2011 19:20:07 +0400 Subject: [PATCH 02/41] fixed int division by zero when printing statistics --- platform/util/src/com/intellij/util/io/IntToIntBtree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 5257e217f70e..147f78110aff 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -184,7 +184,7 @@ abstract class IntToIntBtree { int usedPercent = (int)((count * 100L) / leafNodesCapacity); int usedPercent2 = (int)((count * 100L) / leafNodesCapacity2); IOStatistics.dump("pagecount:" + pagesCount + ", height:" + height + ", movedMembers:"+movedMembersCount + - ", hash steps:" + maxStepsSearchedInHash + ", avg search in hash:" + (totalHashStepsSearched / hashSearchRequests) + + ", hash steps:" + maxStepsSearchedInHash + ", avg search in hash:" + (hashSearchRequests != 0 ? totalHashStepsSearched / hashSearchRequests:0) + ", leaf pages used:" + usedPercent + "%, leaf pages used if max children: " + usedPercent2 + "%" ); } From 3321d8938cd4c30763e904cbcc98993d8192695e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 3 Aug 2011 15:09:20 +0400 Subject: [PATCH 03/41] RUBY-9065 move coverage related color settings to general/coverage tab --- .../options/colors/pages/JavaColorSettingsPage.java | 13 +------------ .../options/colors/pages/GeneralColorsPage.java | 5 +++++ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java index 83f24f0960ff..946b75c4b381 100644 --- a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java +++ b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java @@ -28,14 +28,11 @@ import com.intellij.openapi.options.colors.AttributesDescriptor; import com.intellij.openapi.options.colors.ColorDescriptor; import com.intellij.openapi.options.colors.ColorSettingsPage; import com.intellij.pom.java.LanguageLevel; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColorSettingsPage { @@ -125,15 +122,7 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor @NotNull public AttributesDescriptor[] getAttributeDescriptors() { - List descriptors = new ArrayList(); - ContainerUtil.addAll(descriptors, ourDescriptors); - descriptors.add( - new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.full.coverage"), CodeInsightColors.LINE_FULL_COVERAGE)); - descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.partial.coverage"), - CodeInsightColors.LINE_PARTIAL_COVERAGE)); - descriptors.add( - new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.none.coverage"), CodeInsightColors.LINE_NONE_COVERAGE)); - return descriptors.toArray(new AttributesDescriptor[descriptors.size()]); + return ourDescriptors; } @NotNull diff --git a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/GeneralColorsPage.java b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/GeneralColorsPage.java index 2d1e2b1c2de4..44a06d86d07d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/GeneralColorsPage.java +++ b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/GeneralColorsPage.java @@ -86,6 +86,11 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.unmatched.brace"), CodeInsightColors.UNMATCHED_BRACE_ATTRIBUTES), new AttributesDescriptor(OptionsBundle.message("options.general.color.descriptor.todo.defaults"), CodeInsightColors.TODO_DEFAULT_ATTRIBUTES), + + new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.full.coverage"), CodeInsightColors.LINE_FULL_COVERAGE), + new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.partial.coverage"), + CodeInsightColors.LINE_PARTIAL_COVERAGE), + new AttributesDescriptor(OptionsBundle.message("options.java.color.descriptor.none.coverage"), CodeInsightColors.LINE_NONE_COVERAGE) }; private static final ColorDescriptor[] COLOR_DESCRIPTORS = { From f9d84f58aa04a52ad3de802b2955adc2a47d8615 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 2 Aug 2011 16:14:32 +0400 Subject: [PATCH 04/41] moved to package --- .../com/intellij/openapi/editor/impl/RangeMarkerImpl.java | 3 +-- .../intellij/openapi/editor/impl/StripedIDGenerator.java} | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) rename platform/{util/src/com/intellij/util/DistributedCounter.java => platform-impl/src/com/intellij/openapi/editor/impl/StripedIDGenerator.java} (90%) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 3ce45df63f30..6d89f0be3db6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -21,7 +21,6 @@ import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.RangeMarkerEx; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.util.DistributedCounter; import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -33,7 +32,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx protected RangeMarkerTree.RMNode myNode; private final long myId; - private static final DistributedCounter counter = new DistributedCounter(); + private static final StripedIDGenerator counter = new StripedIDGenerator(); protected RangeMarkerImpl(@NotNull DocumentEx document, int start, int end, boolean register) { this(document, start, end, register, false, false); diff --git a/platform/util/src/com/intellij/util/DistributedCounter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/StripedIDGenerator.java similarity index 90% rename from platform/util/src/com/intellij/util/DistributedCounter.java rename to platform/platform-impl/src/com/intellij/openapi/editor/impl/StripedIDGenerator.java index 9fdfcd0b15a1..081bcb666dc5 100644 --- a/platform/util/src/com/intellij/util/DistributedCounter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/StripedIDGenerator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.util; +package com.intellij.openapi.editor.impl; import java.util.concurrent.atomic.AtomicLong; @@ -21,10 +21,10 @@ import java.util.concurrent.atomic.AtomicLong; * Low-contention counter. * Repeated calls to {@link #next()} return numbers which are unique across all calling threads, and which are increasing over calls within one thread. */ -public class DistributedCounter { +public class StripedIDGenerator { private static final int CHUNK_SIZE = 1000; private final AtomicLong nextChunkStart = new AtomicLong(); - // must not ne static + // must not be static since we might want to have several instances of this class private final ThreadLocal localCounter = new ThreadLocal(); private static class NextPair { long nextId; From 4dcde9bbfa3bd8e161b2b815caea9ebaa086e24b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 3 Aug 2011 14:44:23 +0400 Subject: [PATCH 05/41] IDEA-71599 --- .../daemon/impl/analysis/HighlightUtil.java | 13 ++++++++++++- .../advHighlighting/MethodCalls.java | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 00339413c87f..5c276d0cd9cd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -2107,7 +2107,18 @@ public class HighlightUtil { if (highlightInfo != null) return highlightInfo; PsiElement refParent = ref.getParent(); - if (refParent instanceof PsiMethodCallExpression) { + PsiElement granny; + if (refParent instanceof PsiReferenceExpression && (granny = refParent.getParent()) instanceof PsiMethodCallExpression) { + PsiReferenceExpression referenceToMethod = ((PsiMethodCallExpression)granny).getMethodExpression(); + PsiExpression qualifierExpression = referenceToMethod.getQualifierExpression(); + if (qualifierExpression == ref) { + PsiElement qualifier = resolved; + if (qualifier != null && !(qualifier instanceof PsiClass) && !(qualifier instanceof PsiVariable)) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, qualifierExpression, "Qualifier must be an expression"); + } + } + } + else if (refParent instanceof PsiMethodCallExpression) { return null; // methods checked elsewhere } if (resolved == null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MethodCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MethodCalls.java index c6fc37d77092..74175a7a882c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MethodCalls.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MethodCalls.java @@ -94,6 +94,10 @@ class DCC { DCC(1); new DCC(1); } + { + java.toString(); + } + } class ThisExpression { From ba6f9058e46169dfb116cbaa8083b47b81d75306 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 3 Aug 2011 15:14:40 +0400 Subject: [PATCH 06/41] cleanup --- .../codeInsight/daemon/impl/quickfix/SafeDeleteFix.java | 2 +- .../com/intellij/packageDependencies/ui/PackageNode.java | 2 +- .../com/intellij/packageDependencies/ui/DirectoryNode.java | 3 +-- .../packageDependencies/ui/PackageDependenciesNode.java | 7 ++++--- .../intellij/openapi/editor/LazyRangeMarkerFactory.java | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java index 10acd161174b..d0a271c65022 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SafeDeleteFix.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; public class SafeDeleteFix implements IntentionAction { private final PsiElement myElement; - public SafeDeleteFix(PsiElement element) { + public SafeDeleteFix(@NotNull PsiElement element) { myElement = element; } diff --git a/java/java-impl/src/com/intellij/packageDependencies/ui/PackageNode.java b/java/java-impl/src/com/intellij/packageDependencies/ui/PackageNode.java index ecc137de5c3b..da7af09bd5be 100644 --- a/java/java-impl/src/com/intellij/packageDependencies/ui/PackageNode.java +++ b/java/java-impl/src/com/intellij/packageDependencies/ui/PackageNode.java @@ -117,7 +117,7 @@ public class PackageNode extends PackageDependenciesNode { @Override public boolean canSelectInLeftTree(final Map> deps) { Set files = deps.keySet(); - String packageName = myPackage.getQualifiedName(); + String packageName = myPackageQName; for (PsiFile file : files) { if (file instanceof PsiJavaFile && Comparing.equal(packageName, ((PsiJavaFile)file).getPackageName())) { return true; 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 f718ce80a8b5..453c2464584e 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java @@ -44,8 +44,7 @@ public class DirectoryNode extends PackageDependenciesNode { private boolean myCompactPackages = true; private String myFQName = null; - private VirtualFile myVDirectory; - //private static final Logger LOG = Logger.getInstance("#com.intellij.packageDependencies.ui.DirectoryNode"); + private final VirtualFile myVDirectory; public DirectoryNode(VirtualFile aDirectory, Project project, boolean compactPackages, boolean showFQName) { super(project); diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/PackageDependenciesNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/PackageDependenciesNode.java index cd556bf7017a..4bad2b1df0f2 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/PackageDependenciesNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/PackageDependenciesNode.java @@ -29,6 +29,7 @@ import com.intellij.psi.PsiManager; import com.intellij.util.IconUtil; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -46,11 +47,11 @@ public class PackageDependenciesNode extends DefaultMutableTreeNode implements N private boolean myHasMarked = false; private boolean myEquals; protected Color myColor = null; - protected final static Color NOT_CHANGED = new Color(0, 0, 0); + protected static final Color NOT_CHANGED = new Color(0, 0, 0); protected Project myProject; private boolean mySorted; - public PackageDependenciesNode(Project project) { + public PackageDependenciesNode(@NotNull Project project) { myProject = project; } @@ -135,7 +136,7 @@ public class PackageDependenciesNode extends DefaultMutableTreeNode implements N if (hasUnmarked && !myHasUnmarked || hasMarked && !myHasMarked) { myHasUnmarked |= hasUnmarked; myHasMarked |= hasMarked; - PackageDependenciesNode parent = ((PackageDependenciesNode)getParent()); + PackageDependenciesNode parent = (PackageDependenciesNode)getParent(); if (parent != null) { parent.updateMarked(myHasUnmarked, myHasMarked); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index d9a9b532eaab..2d5d53d4de9e 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -188,7 +188,7 @@ public class LazyRangeMarkerFactory extends AbstractProjectComponent { offset = lineStart; int col = 0; while (offset < lineEnd && col < column) { - col += (docText.charAt(offset) == '\t' ? tabSize : 1); + col += docText.charAt(offset) == '\t' ? tabSize : 1; offset++; } } From 6a4ed303a40d6d2a660229c2582f56c7d476e1cb Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 2 Aug 2011 18:06:18 +0200 Subject: [PATCH 07/41] force no completion phase after the project is closed (could be emptyAutoPopup or restarted) --- .../codeInsight/completion/impl/CompletionServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 4478e4949191..c840766f3190 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -55,7 +55,9 @@ public class CompletionServiceImpl extends CompletionService{ public void projectClosing(Project project) { CompletionProgressIndicator indicator = getCurrentCompletion(); if (indicator != null && indicator.getProject() == project) { - LookupManager.getInstance(project).hideActiveLookup(); + LookupManager.getInstance(indicator.getProject()).hideActiveLookup(); + setCompletionPhase(CompletionPhase.NoCompletion); + } else if (indicator == null) { setCompletionPhase(CompletionPhase.NoCompletion); } } From aac6e8bb0f8f5e3f9c4e6abf1d20896a44caedbb Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 2 Aug 2011 18:56:32 +0200 Subject: [PATCH 08/41] typing non-letter characters should cancel the autopopup completion in its early stages --- .../codeInsight/completion/JavaAutoPopupTest.groovy | 9 +++++++++ .../completion/CodeCompletionHandlerBase.java | 2 +- .../editorActions/CompletionAutoPopupHandler.java | 2 +- 3 files changed, 11 insertions(+), 2 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 4b461596e859..08cf1e0800f7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -490,6 +490,7 @@ public interface Test { public void testCancellingDuringCalculation() { myFixture.configureByText "a.java", """ +class Aaaaaaa {} public interface Test { }""" @@ -676,6 +677,14 @@ class Foo { assert myFixture.editor.document.text.contains('filinpstr()') } + public void testNoAutopopupAfterSpace() { + myFixture.configureByText("a.java", """ class Foo { { int newa; } } """) + edt { myFixture.type('new ') } + joinAlarm() + joinCompletion() + assert !lookup + } + public void testNonFinishedParameterComma() { myFixture.configureByText("a.java", """ class Foo { void foo(int aaa, int aaaaa) { foo() } } """) type 'a,' 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 717dbda30bb4..de686c51ae40 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -501,7 +501,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { final Project project = hostFile.getProject(); if (autopopup) { - final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(false, hostEditor); + final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(true, hostEditor); CompletionServiceImpl.setCompletionPhase(phase); CompletionAutoPopupHandler.runLaterWithCommitted(project, hostDocument, new Runnable() { 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 e5eaf619e081..eaa7315beb24 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -71,7 +71,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { } if (!Character.isLetter(charTyped) && charTyped != '_') { - if (CompletionServiceImpl.isPhase(CompletionPhase.EmptyAutoPopup.class)) { + if (CompletionServiceImpl.isPhase(CompletionPhase.EmptyAutoPopup.class, CompletionPhase.AutoPopupAlarm.class)) { CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); } return Result.CONTINUE; From 50d906f70fb36ac06fc9f1009c15fc56a297dc7f Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Wed, 3 Aug 2011 15:36:25 +0400 Subject: [PATCH 09/41] Do not update invoke git on awt Assertion failed: Git process should never start in the dispatch thread. java.lang.Throwable at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:98) at git4idea.commands.GitHandler.runInCurrentThread(GitHandler.java:622) at git4idea.commands.GitHandlerUtil.runInCurrentThread(GitHandlerUtil.java:185) at git4idea.commands.GitSimpleHandler.run(GitSimpleHandler.java:225) at git4idea.GitRemote.list(GitRemote.java:165) at org.jetbrains.plugins.github.GithubUtil.findGitHubRemoteBranch(GithubUtil.java:371) at org.jetbrains.plugins.github.GithubUtil.getGithubBoundRepository(GithubUtil.java:363) at org.jetbrains.plugins.github.GithubOpenInBrowserAction.update(GithubOpenInBrowserAction.java:57) at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareUpdate(ActionUtil.java:98) at com.intellij.openapi.actionSystem.impl.Utils.doUpdate(Utils.java:162) at com.intellij.openapi.actionSystem.impl.Utils.expandActionGroup(Utils.java:124) at com.intellij.openapi.actionSystem.impl.Utils.expandActionGroup(Utils.java:84) at com.intellij.openapi.actionSystem.impl.Utils.fillMenu(Utils.java:234) at com.intellij.openapi.actionSystem.impl.ActionPopupMenuImpl$MyMenu.show(ActionPopupMenuImpl.java:88) at com.intellij.ide.ui.customization.CustomizationUtil$3.invokePopup(CustomizationUtil.java:323) at com.intellij.ui.PopupHandler.mousePressed(PopupHandler.java:48) at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:263) at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:262) at java.awt.Component.processMouseEvent(Component.java:6370) at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) at com.intellij.ui.treeStructure.Tree.processMouseEvent(Tree.java:316) at com.intellij.ide.dnd.aware.DnDAwareTree.processMouseEvent(DnDAwareTree.java:49) at java.awt.Component.processEvent(Component.java:6138) at java.awt.Container.processEvent(Container.java:2085) at java.awt.Component.dispatchEventImpl(Component.java:4735) at java.awt.Container.dispatchEventImpl(Container.java:2143) at java.awt.Component.dispatchEvent(Component.java:4565) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4621) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4279) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4212) at java.awt.Container.dispatchEventImpl(Container.java:2129) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4565) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:679) at java.awt.EventQueue.access$000(EventQueue.java:85) at java.awt.EventQueue$1.run(EventQueue.java:638) at java.awt.EventQueue$1.run(EventQueue.java:636) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) at java.awt.EventQueue$2.run(EventQueue.java:652) at java.awt.EventQueue$2.run(EventQueue.java:650) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:649) at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:678) at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:527) at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:414) at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:372) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) --- .../jetbrains/plugins/github/GithubOpenInBrowserAction.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index 0919d1d6eb05..b50ba8f4c624 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -55,8 +55,7 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { final Project project = e.getData(PlatformDataKeys.PROJECT); final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); if (StringUtil.isEmptyOrSpaces(GithubSettings.getInstance().getLogin()) || - project == null || project.isDefault() || virtualFile == null || - GithubUtil.getGithubBoundRepository(project) == null) { + project == null || project.isDefault() || virtualFile == null) { e.getPresentation().setVisible(false); e.getPresentation().setEnabled(false); return; From 4f742edf3fe05d969f81112ff11f091163ecbcb1 Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Wed, 3 Aug 2011 15:56:09 +0400 Subject: [PATCH 10/41] "Other languages" item for legacy code style settings --- .../CommonCodeStyleSettingsProvider.java | 18 +++--------------- .../src/messages/ApplicationBundle.properties | 1 + 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/CommonCodeStyleSettingsProvider.java b/platform/lang-impl/src/com/intellij/application/options/CommonCodeStyleSettingsProvider.java index 088eb77dfdbc..4c03e1dc20d4 100644 --- a/platform/lang-impl/src/com/intellij/application/options/CommonCodeStyleSettingsProvider.java +++ b/platform/lang-impl/src/com/intellij/application/options/CommonCodeStyleSettingsProvider.java @@ -16,6 +16,7 @@ package com.intellij.application.options; import com.intellij.lang.Language; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.options.Configurable; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; @@ -35,20 +36,7 @@ public class CommonCodeStyleSettingsProvider extends CodeStyleSettingsProvider { @Override public String getConfigurableDisplayName() { - StringBuilder nameBuilder = new StringBuilder(); - boolean isFirst = true; - for (Language language : LanguageCodeStyleSettingsProvider.getLanguagesWithSharedPreview()) { - if (isFirst) { - isFirst = false; - } - else { - nameBuilder.append('/'); - } - nameBuilder.append(language.getDisplayName()); - } - if (nameBuilder.length() > 0) nameBuilder.append(' '); - nameBuilder.append("Formatting"); - return nameBuilder.toString(); + return ApplicationBundle.message("title.other.languages"); } @Override @@ -58,7 +46,7 @@ public class CommonCodeStyleSettingsProvider extends CodeStyleSettingsProvider { @Override public DisplayPriority getPriority() { - return DisplayPriority.KEY_LANGUAGE_SETTINGS; + return DisplayPriority.OTHER_SETTINGS; } } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index baac625f58f7..ef7630cba3e7 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -529,3 +529,4 @@ insert.override.annotation=Insert @&Override annotation auto.import=Auto Import checkbox.collapse.suppress.warnings=@SuppressWarnings checkbox.collapse.end.of.line.comments=End of line comments sequence +title.other.languages=Other Languages \ No newline at end of file From 4b74220bebb8065b91bb8e746caf45b79012f502 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 14:11:29 +0400 Subject: [PATCH 11/41] smart asses --- .../intellij/codeInsight/daemon/impl/PassExecutorService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java index 1e5bbf036459..67dacd2167ca 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java @@ -351,7 +351,7 @@ public abstract class PassExecutorService implements Disposable { catch (ProcessCanceledException e) { log(myUpdateProgress, myPass, "Canceled "); - myUpdateProgress.cancel(e); //in case when some smartasses throw PCE just for fun + myUpdateProgress.cancel(e); //in case when some smart asses throw PCE just for fun } catch (RuntimeException e) { myUpdateProgress.cancel(e); From f8c13dbce22422aa3fb16030d178a98aed4fdb58 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 15:05:30 +0400 Subject: [PATCH 12/41] IDEA-71647: # is marked as invalid url (provide FileReference for empty string) --- .../intellij/openapi/paths/StaticPathReferenceProvider.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java b/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java index ddf4a56a693e..c6a15535bc30 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java @@ -17,7 +17,6 @@ package com.intellij.openapi.paths; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; @@ -47,9 +46,6 @@ public class StaticPathReferenceProvider extends PathReferenceProviderBase { final @NotNull List references, final boolean soft) { - if (StringUtil.isEmpty(text)) { - return true; - } FileReferenceSet set = new FileReferenceSet(text, psiElement, offset, null, true, myEndingSlashNotAllowed, mySuitableFileTypes) { protected boolean isUrlEncoded() { return true; From c02073c6918d6f20bdaf4ff5ee77adb7b7d86a20 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 15:37:15 +0400 Subject: [PATCH 13/41] @Nullable --- platform/lang-api/src/com/intellij/psi/PsiElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/psi/PsiElement.java b/platform/lang-api/src/com/intellij/psi/PsiElement.java index 13b889d2228e..4ab0e77fa2ad 100644 --- a/platform/lang-api/src/com/intellij/psi/PsiElement.java +++ b/platform/lang-api/src/com/intellij/psi/PsiElement.java @@ -418,7 +418,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * @param value the user data object to attach. * @see #getCopyableUserData(com.intellij.openapi.util.Key) */ - void putCopyableUserData(Key key, T value); + void putCopyableUserData(Key key, @Nullable T value); /** * Passes the declarations contained in this PSI element and its children From 9a207a911b9f93422e1bc38a3642ca3fe2636aad Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 15:57:12 +0400 Subject: [PATCH 14/41] IDEA-72809: Refactor "Move Folder" - Anchor references are incorrectly updated. --- .../psi/impl/include/FileIncludeManagerImpl.java | 7 ++++--- .../reference/impl/providers/FileReference.java | 12 +++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java index 58a21b0ec201..36fa5ad8e196 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java @@ -34,6 +34,7 @@ import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferen import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FactoryMap; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; @@ -61,9 +62,9 @@ public class FileIncludeManagerImpl extends FileIncludeManager { @Override public boolean process(FileIncludeInfo info) { if (compileTimeOnly != info.runtimeOnly) { - PsiFileSystemItem virtualFile = resolveFileInclude(info, file); - if (virtualFile != null) { - files.add(virtualFile.getVirtualFile()); + PsiFileSystemItem item = resolveFileInclude(info, file); + if (item != null) { + ContainerUtil.addIfNotNull(files, item.getVirtualFile()); } } return true; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java index f2cdbdaa6bf0..c6928e8fd93b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java @@ -144,13 +144,8 @@ public class FileReference implements FileReferenceOwner, PsiPolyVariantReferenc protected ResolveResult[] innerResolve(boolean caseSensitive) { final String referenceText = getText(); - final TextRange range = getRangeInElement(); - if (range.isEmpty()) { - final PsiElement element = getElement(); - final String s = element.getText(); - if (s.length() > range.getEndOffset() && s.charAt(range.getEndOffset()) == '#') { - return new ResolveResult[] { new PsiElementResolveResult(element.getContainingFile())}; - } + if (referenceText.isEmpty()) { + return new ResolveResult[] { new PsiElementResolveResult(getElement().getContainingFile())}; } final Collection contexts = getContexts(); final Collection result = new THashSet(RESOLVE_RESULT_HASHING_STRATEGY); @@ -401,6 +396,9 @@ public class FileReference implements FileReferenceOwner, PsiPolyVariantReferenc public PsiElement bindToElement(@NotNull final PsiElement element, final boolean absolute) throws IncorrectOperationException { if (!(element instanceof PsiFileSystemItem)) throw new IncorrectOperationException("Cannot bind to element, should be instanceof PsiFileSystemItem: " + element); + // handle empty reference that resolves to current file + if (getCanonicalText().isEmpty() && element == getElement().getContainingFile()) return getElement(); + final PsiFileSystemItem fileSystemItem = (PsiFileSystemItem)element; VirtualFile dstVFile = fileSystemItem.getVirtualFile(); if (dstVFile == null) throw new IncorrectOperationException("Cannot bind to non-physical element:" + element); From 19971a73fc06f2e38f10c3afeed6952f4afd0022 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 3 Aug 2011 16:04:41 +0400 Subject: [PATCH 15/41] IDEA-72791 Critical bug in Code formatting (Java source files) Providing information about project to the data context of non-opened editor. --- .../source/codeStyle/CodeFormatterFacade.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java index edb94e7755f2..496db4eed3cb 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java @@ -23,6 +23,7 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.LanguageFormatting; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -48,6 +49,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -241,7 +243,7 @@ public class CodeFormatterFacade { * @param startOffset start offset of the first line to check for wrapping (inclusive) * @param endOffset end offset of the first line to check for wrapping (exclusive) */ - private void wrapLongLinesIfNecessary(@NotNull PsiFile file, @Nullable final Document document, final int startOffset, + private void wrapLongLinesIfNecessary(@NotNull final PsiFile file, @Nullable final Document document, final int startOffset, final int endOffset) { if (!mySettings.WRAP_LONG_LINES || file.getViewProvider().isLockedByPsiOperations() || document == null) { @@ -272,7 +274,7 @@ public class CodeFormatterFacade { final CaretModel caretModel = editorToUse.getCaretModel(); final int caretOffset = caretModel.getOffset(); final RangeMarker caretMarker = editorToUse.getDocument().createRangeMarker(caretOffset, caretOffset); - doWrapLongLinesIfNecessary(editorToUse, editorToUse.getDocument(), startOffset, endOffset); + doWrapLongLinesIfNecessary(editorToUse, file.getProject(), editorToUse.getDocument(), startOffset, endOffset); if (caretMarker.isValid() && caretModel.getOffset() != caretMarker.getStartOffset()) { caretModel.moveToOffset(caretMarker.getStartOffset()); } @@ -288,7 +290,8 @@ public class CodeFormatterFacade { } } - private void doWrapLongLinesIfNecessary(@NotNull final Editor editor, @NotNull Document document, int startOffset, int endOffset) { + private void doWrapLongLinesIfNecessary(@NotNull final Editor editor, @NotNull final Project project, @NotNull Document document, + int startOffset, int endOffset) { // Normalization. int startOffsetToUse = Math.min(document.getTextLength(), Math.max(0, startOffset)); int endOffsetToUse = Math.min(document.getTextLength(), Math.max(0, endOffset)); @@ -395,7 +398,21 @@ public class CodeFormatterFacade { continue; } editor.getCaretModel().moveToOffset(wrapOffset); - final DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent()); + + // There is a possible case that formatting is performed from project view and editor is not opened yet. The problem is that + // its data context doesn't contain information about project then. So, we explicitly support that here (see IDEA-72791). + final DataContext baseDataContext = DataManager.getInstance().getDataContext(editor.getComponent()); + final DataContext dataContext = new DataContext() { + @Override + public Object getData(@NonNls String dataId) { + Object result = baseDataContext.getData(dataId); + if (result == null && PlatformDataKeys.PROJECT.is(dataId)) { + result = project; + } + return result; + } + }; + SelectionModel selectionModel = editor.getSelectionModel(); int startSelectionOffset = 0; From 431bdc1cb0c67e00b1942474fbd18638a4b35bca Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 3 Aug 2011 17:10:27 +0400 Subject: [PATCH 16/41] separate btree version added --- platform/util/src/com/intellij/util/io/IntToIntBtree.java | 1 + .../src/com/intellij/util/io/PersistentBTreeEnumerator.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 147f78110aff..002edf7e31c0 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -12,6 +12,7 @@ import java.util.Arrays; * Time: 1:34 PM */ abstract class IntToIntBtree { + static final int VERSION = 1; static final boolean doSanityCheck = false; static final boolean doDump = false; private static final int ROUND_FACTOR = 1048576; diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index 5f50b0ce4b26..0e948db22546 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -62,7 +62,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase Date: Wed, 3 Aug 2011 17:15:27 +0400 Subject: [PATCH 17/41] more optimal offloading children to siblings when btree page has sorted page representation --- .../com/intellij/util/io/IntToIntBtree.java | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 002edf7e31c0..b6996a1b3f78 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -36,7 +36,7 @@ abstract class IntToIntBtree { private final byte[] buffer; private boolean isLarge = true; private final ISimpleStorage storage; - private final boolean offloadToSiblingsBeforeSplit = false; // TODO till effective insertion to page + private final boolean offloadToSiblingsBeforeSplit = false; private boolean indexNodeIsHashTable = true; final int metaDataLeafPageLength; final int hashPageCapacity; @@ -461,7 +461,7 @@ abstract class IntToIntBtree { parent = new BtreeIndexNodeView(btree); parent.setAddress(parentAddress); if (btree.offloadToSiblingsBeforeSplit) { - if (doOffloadToSiblings(parent)) return parentAddress; + if (doOffloadToSiblingsSorted(parent)) return parentAddress; } } @@ -523,7 +523,7 @@ abstract class IntToIntBtree { } else { short recordCountInNewNode = (short)(recordCount - maxIndex); newIndexNode.setChildrenCount(recordCountInNewNode); - + if (btree.isLarge) { final int bytesToMove = recordCountInNewNode * INTERIOR_SIZE; getBytes(indexToOffset(maxIndex), btree.buffer, 0, bytesToMove); @@ -596,56 +596,59 @@ abstract class IntToIntBtree { return parentAddress; } - private boolean doOffloadToSiblings(BtreeIndexNodeView parent) { - int indexInParent = isIndexLeaf() ? parent.search(keyAt(0)) : -1; - BtreeIndexNodeView sibling = new BtreeIndexNodeView(btree); + private boolean doOffloadToSiblingsSorted(BtreeIndexNodeView parent) { + boolean indexLeaf = isIndexLeaf(); + if (!indexLeaf) return false; // TODO - if (indexInParent > 0) { + int indexInParent = parent.search(keyAt(0)); + + if (indexInParent >= 0) { if (doSanityCheck) { myAssert(parent.keyAt(indexInParent) == keyAt(0)); myAssert(parent.addressAt(indexInParent + 1) == -address); } - int siblingAddress = parent.addressAt(indexInParent); - sibling.setAddress(-siblingAddress); + BtreeIndexNodeView sibling = new BtreeIndexNodeView(btree); + sibling.setAddress(-parent.addressAt(indexInParent)); - if (!sibling.isFull() && sibling.getChildrenCount() + 1 != sibling.getMaxChildrenCount()) { + final int toMove = (sibling.getMaxChildrenCount() - sibling.getChildrenCount()) / 2; + + if (toMove > 0) { if (doSanityCheck) { sibling.dump("Offloading to left sibling"); parent.dump("parent before"); } - sibling.insert(keyAt(0), addressAt(0)); + for(int i = 0; i < toMove; ++i) sibling.insert(keyAt(i), addressAt(i)); if (doSanityCheck) { sibling.dump("Left sibling after"); } - parent.setKeyAt(indexInParent, keyAt(1)); + parent.setKeyAt(indexInParent, keyAt(toMove)); + + int indexOfLastChildToMove = (int)getChildrenCount() - toMove; + btree.movedMembersCount += indexOfLastChildToMove; - int indexOflastChildToMove = getChildrenCount() - 1; if (btree.isLarge) { - final int bytesToMove = indexOflastChildToMove * INTERIOR_SIZE; - getBytes(indexToOffset(1), btree.buffer, 0, bytesToMove); + final int bytesToMove = indexOfLastChildToMove * INTERIOR_SIZE; + getBytes(indexToOffset(toMove), btree.buffer, 0, bytesToMove); putBytes(indexToOffset(0), btree.buffer, 0, bytesToMove); } else { - for (int i = 0; i < indexOflastChildToMove; ++i) { - setAddressAt(i, addressAt(i + 1)); - setKeyAt(i, keyAt(i + 1)); + for (int i = 0; i < indexOfLastChildToMove; ++i) { + setAddressAt(i, addressAt(i + toMove)); + setKeyAt(i, keyAt(i + toMove)); } } - setChildrenCount((short)indexOflastChildToMove); + setChildrenCount((short)indexOfLastChildToMove); } else if (indexInParent + 1 < parent.getChildrenCount()) { - insertToRightSibling(parent, indexInParent + 1, sibling); + insertToRightSiblingWhenSorted(parent, indexInParent + 1, sibling); } - // TODO: move members in non leaf level + handle cases below - } /*else if (indexInParent == -1) { - insertToRightSibling(parent, 0, sibling); - } else { - int a = 1; - }*/ + } else if (indexInParent == -1) { + insertToRightSiblingWhenSorted(parent, 0, new BtreeIndexNodeView(btree)); + } if (!isFull()) { sync(); @@ -660,19 +663,19 @@ abstract class IntToIntBtree { return false; } - private void insertToRightSibling(BtreeIndexNodeView parent, int indexInParent, BtreeIndexNodeView sibling) { - int siblingAddress; - siblingAddress = parent.addressAt(indexInParent + 1); - sibling.setAddress(-siblingAddress); + private void insertToRightSiblingWhenSorted(BtreeIndexNodeView parent, int indexInParent, BtreeIndexNodeView sibling) { + sibling.setAddress(-parent.addressAt(indexInParent + 1)); + int toMove = (sibling.getMaxChildrenCount() - sibling.getChildrenCount()) / 2; - if (!sibling.isFull() && sibling.getChildrenCount() + 1 != sibling.getMaxChildrenCount()) { + if (toMove > 0) { if (doSanityCheck) { sibling.dump("Offloading to right sibling"); parent.dump("parent before"); } - int lastChildIndex = getChildrenCount() - 1; - sibling.insert(keyAt(lastChildIndex), addressAt(lastChildIndex)); + int childrenCount = getChildrenCount(); + int lastChildIndex = childrenCount - toMove; + for(int i = lastChildIndex; i < childrenCount; ++i) sibling.insert(keyAt(i), addressAt(i)); if (doSanityCheck) { sibling.dump("Right sibling after"); } @@ -683,6 +686,11 @@ abstract class IntToIntBtree { private void dump(String s) { if (doDump) { + immediateDump(s); + } + } + + private void immediateDump(String s) { short maxIndex = getChildrenCount(); System.out.println(s + " @" + address); for(int i = 0; i < maxIndex; ++i) { @@ -696,7 +704,6 @@ abstract class IntToIntBtree { System.out.println(); } } - } private int locate(int valueHC, boolean split) { int searched = 0; From 5bf66b102a6abef7e5ad8ac16c6d5506902e59d5 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 15:14:48 +0200 Subject: [PATCH 18/41] geget problem: typing anything during interruptible copy commit when there's already a lookup should lead to completion restart --- .../completion/JavaAutoPopupTest.groovy | 129 ++++++++++++++---- .../CompletionAutoPopupTestCase.groovy | 31 +++-- .../CompletionProgressIndicator.java | 2 +- 3 files changed, 121 insertions(+), 41 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 08cf1e0800f7..a69074d6fee9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -312,14 +312,14 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { } """) edt { myFixture.type 'A' } - joinAlarm() // completion started + joinAutopopup() // completion started boolean tooQuick = false edt { tooQuick = lookup == null myFixture.type 'IO' } - joinAlarm() //I - joinAlarm() //O + joinAutopopup() //I + joinAutopopup() //O joinCompletion() assert lookup assert 'ArrayIndexOutOfBoundsException' in myFixture.lookupElementStrings @@ -495,7 +495,7 @@ public interface Test { }""" edt { myFixture.type 'A' } - joinAlarm() + joinAutopopup() def first = lookup assert first edt { @@ -503,9 +503,9 @@ public interface Test { lookup.hide() myFixture.type 'a' } - joinAlarm() - joinAlarm() - joinAlarm() + joinAutopopup() + joinAutopopup() + joinAutopopup() assert lookup != first } @@ -519,25 +519,24 @@ public interface Test { } public void testDuringCompletionMustFinish() { + registerLongCompletionContributor() + + edt { myFixture.addFileToProject 'directory/foo.txt', '' } + myFixture.configureByText "a.java", 'public interface Test { RuntiExcexxx }' + myFixture.completeBasic() + while (!lookup.items) { + Thread.sleep(10) + edt { lookup.refreshUi() } + } + edt { myFixture.type '\t' } + myFixture.checkResult 'public interface Test { RuntimeExceptionx }' + } + + private def registerLongCompletionContributor() { def ep = Extensions.rootArea.getExtensionPoint("com.intellij.completion.contributor") def bean = new CompletionContributorEP(language: 'JAVA', implementationClass: LongReplacementOffsetContributor.name) ep.registerExtension(bean, LoadingOrder.LAST) - - try { - edt { myFixture.addFileToProject 'directory/foo.txt', '' } - myFixture.configureByText "a.java", 'public interface Test { RuntiExcexxx }' - myFixture.completeBasic() - while (!lookup.items) { - Thread.sleep(10) - edt { lookup.refreshUi() } - } - edt { myFixture.type '\t' } - myFixture.checkResult 'public interface Test { RuntimeExceptionx }' - } - finally { - ep.unregisterExtension(bean) - } - + disposeOnTearDown({ ep.unregisterExtension(bean) } as Disposable) } public void testLeftRightMovements() { @@ -563,7 +562,7 @@ public interface Test { assertEquals 'iterable', lookup.currentItem.lookupString edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT) } - joinAlarm() + joinAutopopup() joinCompletion() assert lookup.items.size() > 3 @@ -595,7 +594,7 @@ public interface Test { wca.execute() assert 'x' == another.document.text } - joinAlarm() + joinAutopopup() joinCompletion() LookupImpl l1 = LookupManager.getActiveLookup(another) if (l1) { @@ -680,11 +679,89 @@ class Foo { public void testNoAutopopupAfterSpace() { myFixture.configureByText("a.java", """ class Foo { { int newa; } } """) edt { myFixture.type('new ') } - joinAlarm() + joinAutopopup() joinCompletion() assert !lookup } + public void testRestartAndTypingDuringCopyCommit() { + registerLongCompletionContributor() + + myFixture.configureByText("a.java", """ class Foo { { int newa; } } """) + myFixture.type 'n' + joinAutopopup() + myFixture.type 'e' + joinCommit() // original commit + myFixture.type 'w' + joinAutopopup() + joinCompletion() + myFixture.type '\n' + myFixture.checkResult(" class Foo { { int newa; new } } ") + assert !lookup + } + + private void joinSomething(int degree) { + if (degree == 0) return + joinAlarm() + if (degree == 1) return + joinCommit() + if (degree == 2) return + joinCommit() + if (degree == 3) return + edt {} + if (degree == 4) return + joinCompletion() + } + + public void testEveryPossibleWayToTypeIf() { + def src = "class Foo { { int ifa; } }" + def result = "class Foo { { int ifa; if } }" + int actions = 5 + + for (a1 in 0..actions) { + for (a2 in 0..actions) { + myFixture.configureByText("$a1 $a2 .java", src) + myFixture.type 'i' + joinSomething(a1) + myFixture.type 'f' + joinSomething(a2) + myFixture.type ' ' + + joinAutopopup() + joinCompletion() + myFixture.checkResult(result) + assert !lookup + } + } + + for (a1 in 0..actions) { + myFixture.configureByText("$a1 if .java", src) + edt { myFixture.type 'if' } + joinSomething(a1) + + myFixture.type ' ' + + joinAutopopup() + joinCompletion() + myFixture.checkResult(result) + assert !lookup + } + + for (a1 in 0..actions) { + myFixture.configureByText("$a1 if .java", src) + myFixture.type 'i' + joinSomething(a1) + + edt { myFixture.type 'f ' } + + joinAutopopup() + joinCompletion() + myFixture.checkResult(result) + assert !lookup + } + + } + public void testNonFinishedParameterComma() { myFixture.configureByText("a.java", """ class Foo { void foo(int aaa, int aaaaa) { foo() } } """) type 'a,' diff --git a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy index 802c1dcb630c..34912ef0d2b3 100644 --- a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy +++ b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionAutoPopupTestCase.groovy @@ -16,18 +16,17 @@ package com.intellij.codeInsight.completion import com.intellij.codeInsight.AutoPopupController -import com.intellij.codeInsight.CodeInsightSettings import com.intellij.codeInsight.completion.impl.CompletionServiceImpl import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler import com.intellij.codeInsight.lookup.LookupManager import com.intellij.codeInsight.lookup.impl.LookupImpl +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.ex.DocumentEx import com.intellij.psi.PsiDocumentManager -import com.intellij.testFramework.PlatformTestUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.util.concurrency.Semaphore import com.intellij.util.ui.UIUtil import java.util.concurrent.atomic.AtomicBoolean -import com.intellij.openapi.application.ApplicationManager /** * @author peter @@ -58,17 +57,12 @@ abstract class CompletionAutoPopupTestCase extends LightCodeInsightFixtureTestCa for (i in 0..= 10000) { + fail('too long waiting for a document to be committed') + } UIUtil.pump(); } } - protected void joinAlarm() { - joinCommit() - edt { PlatformTestUtil.waitForAlarm(CodeInsightSettings.instance.AUTO_LOOKUP_DELAY)} + protected void joinAutopopup() { + joinAlarm(); + joinCommit() // physical document commit + joinCommit() // file copy commit in background + } + + protected def joinAlarm() { + AutoPopupController.getInstance(getProject()).executePendingRequests() } @Override protected void runTest() { 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 f028179b006f..86ef2a2f74db 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -599,7 +599,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void scheduleRestart() { - if (isAutopopupCompletion() && hideAutopopupIfMeaningless()) { + if (isAutopopupCompletion() && (!myProcessingDelayedActions || hideAutopopupIfMeaningless())) { AutoPopupController.getInstance(getProject()).scheduleAutoPopup(myEditor, null); return; } From 5284c4d77af57d578af81e196e93bae53ffe826f Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 15:15:10 +0200 Subject: [PATCH 19/41] invoke subtreeChanged on (almost) every raw AST change --- .../intellij/lang/impl/PsiBuilderImpl.java | 8 ++--- .../intellij/psi/impl/source/PsiFileImpl.java | 2 +- .../impl/source/tree/CompositeElement.java | 36 +++++++++++++------ .../source/tree/LazyParseableElement.java | 6 ++-- .../psi/impl/source/tree/TreeElement.java | 35 ++++++++++++++++-- .../injected/InjectedFileViewProvider.java | 6 ++++ .../tree/injected/MultiHostRegistrarImpl.java | 7 +++- 7 files changed, 78 insertions(+), 22 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index e2771e9d08e3..fc487e4f4263 100644 --- a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1068,7 +1068,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { curMarker = marker; final CompositeElement childNode = createComposite(marker); - curNode.rawAddChildren(childNode); + curNode.rawAddChildrenWithoutNotifications(childNode); curNode = childNode; item = marker.myFirstChild != null ? marker.myFirstChild : marker.myDoneMarker; @@ -1080,7 +1080,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } else if (item instanceof ErrorItem) { final CompositeElement errorElement = Factory.createErrorElement(((ErrorItem)item).myMessage); - curNode.rawAddChildren(errorElement); + curNode.rawAddChildrenWithoutNotifications(errorElement); } else if (item instanceof DoneMarker) { curMarker = (StartMarker)((DoneMarker)item).myStart.myParent; @@ -1101,7 +1101,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { if (start < end || myLexTypes[curToken] instanceof ILeafElementType) { // Empty token. Most probably a parser directive like indent/dedent in Python final IElementType type = myLexTypes[curToken]; final TreeElement leaf = createLeaf(type, start, end); - curNode.rawAddChildren(leaf); + curNode.rawAddChildrenWithoutNotifications(leaf); } curToken++; } @@ -1113,7 +1113,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { final int start = myLexStarts[startMarker.myLexemeIndex]; final int end = myLexStarts[startMarker.myDoneMarker.myLexemeIndex]; final TreeElement leaf = createLeaf(startMarker.myType, start, end); - ast.rawAddChildren(leaf); + ast.rawAddChildrenWithoutNotifications(leaf); return startMarker.myDoneMarker.myLexemeIndex; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index dd0eda459d07..69665fdbe69e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -323,7 +323,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF final CompositeElement xxx = ASTFactory.composite(myElementType); assert xxx instanceof FileElement : "BUMM"; treeElement = (FileElement)xxx; - treeElement.rawAddChildren(contentLeaf); + treeElement.rawAddChildrenWithoutNotifications(contentLeaf); } if (CacheUtil.isCopy(this)) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index 49420ee81e25..7d9c6f2def0e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -75,7 +75,7 @@ public class CompositeElement extends TreeElement { clone.myModificationsCount = 0; clone.myWrapper = null; for (ASTNode child = rawFirstChild(); child != null; child = child.getTreeNext()) { - clone.rawAddChildren((TreeElement)child.clone()); + clone.rawAddChildrenWithoutNotifications((TreeElement)child.clone()); } clone.clearCaches(); } @@ -88,7 +88,7 @@ public class CompositeElement extends TreeElement { while(compositeElement != null) { compositeElement.clearCaches(); if (!(compositeElement instanceof PsiElement)) { - final PsiElement psi = compositeElement.getPsi(); + final PsiElement psi = compositeElement.myWrapper; if (psi instanceof ASTDelegatePsiElement) { ((ASTDelegatePsiElement)psi).subtreeChanged(); } @@ -133,7 +133,7 @@ public class CompositeElement extends TreeElement { myModificationsCount++; myHC = -1; - + clearRelativeOffsets(rawFirstChild()); } @@ -231,7 +231,14 @@ public class CompositeElement extends TreeElement { @NotNull public char[] textToCharArray() { + int startStamp = myModificationsCount; + final int len = getTextLength(); + + if (startStamp != myModificationsCount) { + throw new AssertionError("Tree changed while calculating text"); + } + char[] buffer = new char[len]; final int endOffset; try { @@ -239,7 +246,7 @@ public class CompositeElement extends TreeElement { } catch (ArrayIndexOutOfBoundsException e) { @NonNls String msg = "Underestimated text length: " + len; - msg += diagnoseTextInconsistency(new String(buffer)); + msg += diagnoseTextInconsistency(new String(buffer), startStamp); try { int length = AstBufferUtil.toBuffer(this, new char[len], 0); msg += ";\n repetition gives success (" + length + ")"; @@ -251,14 +258,16 @@ public class CompositeElement extends TreeElement { } if (endOffset != len) { @NonNls String msg = "len=" + len + ";\n endOffset=" + endOffset; - msg += diagnoseTextInconsistency(new String(buffer, 0, endOffset)); + msg += diagnoseTextInconsistency(new String(buffer, 0, endOffset), startStamp); throw new AssertionError(msg); } return buffer; } - private String diagnoseTextInconsistency(String text) { - @NonNls String msg = ";\n buffer=" + text; + private String diagnoseTextInconsistency(String text, int startStamp) { + @NonNls String msg = ""; + msg += ";\n changed=" + (startStamp != myModificationsCount); + msg += ";\n buffer=" + text; msg += ";\n this=" + this; int shitStart = textMatches(text, 0); msg += ";\n matches until " + shitStart; @@ -596,6 +605,7 @@ public class CompositeElement extends TreeElement { void setFirstChildNode(TreeElement firstChild) { this.firstChild = firstChild; + clearRelativeOffsets(firstChild); } void setLastChildNode(TreeElement lastChild) { @@ -753,11 +763,17 @@ public class CompositeElement extends TreeElement { myWrapper = psi; } - public void rawAddChildren(@NotNull TreeElement first) { + public final void rawAddChildren(@NotNull TreeElement first) { + rawAddChildrenWithoutNotifications(first); + + subtreeChanged(); + } + + public void rawAddChildrenWithoutNotifications(TreeElement first) { final TreeElement last = getLastChildNode(); if (last == null){ + first.rawRemoveUpToWithoutNotifications(null); setFirstChildNode(first); - first.setTreePrev(null); while(true){ final TreeElement treeNext = first.getTreeNext(); first.setTreeParent(this); @@ -768,7 +784,7 @@ public class CompositeElement extends TreeElement { first.setTreeParent(this); } else { - last.rawInsertAfterMe(first); + last.rawInsertAfterMeWithoutNotifications(first); } DebugUtil.checkTreeStructure(this); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index 467e66230ddc..9e81d3621f26 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -175,7 +175,7 @@ public class LazyParseableElement extends CompositeElement { myText = null; if (parsedNode == null) return; - rawAddChildren((TreeElement)parsedNode); + rawAddChildrenWithoutNotifications((TreeElement)parsedNode); //if (getNotCachedLength() != text.length()) { // if (ApplicationManagerEx.getApplicationEx().isInternal()) { @@ -194,11 +194,11 @@ public class LazyParseableElement extends CompositeElement { } @Override - public void rawAddChildren(@NotNull TreeElement first) { + public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) { if (myText() != null) { LOG.error("Mutating collapsed chameleon"); } - super.rawAddChildren(first); + super.rawAddChildrenWithoutNotifications(first); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java index 2e90e7e13e04..499c9cc0b3b2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java @@ -28,6 +28,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.util.CharTable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class TreeElement extends ElementBase implements ASTNode, Cloneable { public static final TreeElement[] EMPTY_ARRAY = new TreeElement[0]; @@ -227,6 +228,9 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea } setTreePrev(firstNew); firstNew.setTreeNext(this); + if (p != null) { + p.subtreeChanged(); + } } else anchorPrev.rawInsertAfterMe(firstNew); @@ -234,7 +238,16 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea } public void rawInsertAfterMe(@NotNull TreeElement firstNew) { - firstNew.rawRemoveUpToLast(); + rawInsertAfterMeWithoutNotifications(firstNew); + + final CompositeElement parent = getTreeParent(); + if (parent != null) { + parent.subtreeChanged(); + } + } + + protected final void rawInsertAfterMeWithoutNotifications(TreeElement firstNew) { + firstNew.rawRemoveUpToWithoutNotifications(null); final CompositeElement p = getTreeParent(); final TreeElement treeNext = getTreeNext(); firstNew.setTreePrev(this); @@ -288,12 +301,17 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea public void rawReplaceWithList(TreeElement firstNew) { if (firstNew != null){ - rawInsertAfterMe(firstNew); + rawInsertAfterMeWithoutNotifications(firstNew); } rawRemove(); } protected void invalidate() { + CompositeElement parent = getTreeParent(); + if (parent != null) { + parent.subtreeChanged(); + } + // invalidate replaced element setTreeNext(null); setTreePrev(null); @@ -306,7 +324,18 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea } // remove nodes from this[including] to end[excluding] from the parent - public void rawRemoveUpTo(TreeElement end) { + public void rawRemoveUpTo(@Nullable TreeElement end) { + CompositeElement parent = getTreeParent(); + + rawRemoveUpToWithoutNotifications(end); + + if (parent != null) { + parent.subtreeChanged(); + } + } + + // remove nodes from this[including] to end[excluding] from the parent + protected final void rawRemoveUpToWithoutNotifications(TreeElement end) { if(this == end) return; final CompositeElement parent = getTreeParent(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java index 7878c22b3b63..240be2f40dce 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java @@ -47,6 +47,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider { return false; } }; + private boolean myPatchingLeaves; InjectedFileViewProvider(@NotNull PsiManager psiManager, @NotNull VirtualFileWindow virtualFile, @@ -64,6 +65,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider { public void rootChanged(PsiFile psiFile) { super.rootChanged(psiFile); if (!isPhysical()) return; // injected PSI change happened inside reparse; ignore + if (myPatchingLeaves) return; List shreds; synchronized (myLock) { @@ -171,4 +173,8 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider { public String toString() { return "Injected file '"+getVirtualFile().getName()+"' " + (isValid() ? "" : " invalid") + (isPhysical() ? "" : " nonphysical"); } + + public void setPatchingLeaves(boolean patchingLeaves) { + myPatchingLeaves = patchingLeaves; + } } 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 eb92d6b56472..eb9eb8cd01fb 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 @@ -226,6 +226,8 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar { String documentText = documentWindow.getText(); assert outChars.toString().equals(parsedNode.getText()) : exceptionContext("Before patch: doc:\n'" + documentText + "'\n---PSI:\n'" + parsedNode.getText() + "'\n---chars:\n'"+outChars+"'"); + + viewProvider.setPatchingLeaves(true); try { patchLeafs(parsedNode, escapers, place); } @@ -235,10 +237,13 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar { catch (RuntimeException e) { throw new RuntimeException(exceptionContext("Patch error"), e); } + finally { + viewProvider.setPatchingLeaves(false); + } assert parsedNode.getText().equals(documentText) : exceptionContext("After patch: doc:\n'" + documentText + "'\n---PSI:\n'" + parsedNode.getText() + "'\n---chars:\n'"+outChars+"'"); virtualFile.setContent(null, documentWindow.getText(), false); - + cacheEverything(place, documentWindow, viewProvider, psiFile, pointer); PsiFile cachedPsiFile = documentManager.getCachedPsiFile(documentWindow); From 3be69f0a28e65d8738a298e7a562651cec7c0b82 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 3 Aug 2011 16:29:52 +0400 Subject: [PATCH 20/41] scopes: hide empty location string --- .../com/intellij/ide/util/scopeChooser/ScopeEditorPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeEditorPanel.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeEditorPanel.java index d65c7aaf7219..df8137ea1f15 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeEditorPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeEditorPanel.java @@ -559,7 +559,7 @@ public class ScopeEditorPanel { } append(node.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES); final String locationString = node.getComment(); - if (locationString != null) { + if (!StringUtil.isEmpty(locationString)) { append(" (" + locationString + ")", SimpleTextAttributes.GRAY_ATTRIBUTES); } } From bd0fe15bb5070be220bdf724999fc71f66baac05 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 3 Aug 2011 17:38:51 +0400 Subject: [PATCH 21/41] scopes: leave content roots undistinguish from each other (inspired by IDEA-72774) --- .../packageSet/FilePatternPackageSet.java | 15 +++------ .../packageDependencies/ui/DirectoryNode.java | 31 ++++++++++++++----- .../ui/FileTreeModelBuilder.java | 7 ++++- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java index 65961ef852da..7d618bcb8cc8 100644 --- a/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java +++ b/platform/lang-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java @@ -73,12 +73,7 @@ public class FilePatternPackageSet extends PatternBasedPackageSet { } private boolean fileMatcher(VirtualFile virtualFile, ProjectFileIndex fileIndex, VirtualFile projectBaseDir){ - if (myModulePattern != null) { - final VirtualFile contentRoot = fileIndex.getContentRootForFile(virtualFile); - return myFilePattern.matcher(VfsUtil.getRelativePath(virtualFile, contentRoot, '/')).matches(); - } else { - return myFilePattern.matcher(getRelativePath(virtualFile, fileIndex, true, projectBaseDir)).matches(); - } + return myFilePattern.matcher(getRelativePath(virtualFile, fileIndex, true, projectBaseDir)).matches(); } public static boolean matchesModule(final Pattern moduleGroupPattern, @@ -191,6 +186,10 @@ public class FilePatternPackageSet extends PatternBasedPackageSet { final ProjectFileIndex index, final boolean useFQName, VirtualFile projectBaseDir) { + final VirtualFile contentRootForFile = index.getContentRootForFile(virtualFile); + if (contentRootForFile != null) { + return VfsUtil.getRelativePath(virtualFile, contentRootForFile, '/'); + } final Module module = index.getModuleForFile(virtualFile); if (module != null) { if (projectBaseDir != null) { @@ -201,10 +200,6 @@ public class FilePatternPackageSet extends PatternBasedPackageSet { } return virtualFile.getPath(); } else { - final VirtualFile contentRootForFile = index.getContentRootForFile(virtualFile); - if (contentRootForFile != null) { - return VfsUtil.getRelativePath(virtualFile, contentRootForFile, '/'); - } return getLibRelativePath(virtualFile, index); } } 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 453c2464584e..c6a39f56c211 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java @@ -16,6 +16,7 @@ package com.intellij.packageDependencies.ui; +import com.intellij.ide.projectView.impl.ProjectRootsUtil; import com.intellij.ide.projectView.impl.nodes.ProjectViewDirectoryHelper; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; @@ -46,10 +47,15 @@ public class DirectoryNode extends PackageDependenciesNode { private String myFQName = null; private final VirtualFile myVDirectory; - public DirectoryNode(VirtualFile aDirectory, Project project, boolean compactPackages, boolean showFQName) { + public DirectoryNode(VirtualFile aDirectory, + Project project, + boolean compactPackages, + boolean showFQName, + VirtualFile baseDir, final VirtualFile[] contentRoots) { super(project); myVDirectory = aDirectory; - final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); + final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project); + final ProjectFileIndex index = projectRootManager.getFileIndex(); String dirName = aDirectory.getName(); if (showFQName) { final VirtualFile contentRoot = index.getContentRootForFile(myVDirectory); @@ -74,6 +80,20 @@ public class DirectoryNode extends PackageDependenciesNode { myFQName = FilePatternPackageSet.getLibRelativePath(myVDirectory, index); } 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(); + } + } } myDirName = dirName; myCompactPackages = compactPackages; @@ -107,7 +127,6 @@ public class DirectoryNode extends PackageDependenciesNode { } public String getFQName() { - final StringBuffer buf = new StringBuffer(); final ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); VirtualFile directory = myVDirectory; VirtualFile contentRoot = index.getContentRootForFile(directory); @@ -117,11 +136,7 @@ public class DirectoryNode extends PackageDependenciesNode { if (contentRoot == null) { return ""; } - while (directory != null && contentRoot != directory) { - buf.insert(0, directory.getName() + "/"); - directory = directory.getParent(); - } - return buf.toString(); + return VfsUtil.getRelativePath(directory, contentRoot, '/'); } public PsiElement getPsiElement() { diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/FileTreeModelBuilder.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/FileTreeModelBuilder.java index 63e55e4d9686..bc52e51535d5 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/FileTreeModelBuilder.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/FileTreeModelBuilder.java @@ -75,9 +75,13 @@ public class FileTreeModelBuilder { private int myMarkedFileCount = 0; private JTree myTree; + protected final VirtualFile myBaseDir; + protected VirtualFile[] myContentRoots; public FileTreeModelBuilder(Project project, Marker marker, DependenciesPanel.DependencyPanelSettings settings) { myProject = project; + myBaseDir = myProject.getBaseDir(); + myContentRoots = ProjectRootManager.getInstance(myProject).getContentRoots(); final boolean multiModuleProject = ModuleManager.getInstance(myProject).getModules().length > 1; myShowModules = settings.UI_SHOW_MODULES && multiModuleProject; myFlattenPackages = settings.UI_FLATTEN_PACKAGES; @@ -434,7 +438,8 @@ public class FileTreeModelBuilder { final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(virtualFile); final VirtualFile contentRoot = fileIndex.getContentRootForFile(virtualFile); - directoryNode = new DirectoryNode(virtualFile, myProject, myCompactEmptyMiddlePackages, myFlattenPackages); + directoryNode = new DirectoryNode(virtualFile, myProject, myCompactEmptyMiddlePackages, myFlattenPackages, myBaseDir, + myContentRoots); myModuleDirNodes.put(virtualFile, (DirectoryNode)directoryNode); final VirtualFile directory = virtualFile.getParent(); From ed7f64895736463e16d2e55d22b17e7978a1d105 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 3 Aug 2011 17:32:22 +0400 Subject: [PATCH 22/41] Git IDEA-72767 find roots on a pooled thread. --- .../src/git4idea/vfs/GitRootTracker.java | 176 ++++++++++-------- 1 file changed, 95 insertions(+), 81 deletions(-) diff --git a/plugins/git4idea/src/git4idea/vfs/GitRootTracker.java b/plugins/git4idea/src/git4idea/vfs/GitRootTracker.java index 2335fb132f35..a4b9b156c156 100644 --- a/plugins/git4idea/src/git4idea/vfs/GitRootTracker.java +++ b/plugins/git4idea/src/git4idea/vfs/GitRootTracker.java @@ -294,11 +294,9 @@ public class GitRootTracker implements VcsListener { myNotification = new Notification(GIT_INVALID_ROOTS_ID, GitBundle.getString("root.tracker.message.title"), GitBundle.getString("root.tracker.message"), NotificationType.ERROR, new NotificationListener() { - public void hyperlinkUpdate(@NotNull Notification notification, + public void hyperlinkUpdate(@NotNull final Notification notification, @NotNull HyperlinkEvent event) { - if (fixRoots()) { - notification.expire(); - } + fixRoots(notification); } }); @@ -346,97 +344,113 @@ public class GitRootTracker implements VcsListener { /** * Fix mapped roots - * - * @return true if roots now in the correct state + * @param notification Expires the notification if roots are in the correct state after fix. */ - boolean fixRoots() { - final List vcsDirectoryMappings = new ArrayList(myVcsManager.getDirectoryMappings()); - final HashSet mapped = new HashSet(); - final HashSet removed = new HashSet(); - final HashSet added = new HashSet(); - final VirtualFile baseDir = myProject.getBaseDir(); - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - for (Iterator i = vcsDirectoryMappings.iterator(); i.hasNext();) { - VcsDirectoryMapping m = i.next(); - String vcsName = myVcs.getName(); - if (!vcsName.equals(m.getVcs())) { - continue; - } - String path = m.getDirectory(); - if (path.length() == 0 && baseDir != null) { - path = baseDir.getPath(); - } - VirtualFile file = lookupFile(path); - if (file != null && !mapped.add(file.getPath())) { - // eliminate duplicates - i.remove(); - continue; - } - final VirtualFile actual = GitUtil.gitRootOrNull(file); - if (file == null || actual == null) { - removed.add(path); - } - else if (actual != file) { - removed.add(path); - added.add(actual.getPath()); - } - } - for (String m : mapped) { - VirtualFile file = lookupFile(m); - if (file == null) { - continue; - } - addSubroots(file, added, mapped); - if (removed.contains(m)) { - continue; - } - VirtualFile root = GitUtil.gitRootOrNull(file); - assert root != null; - for (String o : mapped) { - // the mapped collection is not modified here, so order is being kept - if (o.equals(m) || removed.contains(o)) { - continue; + private void fixRoots(final Notification notification) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override public void run() { + final List vcsDirectoryMappings = new ArrayList(myVcsManager.getDirectoryMappings()); + final HashSet mapped = new HashSet(); + final HashSet removed = new HashSet(); + final HashSet added = new HashSet(); + + collectRoots(vcsDirectoryMappings, mapped, removed, added); + + final VirtualFile baseDir = myProject.getBaseDir(); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { + if (added.isEmpty() && removed.isEmpty()) { + Messages.showInfoMessage(myProject, GitBundle.message("fix.roots.valid.message"), GitBundle.message("fix.roots.valid.title")); + notification.expire(); + return; } - if (o.startsWith(m)) { - VirtualFile otherFile = lookupFile(m); - assert otherFile != null; - VirtualFile otherRoot = GitUtil.gitRootOrNull(otherFile); - assert otherRoot != null; - if (otherRoot == root) { - removed.add(o); - } - else if (otherFile != otherRoot) { - added.add(otherRoot.getPath()); - removed.add(o); + GitFixRootsDialog d = new GitFixRootsDialog(myProject, mapped, added, removed); + d.show(); + if (!d.isOK()) { + return; + } + + for (Iterator i = vcsDirectoryMappings.iterator(); i.hasNext(); ) { + VcsDirectoryMapping m = i.next(); + String path = m.getDirectory(); + if (removed.contains(path) || (path.length() == 0 && baseDir != null && removed.contains(baseDir.getPath()))) { + i.remove(); } } + for (String a : added) { + vcsDirectoryMappings.add(new VcsDirectoryMapping(a, myVcs.getName())); + } + myVcsManager.setDirectoryMappings(vcsDirectoryMappings); + myVcsManager.updateActiveVcss(); + notification.expire(); } - } + }); } }); - if (added.isEmpty() && removed.isEmpty()) { - Messages.showInfoMessage(myProject, GitBundle.message("fix.roots.valid.message"), GitBundle.message("fix.roots.valid.title")); - return true; - } - GitFixRootsDialog d = new GitFixRootsDialog(myProject, mapped, added, removed); - d.show(); - if (!d.isOK()) { - return false; - } + } + + private void collectRoots(List vcsDirectoryMappings, + HashSet mapped, + HashSet removed, + HashSet added) { + final VirtualFile baseDir = myProject.getBaseDir(); for (Iterator i = vcsDirectoryMappings.iterator(); i.hasNext();) { VcsDirectoryMapping m = i.next(); + String vcsName = myVcs.getName(); + if (!vcsName.equals(m.getVcs())) { + continue; + } String path = m.getDirectory(); - if (removed.contains(path) || (path.length() == 0 && baseDir != null && removed.contains(baseDir.getPath()))) { + if (path.length() == 0 && baseDir != null) { + path = baseDir.getPath(); + } + VirtualFile file = lookupFile(path); + if (file != null && !mapped.add(file.getPath())) { + // eliminate duplicates i.remove(); + continue; + } + final VirtualFile actual = GitUtil.gitRootOrNull(file); + if (file == null || actual == null) { + removed.add(path); + } + else if (actual != file) { + removed.add(path); + added.add(actual.getPath()); } } - for (String a : added) { - vcsDirectoryMappings.add(new VcsDirectoryMapping(a, myVcs.getName())); + for (String m : mapped) { + VirtualFile file = lookupFile(m); + if (file == null) { + continue; + } + addSubroots(file, added, mapped); + if (removed.contains(m)) { + continue; + } + VirtualFile root = GitUtil.gitRootOrNull(file); + assert root != null; + for (String o : mapped) { + // the mapped collection is not modified here, so order is being kept + if (o.equals(m) || removed.contains(o)) { + continue; + } + if (o.startsWith(m)) { + VirtualFile otherFile = lookupFile(m); + assert otherFile != null; + VirtualFile otherRoot = GitUtil.gitRootOrNull(otherFile); + assert otherRoot != null; + if (otherRoot == root) { + removed.add(o); + } + else if (otherFile != otherRoot) { + added.add(otherRoot.getPath()); + removed.add(o); + } + } + } } - myVcsManager.setDirectoryMappings(vcsDirectoryMappings); - myVcsManager.updateActiveVcss(); - return true; } /** From 329366efa5ca3a4fd996469ac9ea0c1888ae3db7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 3 Aug 2011 17:37:34 +0400 Subject: [PATCH 23/41] GitRepositoryReader: .git/packed-refs may not exist - don't fail in that case. --- plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java index 6e3f30656766..1d888711223c 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java @@ -303,6 +303,9 @@ class GitRepositoryReader { private GitBranchesCollection readPackedBranches() { final Set localBranches = new HashSet(); final Set remoteBranches = new HashSet(); + if (!myPackedRefsFile.exists()) { + return GitBranchesCollection.EMPTY; + } final String content = tryLoadFile(myPackedRefsFile); for (String line : content.split("\n")) { @@ -354,6 +357,7 @@ class GitRepositoryReader { throw new GitRepoStateException("Invalid format of the .git/HEAD file: \n" + headContent); } + @NotNull private static String tryLoadFile(final File file) { return tryOrThrow(new Callable() { @Override From 35a452ad461f74805b324d79ecba5241d3cbed3e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 3 Aug 2011 17:56:17 +0400 Subject: [PATCH 24/41] misprint --- .../src/git4idea/checkin/GitPushActiveBranchesDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java index 7b6b0686f3f7..24629773717d 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java +++ b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java @@ -222,7 +222,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { private GitPushActiveBranchesDialog myDialog; public DialogInitTask(Project project, List vcsRoots, Collection exceptions) { - super(project, "Collection information for push", false); + super(project, "Collecting information for push", false); myProject = project; myVcsRoots = vcsRoots; myExceptions = exceptions; From 74f59fb198bcc5dd79d3f9bc7ae7b660c81841d6 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 3 Aug 2011 18:43:54 +0400 Subject: [PATCH 25/41] revert: use smart type pointers to preserve types instead of classes (IDEA-72807 ) --- .../TooBroadThrowsInspection.java | 69 ++++++++++--------- .../NotFoundInsteadOfIOException.after.java | 5 ++ .../NotFoundInsteadOfIOException.java | 5 ++ .../TooBroadThrowsInspectionTest.java | 33 +++++++++ 4 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java index dc79c69183b4..7b231a1e2a9e 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java @@ -47,29 +47,33 @@ public class TooBroadThrowsInspection extends BaseInspection { "overly.broad.throws.clause.display.name"); } - @Override @NotNull + @Override + @NotNull protected String buildErrorString(Object... infos) { - final List typesMasked = (List)infos[0]; - String typesMaskedString = typesMasked.get(0).getName(); + final List typesMasked = (List)infos[0]; + final PsiType type = typesMasked.get(0).getType(); + String typesMaskedString = type != null ? type.getPresentableText() : ""; if (typesMasked.size() == 1) { return InspectionGadgetsBundle.message( - "overly.broad.throws.clause.problem.descriptor1", - typesMaskedString); - } else { + "overly.broad.throws.clause.problem.descriptor1", + typesMaskedString); + } + else { final int lastTypeIndex = typesMasked.size() - 1; for (int i = 1; i < lastTypeIndex; i++) { - typesMaskedString += ", "; - typesMaskedString += typesMasked.get(i).getName(); + final PsiType psiType = typesMasked.get(i).getType(); + if (psiType != null) { + typesMaskedString += ", "; + typesMaskedString += psiType.getPresentableText(); + } } - final String lastTypeString = - typesMasked.get(lastTypeIndex).getName(); - return InspectionGadgetsBundle.message( - "overly.broad.throws.clause.problem.descriptor2", - typesMaskedString, lastTypeString); + final PsiType psiType = typesMasked.get(lastTypeIndex).getType(); + final String lastTypeString = psiType != null ? psiType.getPresentableText() : ""; + return InspectionGadgetsBundle.message("overly.broad.throws.clause.problem.descriptor2", typesMaskedString, lastTypeString); } } - @Override + @Override public JComponent createOptionsPanel() { return new SingleCheckboxOptionsPanel( InspectionGadgetsBundle.message("too.broad.catch.option"), @@ -79,23 +83,21 @@ public class TooBroadThrowsInspection extends BaseInspection { @NotNull @Override protected InspectionGadgetsFix buildFix(Object... infos) { - final Collection maskedExceptions = - (Collection)infos[0]; + final Collection maskedExceptions = + (Collection)infos[0]; final Boolean originalNeeded = (Boolean) infos[1]; return new AddThrowsClauseFix(maskedExceptions, originalNeeded.booleanValue()); } private static class AddThrowsClauseFix extends InspectionGadgetsFix { - private final Collection> types; + + private final Collection types; private final boolean originalNeeded; - AddThrowsClauseFix(@NotNull Collection classes, + AddThrowsClauseFix(Collection types, boolean originalNeeded) { - types = new ArrayList>(); - for (PsiClass type : classes) { - types.add(SmartPointerManager.getInstance(type.getProject()).createSmartPsiElementPointer(type)); - } + this.types = types; this.originalNeeded = originalNeeded; } @@ -124,12 +126,13 @@ public class TooBroadThrowsInspection extends BaseInspection { if (!originalNeeded) { element.delete(); } - for (SmartPsiElementPointer type : types) { - PsiClass aClass = type.getElement(); - if (aClass == null) continue; - final PsiJavaCodeReferenceElement referenceElement = - factory.createReferenceExpression(aClass); + for (SmartTypePointer type : types) { + final PsiType psiType = type.getType(); + if (psiType instanceof PsiClassType) { + final PsiJavaCodeReferenceElement referenceElement = + factory.createReferenceElementByType((PsiClassType)psiType); referenceList.add(referenceElement); + } } } } @@ -172,14 +175,12 @@ public class TooBroadThrowsInspection extends BaseInspection { continue; } } - final List exceptionsMasked = new ArrayList(); - for (PsiClassType exceptionThrown : exceptionsThrown) { + final List exceptionsMasked = new ArrayList(); + final SmartTypePointerManager pointerManager = SmartTypePointerManager.getInstance(body.getProject()); + for (PsiClassType exceptionThrown : exceptionsThrown) { if (referencedException.isAssignableFrom(exceptionThrown) && !exceptionsDeclared.contains(exceptionThrown)) { - PsiClass aClass = exceptionThrown.resolve(); - if (aClass != null) { - exceptionsMasked.add(aClass); - } + exceptionsMasked.add(pointerManager.createSmartTypePointer(exceptionThrown)); } } if (!exceptionsMasked.isEmpty()) { @@ -193,4 +194,4 @@ public class TooBroadThrowsInspection extends BaseInspection { } } } -} +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.after.java new file mode 100644 index 000000000000..3194b1c29e55 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.after.java @@ -0,0 +1,5 @@ +class Foo{ + void foo() throws FileNotFoundException { + throw new FileNotFoundException(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.java new file mode 100644 index 000000000000..458eb54cd696 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/toobroadthrows/NotFoundInsteadOfIOException.java @@ -0,0 +1,5 @@ +class Foo{ + void foo() throws IOException { + throw new FileNotFoundException(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionTest.java new file mode 100644 index 000000000000..d235bf8336c1 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionTest.java @@ -0,0 +1,33 @@ +/* + * 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.siyeh.ig.errorhandling; + +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.IGQuickFixesTestCase; + +public class TooBroadThrowsInspectionTest extends IGQuickFixesTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new TooBroadThrowsInspection()); + myRelativePath = "toobroadthrows"; + myDefaultHint = InspectionGadgetsBundle.message("overly.broad.throws.clause.quickfix2"); + } + + public void testNotFoundInsteadOfIOException() { + doTest(); + } +} \ No newline at end of file From b9168340db4ccf55643b3e0e265bd8f13717e05a Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 3 Aug 2011 18:54:02 +0400 Subject: [PATCH 26/41] ability to offload to siblings when using hashed page representation for btree --- .../com/intellij/util/io/IntToIntBtree.java | 248 ++++++++++++++---- 1 file changed, 202 insertions(+), 46 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index b6996a1b3f78..3134449a6af5 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -280,6 +280,7 @@ abstract class IntToIntBtree { static class BtreeIndexNodeView extends BtreePage { static final int INTERIOR_SIZE = 8; static final int KEY_OFFSET = 4; + static final int MIN_ITEMS_TO_SHARE = 20; private boolean isIndexLeaf; private boolean isIndexLeafSet; @@ -449,19 +450,62 @@ abstract class IntToIntBtree { return keys; } - private int splitNode(int parentAddress) { - if (doSanityCheck) { - myAssert(isFull()); - dump("before split:"+isIndexLeaf()); + static class HashLeafData { + final BtreeIndexNodeView nodeView; + final int[] keys; + final TIntIntHashMap values; + + HashLeafData(BtreeIndexNodeView _nodeView, int recordCount) { + nodeView = _nodeView; + final IntToIntBtree btree = _nodeView.btree; + nodeView.getBytes(nodeView.indexToOffset(0), btree.buffer, 0, btree.pageSize - btree.metaDataLeafPageLength); + keys = new int[recordCount]; + values = new TIntIntHashMap(recordCount); + int keyNumber = 0; + + for(int i = 0; i < btree.hashPageCapacity; ++i) { + if (nodeView.hashGetState(i) == HASH_FULL) { + int key = Bits.getInt(btree.buffer, i * INTERIOR_SIZE + KEY_OFFSET); + keys[keyNumber++] = key; + values.put(key, Bits.getInt(btree.buffer, i * INTERIOR_SIZE)); + } + } + + Arrays.sort(keys); } + void clean() { + final IntToIntBtree btree = nodeView.btree; + for(int i = 0; i < btree.hashPageCapacity; ++i) { + nodeView.hashSetState(i, HASH_FREE); + } + } + } + + private int splitNode(int parentAddress) { + final boolean indexLeaf = isIndexLeaf(); + + if (doSanityCheck) { + myAssert(isFull()); + dump("before split:"+indexLeaf); + } + + final boolean hashedLeaf = isHashedLeaf(); + final short recordCount = getChildrenCount(); BtreeIndexNodeView parent = null; + HashLeafData hashLeafData = null; if (parentAddress != 0) { parent = new BtreeIndexNodeView(btree); parent.setAddress(parentAddress); + if (btree.offloadToSiblingsBeforeSplit) { - if (doOffloadToSiblingsSorted(parent)) return parentAddress; + if (hashedLeaf) { + hashLeafData = new HashLeafData(this, recordCount); + if (doOffloadToSiblingsWhenHashed(parent, hashLeafData)) return parentAddress; + } else { + if (doOffloadToSiblingsSorted(parent)) return parentAddress; + } } } @@ -470,60 +514,74 @@ abstract class IntToIntBtree { BtreeIndexNodeView newIndexNode = new BtreeIndexNodeView(btree); newIndexNode.setAddress(btree.nextPage(false)); - boolean indexLeaf = isIndexLeaf(); newIndexNode.setIndexLeaf(indexLeaf); int nextPage = getNextPage(); setNextPage(newIndexNode.address); newIndexNode.setNextPage(nextPage); - final short recordCount = getChildrenCount(); + int medianKey = -1; - int medianKey; + if (indexLeaf && hashedLeaf) { + if (hashLeafData == null) hashLeafData = new HashLeafData(this, recordCount); + final int[] keys = hashLeafData.keys; - if (indexLeaf && isHashedLeaf()) { - TIntIntHashMap map = new TIntIntHashMap(recordCount); - getBytes(indexToOffset(0), btree.buffer, 0, btree.pageSize - btree.metaDataLeafPageLength); - int[] keys = new int[recordCount]; - int keyNumber = 0; - - for(int i = 0; i < btree.hashPageCapacity; ++i) { - if (hashGetState(i) == HASH_FULL) { - int key = Bits.getInt(btree.buffer, i * INTERIOR_SIZE + KEY_OFFSET); - keys[keyNumber++] = key; - map.put(key, Bits.getInt(btree.buffer, i * INTERIOR_SIZE)); - hashSetState(i, HASH_FREE); + boolean defaultSplit = true; + + //if (keys[keys.length - 1] < newValue && btree.height <= 3 && false) { + // btree.root.setAddress(btree.root.address); + // if (btree.height == 2 && btree.root.search(keys[0]) == btree.root.getChildrenCount() - 1) { + // defaultSplit = false; + // } else if (btree.height == 3 && + // btree.root.search(keys[0]) == -btree.root.getChildrenCount() && + // parent.search(keys[0]) == parent.getChildrenCount() - 1 + // ) { + // defaultSplit = false; + // } + // + // if (!defaultSplit) { + // newIndexNode.setChildrenCount((short)0); + // newIndexNode.insert(newValue, 0); + // ++btree.count; + // medianKey = newValue; + // } + //} + + if (defaultSplit) { + hashLeafData.clean(); + + final TIntIntHashMap map = hashLeafData.values; + + final int avg = keys.length / 2; + medianKey = keys[avg]; + --btree.hashedPagesCount; + setChildrenCount((short)0); + newIndexNode.setChildrenCount((short)0); + + for(int i = 0; i < avg; ++i) { + int key = keys[i]; + insert(key, map.get(key)); + key = keys[avg + i]; + newIndexNode.insert(key, map.get(key)); } + + /*setHashedLeaf(false); + setChildrenCount((short)keys.length); + + --btree.hashedPagesCount; + btree.movedMembersCount += keys.length; + + for(int i = 0; i < keys.length; ++i) { + int key = keys[i]; + setKeyAt(i, key); + setAddressAt(i, map.get(key)); + } + return parentAddress;*/ } - - Arrays.sort(keys); - final int avg = keys.length / 2; - medianKey = keys[avg]; - --btree.hashedPagesCount; - setChildrenCount((short)0); - newIndexNode.setChildrenCount((short)0); - - for(int i = 0; i < avg; ++i) { - insert(keys[i], map.get(keys[i])); - newIndexNode.insert(keys[avg + i], map.get(keys[avg + i])); - } - - /*setHashedLeaf(false); - setChildrenCount((short)keys.length); - - --btree.hashedPagesCount; - btree.movedMembersCount += keys.length; - - for(int i = 0; i < keys.length; ++i) { - int key = keys[i]; - setKeyAt(i, key); - setAddressAt(i, map.get(key)); - } - return parentAddress;*/ } else { short recordCountInNewNode = (short)(recordCount - maxIndex); newIndexNode.setChildrenCount(recordCountInNewNode); - + if (btree.isLarge) { final int bytesToMove = recordCountInNewNode * INTERIOR_SIZE; getBytes(indexToOffset(maxIndex), btree.buffer, 0, bytesToMove); @@ -596,6 +654,104 @@ abstract class IntToIntBtree { return parentAddress; } + private boolean doOffloadToSiblingsWhenHashed(BtreeIndexNodeView parent, final HashLeafData hashLeafData) { + int indexInParent = parent.search(hashLeafData.keys[0]); + + if (indexInParent >= 0) { + BtreeIndexNodeView sibling = new BtreeIndexNodeView(btree); + sibling.setAddress(-parent.addressAt(indexInParent)); + + int numberOfKeysToMove = (sibling.getMaxChildrenCount() - sibling.getChildrenCount()) / 2; + + if (!sibling.isFull() && numberOfKeysToMove > MIN_ITEMS_TO_SHARE) { + if (doSanityCheck) { + sibling.dump("Offloading to left sibling"); + parent.dump("parent before"); + } + + final int childrenCount = getChildrenCount(); + final int[] keys = hashLeafData.keys; + final TIntIntHashMap map = hashLeafData.values; + + for(int i = 0; i < numberOfKeysToMove; ++i) { + final int key = keys[i]; + sibling.insert(key, map.get(key)); + } + + if (doSanityCheck) { + sibling.dump("Left sibling after"); + } + + parent.setKeyAt(indexInParent, keys[numberOfKeysToMove]); + + setChildrenCount((short)0); + --btree.hashedPagesCount; + hashLeafData.clean(); + + for(int i = numberOfKeysToMove; i < childrenCount; ++i) { + final int key = keys[i]; + insert(key, map.get(key)); + } + } else if (indexInParent + 1 < parent.getChildrenCount()) { + insertToRightSiblingWhenHashed(parent, hashLeafData, indexInParent, sibling); + } + } else if (indexInParent == -1) { + insertToRightSiblingWhenHashed(parent, hashLeafData, 0, new BtreeIndexNodeView(btree)); + } + + if (!isFull()) { + sync(); + parent.sync(); + + if (doSanityCheck) { + dump("old node after split:"); + parent.dump("Parent node after split"); + } + return true; + } + + return false; + } + + private void insertToRightSiblingWhenHashed(BtreeIndexNodeView parent, + HashLeafData hashLeafData, + int indexInParent, + BtreeIndexNodeView sibling) { + sibling.setAddress(-parent.addressAt(indexInParent + 1)); + int numberOfKeysToMove = (sibling.getMaxChildrenCount() - sibling.getChildrenCount()) / 2; + + if (!sibling.isFull() && numberOfKeysToMove > MIN_ITEMS_TO_SHARE) { + if (doSanityCheck) { + sibling.dump("Offloading to right sibling"); + parent.dump("parent before"); + } + + final int[] keys = hashLeafData.keys; + final TIntIntHashMap map = hashLeafData.values; + + final int childrenCount = getChildrenCount(); + final int lastChildIndex = childrenCount - numberOfKeysToMove; + for(int i = lastChildIndex; i < childrenCount; ++i) { + final int key = keys[i]; + sibling.insert(key, map.get(key)); + } + + if (doSanityCheck) { + sibling.dump("Right sibling after"); + } + parent.setKeyAt(indexInParent, keys[lastChildIndex]); + + setChildrenCount((short)0); + --btree.hashedPagesCount; + hashLeafData.clean(); + + for(int i = 0; i < lastChildIndex; ++i) { + final int key = keys[i]; + insert(key, map.get(key)); + } + } + } + private boolean doOffloadToSiblingsSorted(BtreeIndexNodeView parent) { boolean indexLeaf = isIndexLeaf(); if (!indexLeaf) return false; // TODO From bac3c59fda4ee5ed96a72d08772d06b6f8cebac7 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 17:16:38 +0400 Subject: [PATCH 27/41] gave up --- .../impl/PushedFilePropertiesUpdater.java | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java index 77cf51035450..828e2a5f37fb 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java @@ -33,7 +33,6 @@ import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; -import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -81,7 +80,7 @@ public class PushedFilePropertiesUpdater { public void fileCreated(final VirtualFileEvent event) { final VirtualFile file = event.getFile(); final FilePropertyPusher[] pushers = file.isDirectory() ? myPushers : myFilePushers; - pushRecursively(file, pushers); + pushRecursively(file, project, pushers); } @Override @@ -91,7 +90,7 @@ public class PushedFilePropertiesUpdater { for (FilePropertyPusher pusher : pushers) { file.putUserData(pusher.getFileDataKey(), null); } - pushRecursively(file, pushers); + pushRecursively(file, project, pushers); } })); for (final FilePropertyPusher pusher : myPushers) { @@ -101,7 +100,7 @@ public class PushedFilePropertiesUpdater { } public void pushRecursively(VirtualFile file, Project project) { - PushedFilePropertiesUpdater.this.pushRecursively(file, pusher); + PushedFilePropertiesUpdater.this.pushRecursively(file, project, pusher); } }); } @@ -109,63 +108,66 @@ public class PushedFilePropertiesUpdater { }); } - private void pushRecursively(final VirtualFile dir, final FilePropertyPusher... pushers) { - - final Object[] values = new Object[pushers.length]; - VirtualFile parent = dir.getParent(); - for (int i = 0, pushersLength = pushers.length; i < pushersLength; i++) { - FilePropertyPusher pusher = pushers[i]; - if (parent != null) { - values[i] = parent.getUserData(pusher.getFileDataKey()); - } - if (values[i] == null) { - values[i] = pusher.getDefaultValue(); - } - } - iterateContentUnderDirectory(dir, values, pushers); - } - - public void pushAll(final FilePropertyPusher... pushers) { - for (Module module : ModuleManager.getInstance(myProject).getModules()) { - final Object[] values = new Object[pushers.length]; - for (int i = 0; i < values.length; i++) { - values[i] = pushers[i].getImmediateValue(module); - if (values[i] == null) { - values[i] = pushers[i].getDefaultValue(); - } - } - for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) { - iterateContentUnderDirectory(root, values, pushers); - } - } - } - - private void iterateContentUnderDirectory(VirtualFile root, - final Object[] values, - final FilePropertyPusher[] pushers) { - FileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); - index.iterateContentUnderDirectory(root, new ContentIterator() { + public void pushRecursively(final VirtualFile dir, final Project project, final FilePropertyPusher... pushers) { + if (pushers.length == 0) return; + ProjectRootManager.getInstance(project).getFileIndex().iterateContentUnderDirectory(dir, new ContentIterator() { public boolean processFile(final VirtualFile fileOrDir) { final boolean isDir = fileOrDir.isDirectory(); - for (int i = 0, pushersLength = pushers.length; i < pushersLength; i++) { - final FilePropertyPusher pusher = pushers[i]; + for (FilePropertyPusher pusher : pushers) { if (!isDir && (pusher.pushDirectoriesOnly() || !pusher.acceptsFile(fileOrDir))) continue; - values[i] = findAndUpdateValue(myProject, fileOrDir, pusher, values[i]); + findAndUpdateValue(project, fileOrDir, pusher, null); } return true; } }); } - @Nullable - public static T findAndUpdateValue(final Project project, - final VirtualFile fileOrDir, - final FilePropertyPusher pusher, - final T parentValue) { - final T immediateValue = pusher.getImmediateValue(project, fileOrDir); - final T value = immediateValue != null ? immediateValue : parentValue; + private static T findPusherValuesUpwards(final Project project, final VirtualFile dir, FilePropertyPusher pusher, T moduleValue) { + final T value = pusher.getImmediateValue(project, dir); + if (value != null) return value; + if (moduleValue != null) return moduleValue; + final VirtualFile parent = dir.getParent(); + if (parent != null) return findPusherValuesUpwards(project, parent, pusher); + return pusher.getDefaultValue(); + } + + private static T findPusherValuesUpwards(final Project project, final VirtualFile dir, FilePropertyPusher pusher) { + final T userValue = dir.getUserData(pusher.getFileDataKey()); + if (userValue != null) return userValue; + final T value = pusher.getImmediateValue(project, dir); + if (value != null) return value; + final VirtualFile parent = dir.getParent(); + if (parent != null) return findPusherValuesUpwards(project, parent, pusher); + return pusher.getDefaultValue(); + } + + public void pushAll(final FilePropertyPusher... pushers) { + for (Module module : ModuleManager.getInstance(myProject).getModules()) { + final Object[] moduleValues = new Object[pushers.length]; + for (int i = 0; i < moduleValues.length; i++) { + moduleValues[i] = pushers[i].getImmediateValue(module); + } + final ModuleRootManager rootManager = ModuleRootManager.getInstance(module); + final ModuleFileIndex index = rootManager.getFileIndex(); + for (VirtualFile root : rootManager.getContentRoots()) { + index.iterateContentUnderDirectory(root, new ContentIterator() { + public boolean processFile(final VirtualFile fileOrDir) { + final boolean isDir = fileOrDir.isDirectory(); + for (int i = 0, pushersLength = pushers.length; i < pushersLength; i++) { + final FilePropertyPusher pusher = pushers[i]; + if (!isDir && (pusher.pushDirectoriesOnly() || !pusher.acceptsFile(fileOrDir))) continue; + findAndUpdateValue(myProject, fileOrDir, pusher, moduleValues[i]); + } + return true; + } + }); + } + } + } + + public static void findAndUpdateValue(final Project project, final VirtualFile fileOrDir, final FilePropertyPusher pusher, final T moduleValue) { + final T value = findPusherValuesUpwards(project, fileOrDir, pusher, moduleValue); updateValue(fileOrDir, value, pusher); - return value; } private static void updateValue(final VirtualFile fileOrDir, final T value, final FilePropertyPusher pusher) { From dc9f3123f2bbcd648155ccdaf9894e7c5bac1207 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 3 Aug 2011 18:58:14 +0400 Subject: [PATCH 28/41] GSP tests fixed --- .../source/resolve/reference/impl/providers/FileReference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java index c6928e8fd93b..5639542ac70c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java @@ -144,7 +144,7 @@ public class FileReference implements FileReferenceOwner, PsiPolyVariantReferenc protected ResolveResult[] innerResolve(boolean caseSensitive) { final String referenceText = getText(); - if (referenceText.isEmpty()) { + if (referenceText.isEmpty() && myIndex == 0) { return new ResolveResult[] { new PsiElementResolveResult(getElement().getContainingFile())}; } final Collection contexts = getContexts(); From 12ca93fccd00f0e98ce1617ce048834e567d2cb3 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 15:49:09 +0200 Subject: [PATCH 29/41] a lookup may not become visible after show (e.g. if the application has become inactive). accept that and cancel completion (EA-27791) --- .../completion/CompletionProgressIndicator.java | 5 ++++- .../com/intellij/codeInsight/lookup/impl/LookupImpl.java | 9 ++++++--- .../codeInsight/lookup/impl/LookupManagerImpl.java | 2 +- .../codeInsight/template/impl/ListTemplatesHandler.java | 4 ++-- .../src/com/intellij/ui/TextFieldWithAutoCompletion.java | 2 +- 5 files changed, 14 insertions(+), 8 deletions(-) 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 86ef2a2f74db..a428af1005cd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -340,7 +340,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } - myLookup.show(); + if (!myLookup.showLookup()) { + myLookup.hide(); + return; + } justShown = true; } myLookup.refreshUi(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 01e9d0bbda87..2f74928c860d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -800,14 +800,14 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable return myShown; } - public void show(){ + public boolean showLookup() { ApplicationManager.getApplication().assertIsDispatchThread(); checkValid(); LOG.assertTrue(!myShown); myShown = true; myStampShown = System.currentTimeMillis(); - if (ApplicationManager.getApplication().isUnitTestMode()) return; + if (ApplicationManager.getApplication().isUnitTestMode()) return true; myAdComponent.showRandomText(); @@ -817,7 +817,9 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable Point p = calculatePosition(getComponent()); HintManagerImpl.getInstanceImpl().showEditorHint(this, myEditor, p, HintManager.HIDE_BY_ESCAPE | HintManager.UPDATE_BY_SCROLLING, 0, false, HintManagerImpl.createHintHint(myEditor, p, this, HintManager.UNDER).setAwtTooltip(false)); - LOG.assertTrue(isVisible(), "!visible, disposed=" + myDisposed); + + if (!isVisible()) return false; + LOG.assertTrue(myList.isShowing(), "!showing, disposed=" + myDisposed); final JLayeredPane layeredPane = getComponent().getRootPane().getLayeredPane(); @@ -834,6 +836,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable }); layoutStatusIcons(); + return true; } public boolean mayBeNoticed() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupManagerImpl.java index f1568ecbc649..1d3cc548be8c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupManagerImpl.java @@ -113,7 +113,7 @@ public class LookupManagerImpl extends LookupManager { } final LookupImpl lookup = createLookup(editor, items, prefix, arranger); - lookup.show(); + lookup.showLookup(); return lookup; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java index 5caeb7421e0d..9cd759cb774e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java @@ -74,7 +74,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler { final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, items, prefix, LookupArranger.DEFAULT); lookup.addLookupListener(new MyLookupAdapter(project, editor, null)); - lookup.show(); + lookup.showLookup(); } private static String computePrefix(TemplateImpl template, String argument) { @@ -96,7 +96,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler { } lookup.addLookupListener(new MyLookupAdapter(project, editor, template2Argument)); - lookup.show(); + lookup.showLookup(); } public boolean startInWriteAction() { diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java index c84cb9bad789..8a57b651c0b9 100644 --- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java +++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java @@ -119,7 +119,7 @@ public class TextFieldWithAutoCompletion extends EditorTextField { lookup.setAdvertisementText(advertisementText); lookup.refreshUi(); } - lookup.show(); + lookup.showLookup(); } public void setAdvertisementText(@Nullable String text) { From d8ed96e60fb55b96fca0f751351a75b1642400a6 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 16:51:56 +0200 Subject: [PATCH 30/41] groovy completion: when completing a method by space, don't insert parentheses when completing if by space or (, don't insert them second time parameters are more relevant than classes --- .../GroovyCompletionContributor.java | 9 +++++++-- .../lang/completion/GroovyInsertHandler.java | 17 +++++++++-------- .../completion/weighers/GrKindWeigher.java | 4 ++-- .../plugins/groovy/lang/psi/util/PsiUtil.java | 2 +- .../GrCompletionWithLibraryTest.groovy | 3 +++ .../completion/GroovyCompletionTest.groovy | 19 +++++++++++++++++++ 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 88a726f1b190..b9e5b2988725 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -264,8 +264,13 @@ public class GroovyCompletionContributor extends CompletionContributor { result.addElement(LookupElementBuilder.create("if").setBold().setInsertHandler(new InsertHandler() { @Override public void handleInsert(InsertionContext context, LookupElement item) { - TailTypes.IF_LPARENTH.processTail(context.getEditor(), context.getTailOffset()); - } + if (context.getCompletionChar() != ' ') { + TailTypes.IF_LPARENTH.processTail(context.getEditor(), context.getTailOffset()); + } + if (context.getCompletionChar() == '(') { + context.setAddCompletionChar(false); + } + } })); } }); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java index 6e8946605595..17b630501613 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java @@ -32,12 +32,14 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.Arrays; @@ -91,15 +93,14 @@ public class GroovyInsertHandler implements InsertHandler { } } - PsiDocumentManager docManager = PsiDocumentManager.getInstance(method.getProject()); - docManager.commitDocument(document); - /* - //always use parentheses + context.commitDocument(); - PsiFile psiFile = docManager.getPsiFile(document); - if (method.getParameterList().getParametersCount() > 0 && isExpressionStatement(psiFile, context.getStartOffset())) { - return; - }*/ + if (context.getCompletionChar() == ' ') { + GrExpression expr = PsiTreeUtil.getParentOfType(context.getFile().findElementAt(context.getStartOffset()), GrExpression.class); + if (expr != null && PsiUtil.isExpressionStatement(expr)) { + return; + } + } new MethodParenthesesHandler(method, true).handleInsert(context, item); return; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java index 58a80da31355..cdb8e42dc9fa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java @@ -24,12 +24,12 @@ import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrPropertyForCompletion; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.Set; @@ -64,7 +64,7 @@ public class GrKindWeigher extends CompletionWeigher { final GrReferenceElement parent = (GrReferenceElement)position.getParent(); if (parent.getQualifier() == null) { - if (o instanceof GrVariable && GroovyRefactoringUtil.isLocalVariable((GrVariable)o)) return NotQualifiedKind.aLocal; + if (o instanceof GrVariable && !(o instanceof GrField)) return NotQualifiedKind.aLocal; if (o instanceof PsiClass) return NotQualifiedKind.aClass; if (o instanceof PsiPackage) return NotQualifiedKind.aPackage; if (isLightElement(o)) return NotQualifiedKind.anImplicitGroovyMethod; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 4a7a156170a8..58230dafc025 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -1032,7 +1032,7 @@ public class PsiUtil { return ((GrListOrMap)firstArg).getNamedArguments(); } - public static boolean isExpressionStatement(PsiElement expr) { + public static boolean isExpressionStatement(@NotNull PsiElement expr) { final PsiElement parent = expr.getParent(); if (parent instanceof GrControlFlowOwner) return true; if (parent instanceof GrExpression || diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy index a392764fa1f0..33867eff0838 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy @@ -71,6 +71,9 @@ class GrCompletionWithLibraryTest extends GroovyCompletionTestBase { public void testEachMethodForRanges() throws Throwable {doBasicTest();} public void testEachMethodForEnumRanges() throws Throwable {doBasicTest();} + public void testPrintlnSpace() { checkCompletion 'print', ' ', "print " } + public void testHashCodeSpace() { checkCompletion 'if ("".sub', ' ', 'if ("".subSequence() ' } + public void testTwoMethodWithSameName() { doVariantableTest "fooo", "fooo" } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index dbaae99c63f8..0e6f886b8678 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -20,6 +20,7 @@ package org.jetbrains.plugins.groovy.completion; import com.intellij.codeInsight.lookup.LookupElement import org.jetbrains.plugins.groovy.GroovyFileType import org.jetbrains.plugins.groovy.util.TestUtils +import com.intellij.codeInsight.CodeInsightSettings /** * @author Maxim.Medvedev @@ -739,6 +740,10 @@ a.""") checkSingleItemCompletion('def foo = "fo"', 'def foo = "foo"') } + public void testIfSpace() { checkCompletion 'int iff; if', ' ', "int iff; if " } + + public void testIfParenthesis() { checkCompletion 'int iff; if', '(', "int iff; if ()" } + public void testShowAccessor() { assertNotNull doContainsTest("getFoo", """ class MyClass { @@ -758,4 +763,18 @@ while(true) { }""") } + + public void testPreferParametersToClasses() { + CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE + + try { + myFixture.configureByText "a.groovy", "def foo(stryng) { println str }" + myFixture.completeBasic() + assert myFixture.lookupElementStrings[0] == 'stryng' + } + finally { + CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER + } + } + } \ No newline at end of file From c3e418ca1f60d89cb5b03841c7042619924c2c64 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 17:24:04 +0200 Subject: [PATCH 31/41] a more straightforward check that the lookup has been shown --- .../codeInsight/completion/CompletionProgressIndicator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a428af1005cd..d08349197f0b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -602,7 +602,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } public void scheduleRestart() { - if (isAutopopupCompletion() && (!myProcessingDelayedActions || hideAutopopupIfMeaningless())) { + if (isAutopopupCompletion() && (!myLookup.isShown() || hideAutopopupIfMeaningless())) { AutoPopupController.getInstance(getProject()).scheduleAutoPopup(myEditor, null); return; } From 602098f2dda091f103f6c189854e6b944576d03b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 18:20:05 +0200 Subject: [PATCH 32/41] let toolwindow notifications not affect the ide notification icon color, they spam too much --- .../platform-impl/src/com/intellij/notification/LogModel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/notification/LogModel.java b/platform/platform-impl/src/com/intellij/notification/LogModel.java index f2fdb78bc00b..c57c60e4abcd 100644 --- a/platform/platform-impl/src/com/intellij/notification/LogModel.java +++ b/platform/platform-impl/src/com/intellij/notification/LogModel.java @@ -43,7 +43,8 @@ public class LogModel { } void addNotification(Notification notification) { - if (notification.isImportant() || NotificationsConfiguration.getSettings(notification.getGroupId()).getDisplayType() != NotificationDisplayType.NONE) { + NotificationDisplayType type = NotificationsConfiguration.getSettings(notification.getGroupId()).getDisplayType(); + if (notification.isImportant() || (type != NotificationDisplayType.NONE && type != NotificationDisplayType.TOOL_WINDOW)) { synchronized (myNotifications) { myNotifications.add(notification); } From 1392a291d6d62c3eaa147429074726864e3ecac2 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 3 Aug 2011 18:22:28 +0200 Subject: [PATCH 33/41] when there are no projects open (=> no event log), make all the balloons sticky --- .../intellij/notification/impl/NotificationsManagerImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index 693ed6bc5ef7..af4b6050a52c 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -22,6 +22,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.*; @@ -178,6 +179,9 @@ public class NotificationsManagerImpl extends NotificationsManager implements No (toolWindowId == null || project == null || !Arrays.asList(ToolWindowManager.getInstance(project).getToolWindowIds()).contains(toolWindowId))) { type = NotificationDisplayType.BALLOON; } + if (type == NotificationDisplayType.BALLOON && ProjectManager.getInstance().getOpenProjects().length == 0) { + type = NotificationDisplayType.STICKY_BALLOON; + } switch (type) { case NONE: From 175ae1722c5e07e6994dda68c185bb5ad94cd12b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 13:29:23 +0200 Subject: [PATCH 34/41] set LAF before showing patch error dialog (IDEA-65793) --- platform/bootstrap/src/com/intellij/idea/Main.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java index 853c717472ed..085d39f8c052 100644 --- a/platform/bootstrap/src/com/intellij/idea/Main.java +++ b/platform/bootstrap/src/com/intellij/idea/Main.java @@ -39,6 +39,10 @@ public class Main { public static void main(final String[] args) { if (installPatch()) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception ignore) { } JOptionPane.showMessageDialog(null, "The application cannot start right away since some critical files have been changed, " + "please restart it manually."); return; From 66b3d3602f9bc987fc41c8d337ef1d3198f2d1a7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 13:38:39 +0200 Subject: [PATCH 35/41] dialog cosmetics --- .../impl/quickfix/LocateLibraryDialog.form | 26 ++++++------------- .../src/messages/QuickFixBundle.properties | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.form b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.form index a7f36e878c0c..ce18bcc96501 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.form +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/LocateLibraryDialog.form @@ -1,7 +1,7 @@
- + @@ -57,25 +57,15 @@ - - + - + - - - - - - - - - - - - - - + + + + + diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index a0fc1f94fd83..3b9f912d78e2 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -230,7 +230,7 @@ orderEntry.fix.add.annotations.jar.to.classpath=Add 'annotations.jar' to classpa static.import.method.text=Static Import Method static.import.method.choose.method.to.import=Choose Method to Import -add.library.title.dialog=Adding library +add.library.title.dialog=Add Library to Project add.library.title.locate.library=Locate library add.library.description.locate.library=Locate library file which will be added as module library add.library.title.choose.folder=Choose directory From d38f27c7c86560c9a02a006d8937fd724ee4b090 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 15:52:59 +0200 Subject: [PATCH 36/41] remove incorrect qualified name check; provide tests (IDEA-71870) [r=jeka] --- .../testData/psi/classUtil/ManyClasses.java | 47 +++++++++++++++++++ .../com/intellij/psi/util/ClassUtilTest.java | 45 ++++++++++++++++++ .../src/com/intellij/psi/util/ClassUtil.java | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/psi/classUtil/ManyClasses.java create mode 100644 java/java-tests/testSrc/com/intellij/psi/util/ClassUtilTest.java diff --git a/java/java-tests/testData/psi/classUtil/ManyClasses.java b/java/java-tests/testData/psi/classUtil/ManyClasses.java new file mode 100644 index 000000000000..461dfb4109cf --- /dev/null +++ b/java/java-tests/testData/psi/classUtil/ManyClasses.java @@ -0,0 +1,47 @@ +import java.lang.Comparable; +import java.lang.Integer; +import java.lang.Override; +import java.lang.Runnable; + +public class ManyClasses { + public void foo() { + Runnable r = new Runnable() { + @Override + public void run() { + Comparable c = new Comparable() { + @Override + public int compareTo(Integer o) { + return 0; + } + }; + } + }; + + class FooLocal { + Runnable r = new Runnable() { + @Override + public void run() { + } + }; + } + } + + public void bar() { + class FooLocal implements Runnable { + @Override + public void run() { + } + } + } + + public class Child { + + } + +} + +class Local { + public static class Sub { + + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/psi/util/ClassUtilTest.java b/java/java-tests/testSrc/com/intellij/psi/util/ClassUtilTest.java new file mode 100644 index 000000000000..efac16071d38 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/util/ClassUtilTest.java @@ -0,0 +1,45 @@ +/* + * 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.psi.util; + +import com.intellij.JavaTestUtil; +import com.intellij.psi.PsiClass; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +/** + * @author yole + */ +public class ClassUtilTest extends LightCodeInsightFixtureTestCase { + public void testFindPsiClassByJvmName() { + myFixture.configureByFile("ManyClasses.java"); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$1")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$1$1")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$1FooLocal")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$1FooLocal$1")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$Child")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "Local")); + assertNotNull(ClassUtil.findPsiClassByJVMName(getPsiManager(), "Local$Sub")); + + final PsiClass fooLocal2 = ClassUtil.findPsiClassByJVMName(getPsiManager(), "ManyClasses$2FooLocal"); + assertEquals("Runnable", fooLocal2.getImplementsListTypes() [0].getClassName()); + } + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/psi/classUtil/"; + } +} diff --git a/java/openapi/src/com/intellij/psi/util/ClassUtil.java b/java/openapi/src/com/intellij/psi/util/ClassUtil.java index 3926d2d5f976..ec81618addd0 100644 --- a/java/openapi/src/com/intellij/psi/util/ClassUtil.java +++ b/java/openapi/src/com/intellij/psi/util/ClassUtil.java @@ -148,7 +148,7 @@ public class ClassUtil { super.visitClass(aClass); return; } - if (aClass.getQualifiedName() == null && Comparing.strEqual(name, aClass.getName())) { + if (Comparing.strEqual(name, aClass.getName())) { myCurrentIdx++; if (myCurrentIdx == idx || idx == -1) { result[0] = aClass; From f539aaae474d0891c12180625e2a95809c05961d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 16:04:00 +0200 Subject: [PATCH 37/41] disregard ignored builds when performing manual check for updates (IDEA-71831) --- .../impl/CheckForUpdateAction.java | 2 +- .../updateSettings/impl/UpdateChecker.java | 40 ++++++++++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java index c78d54abe30f..70eb21a5ee44 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java @@ -45,7 +45,7 @@ public class CheckForUpdateAction extends AnAction implements DumbAware { ProgressManager.getInstance().run(new Task.Backgroundable(project, "Checking for updates", false) { @Override public void run(@NotNull ProgressIndicator indicator) { - final CheckForUpdateResult result = UpdateChecker.checkForUpdates(); + final CheckForUpdateResult result = UpdateChecker.checkForUpdates(true); final List updatedPlugins = UpdateChecker.updatePlugins(true, settingsConfigurable); ApplicationManager.getApplication().invokeLater(new Runnable() { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 7d55245f514f..734b41e4521f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -287,12 +287,11 @@ public final class UpdateChecker { } @NotNull - public static CheckForUpdateResult doCheckForUpdates() { + public static CheckForUpdateResult doCheckForUpdates(final UpdateSettings settings) { ApplicationInfo appInfo = ApplicationInfo.getInstance(); BuildNumber currentBuild = appInfo.getBuild(); int majorVersion = Integer.parseInt(appInfo.getMajorVersion()); final UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl(), getInstallationUID(), null); - final UpdateSettings settings = UpdateSettings.getInstance(); final UpdatesInfo info; try { info = loader.loadUpdatesInfo(); @@ -309,19 +308,48 @@ public final class UpdateChecker { } - @NotNull public static CheckForUpdateResult checkForUpdates() { + return checkForUpdates(false); + } + + @NotNull + public static CheckForUpdateResult checkForUpdates(final boolean disregardIgnoredBuilds) { if (LOG.isDebugEnabled()) { LOG.debug("enter: auto checkForUpdates()"); } - final UpdateSettings settings = UpdateSettings.getInstance(); + UserUpdateSettings settings = UpdateSettings.getInstance(); + if (disregardIgnoredBuilds) { + settings = new UserUpdateSettings() { + @NotNull + @Override + public List getKnownChannelsIds() { + return UpdateSettings.getInstance().getKnownChannelsIds(); + } - final CheckForUpdateResult result = doCheckForUpdates(); + @Override + public List getIgnoredBuildNumbers() { + return Collections.emptyList(); + } + + @Override + public void setKnownChannelIds(List ids) { + UpdateSettings.getInstance().setKnownChannelIds(ids); + } + + @NotNull + @Override + public ChannelStatus getSelectedChannelStatus() { + return UpdateSettings.getInstance().getSelectedChannelStatus(); + } + }; + } + + final CheckForUpdateResult result = doCheckForUpdates(UpdateSettings.getInstance()); if (result.getState() == UpdateStrategy.State.LOADED) { - settings.LAST_TIME_CHECKED = System.currentTimeMillis(); + UpdateSettings.getInstance().LAST_TIME_CHECKED = System.currentTimeMillis(); settings.setKnownChannelIds(result.getAllChannelsIds()); } From d2858e8669fcd20d7051783b5a6dbde6917dd5ad Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 16:41:22 +0200 Subject: [PATCH 38/41] set platform prefix automatically in plugin run configuration (IDEA-71433); assorted cleanup --- plugins/devkit/src/projectRoots/IdeaJdk.java | 12 ++++++++-- plugins/devkit/src/run/IdeaLicenseHelper.java | 2 +- .../src/run/PluginRunConfiguration.java | 24 ++++++++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java index eefb4479811f..0f6c318daede 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/src/projectRoots/IdeaJdk.java @@ -150,16 +150,24 @@ public class IdeaJdk extends SdkType implements JavaSdkType { if (new File(sdkHome, "lib/rubymine.jar").exists()) { productName = "RubyMine "; } + else if (new File(sdkHome, "lib/pycharm.jar").exists()) { + productName = "PyCharm "; + } + else if (new File(sdkHome, "lib/webide.jar").exists()) { + productName = "WebStorm/PhpStorm "; + } + else if (new File(sdkHome, "lib/webide.jar").exists()) { + productName = "WebStorm/PhpStorm "; + } else { productName = "IDEA "; - } String buildNumber = getBuildNumber(sdkHome); return productName + (buildNumber != null ? buildNumber : ""); } @Nullable - private static String getBuildNumber(String ideaHome) { + public static String getBuildNumber(String ideaHome) { try { @NonNls final String buildTxt = "/build.txt"; return FileUtil.loadFile(new File(ideaHome + buildTxt)).trim(); diff --git a/plugins/devkit/src/run/IdeaLicenseHelper.java b/plugins/devkit/src/run/IdeaLicenseHelper.java index 84dc5a02f61e..ca8e3115547f 100644 --- a/plugins/devkit/src/run/IdeaLicenseHelper.java +++ b/plugins/devkit/src/run/IdeaLicenseHelper.java @@ -74,7 +74,7 @@ public class IdeaLicenseHelper { return null; } - public static void copyIDEALicencse(final String sandboxHome, Sdk jdk){ + public static void copyIDEALicense(final String sandboxHome, Sdk jdk){ if (isIDEALicenseInSandbox(sandboxHome + File.separator + CONFIG_DIR_NAME, sandboxHome + File.separator + "system", jdk.getHomePath() + File.separator + "bin") == null){ final File ideaLicense = isIDEALicenseInSandbox(PathManager.getConfigPath(), PathManager.getSystemPath(), PathManager.getBinPath()); if (ideaLicense != null){ diff --git a/plugins/devkit/src/run/PluginRunConfiguration.java b/plugins/devkit/src/run/PluginRunConfiguration.java index 9dff21bb8474..301459f68afc 100644 --- a/plugins/devkit/src/run/PluginRunConfiguration.java +++ b/plugins/devkit/src/run/PluginRunConfiguration.java @@ -99,7 +99,7 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu final String canonicalSandbox = sandboxHome; //copy license from running instance of idea - IdeaLicenseHelper.copyIDEALicencse(sandboxHome, ideaJdk); + IdeaLicenseHelper.copyIDEALicense(sandboxHome, ideaJdk); final JavaCommandLineState state = new JavaCommandLineState(env) { protected JavaParameters createJavaParameters() throws ExecutionException { @@ -122,6 +122,28 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu vm.defineProperty("idea.smooth.progress", "false"); vm.defineProperty("apple.laf.useScreenMenuBar", "true"); } + + String buildNumber = IdeaJdk.getBuildNumber(ideaJdk.getHomePath()); + if (buildNumber != null) { + if (buildNumber.startsWith("IC")) { + vm.defineProperty("idea.platform.prefix", "Idea"); + } + else if (buildNumber.startsWith("PY")) { + vm.defineProperty("idea.platform.prefix", "Python"); + } + else if (buildNumber.startsWith("RM")) { + vm.defineProperty("idea.platform.prefix", "Ruby"); + } + else if (buildNumber.startsWith("PS")) { + vm.defineProperty("idea.platform.prefix", "PhpStorm"); + } + else if (buildNumber.startsWith("WS")) { + vm.defineProperty("idea.platform.prefix", "WebStorm"); + } + else if (buildNumber.startsWith("OC")) { + vm.defineProperty("idea.platform.prefix", "CIDR"); + } + } params.setWorkingDirectory(ideaJdk.getHomePath() + File.separator + "bin" + File.separator); From 11a6e809d4ea562bb3675f3741fd9c2cc7875e44 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 17:23:55 +0200 Subject: [PATCH 39/41] small special-case to allow serializing Rectangle objects --- .../com/intellij/util/xmlb/BeanBinding.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index fd7620a5ec58..3860937d488d 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -31,11 +31,13 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.*; import java.beans.Introspector; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; class BeanBinding implements Binding { @@ -208,6 +210,17 @@ class BeanBinding implements Binding { accessors = Lists.newArrayList(); + if (aClass != Rectangle.class) { // special case for Rectangle.class to avoid infinite recursion during serialization due to bounds() method + collectPropertyAccessors(aClass, accessors); + } + collectFieldAccessors(aClass, accessors); + + ourAccessorCache.put(aClass, new SoftReference>(accessors)); + + return accessors; + } + + private static void collectPropertyAccessors(Class aClass, List accessors) { final Map> candidates = Maps.newTreeMap(); // (name,(getter,setter)) for (Method method : aClass.getMethods()) { if (!Modifier.isPublic(method.getModifiers())) continue; @@ -230,7 +243,9 @@ class BeanBinding implements Binding { accessors.add(new PropertyAccessor(candidate.getKey(), methods.first.getReturnType(), methods.first, methods.second)); } } + } + private static void collectFieldAccessors(Class aClass, List accessors) { for (Field field : aClass.getFields()) { final int modifiers = field.getModifiers(); if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && @@ -239,10 +254,6 @@ class BeanBinding implements Binding { accessors.add(new FieldAccessor(field)); } } - - ourAccessorCache.put(aClass, new SoftReference>(accessors)); - - return accessors; } @Nullable From eefc611bf2b5c970fca54605d5f36131918671ad Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 17:25:30 +0200 Subject: [PATCH 40/41] remember per-project frame coordinates (IDEA-66434) --- .../openapi/wm/impl/IdeFrameImpl.java | 1 + .../openapi/wm/impl/ProjectFrameBounds.java | 60 +++++++++++++++++++ .../openapi/wm/impl/WindowManagerImpl.java | 6 +- .../src/META-INF/PlatformExtensions.xml | 2 + 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.java diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index 891008c295bf..7123a943634d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -289,6 +289,7 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider { myProject = project; if (project != null) { + ProjectFrameBounds.getInstance(project); // make sure the service is initialized and its state will be saved if (myRootPane != null) { myRootPane.installNorthComponents(project); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.java new file mode 100644 index 000000000000..39d87488e2b1 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectFrameBounds.java @@ -0,0 +1,60 @@ +/* + * 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.wm.impl; + +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.WindowManager; + +import java.awt.*; + +/** + * @author yole + */ +@State( + name = "ProjectFrameBounds", + storages = { @Storage( + file = "$WORKSPACE_FILE$") } +) +public class ProjectFrameBounds implements PersistentStateComponent { + public static ProjectFrameBounds getInstance(Project project) { + return ServiceManager.getService(project, ProjectFrameBounds.class); + } + + private final Project myProject; + private Rectangle myBounds; + + public ProjectFrameBounds(Project project) { + myProject = project; + } + + @Override + public Rectangle getState() { + return WindowManager.getInstance().getFrame(myProject).getBounds(); + } + + @Override + public void loadState(Rectangle state) { + myBounds = state; + } + + public Rectangle getBounds() { + return myBounds; + } +} 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 00b3ee9eb076..e33c50e894fa 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 @@ -540,7 +540,11 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat else { frame = new IdeFrameImpl((ApplicationInfoEx)ApplicationInfo.getInstance(), ActionManagerEx.getInstanceEx(), UISettings.getInstance(), DataManager.getInstance(), ApplicationManager.getApplication(), ArrayUtil.EMPTY_STRING_ARRAY); - if (myFrameBounds != null) { + final Rectangle bounds = ProjectFrameBounds.getInstance(project).getBounds(); + if (bounds != null) { + frame.setBounds(bounds); + } + else if (myFrameBounds != null) { frame.setBounds(myFrameBounds); } frame.setExtendedState(myFrameExtendedState); diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index b79ff584d213..26aeee11a962 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -224,4 +224,6 @@ + From b890d3d12ea6527babfbc4a70028337e0ecc9af2 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 3 Aug 2011 17:33:35 +0200 Subject: [PATCH 41/41] enable speed search in color choosers (IDEA-69979) --- .../uiDesigner/propertyInspector/editors/ColorEditor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java index 54531c3ebb00..9a57f37b4ea7 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java @@ -18,6 +18,7 @@ package com.intellij.uiDesigner.propertyInspector.editors; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.ListSpeedSearch; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBList; import com.intellij.uiDesigner.UIDesignerBundle; @@ -234,10 +235,11 @@ public class ColorEditor extends PropertyEditor { myDescriptorList.setCellRenderer(new ColorRenderer()); myDescriptorList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { - ColorDescriptor descriptor = (ColorDescriptor) myDescriptorList.getSelectedValue(); + ColorDescriptor descriptor = (ColorDescriptor)myDescriptorList.getSelectedValue(); getColorSelectionModel().setSelectedColor(new ColorDescriptorWrapper(descriptor)); } }); + new ListSpeedSearch(myDescriptorList); add(ScrollPaneFactory.createScrollPane(myDescriptorList), BorderLayout.CENTER); }