diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java index e52236dca5a2..2eb2ca8e78a8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java @@ -116,8 +116,8 @@ public class JavaExecutionStack extends XExecutionStack { @Override protected void action() throws Exception { boolean showLibraryStackframes = DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES; - List frames = new ArrayList(); if (!myThreadProxy.isCollected() && myDebugProcess.getSuspendManager().isSuspended(myThreadProxy)) { + List frames = new ArrayList(); int status = myThreadProxy.status(); if (!(status == ThreadReference.THREAD_STATUS_UNKNOWN) && !(status == ThreadReference.THREAD_STATUS_NOT_STARTED) && @@ -146,8 +146,11 @@ public class JavaExecutionStack extends XExecutionStack { return; } } + container.addStackFrames(frames, true); + } + else { + container.errorOccurred(DebuggerBundle.message("frame.panel.frames.not.available")); } - container.addStackFrames(frames, true); } }); } diff --git a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java index 5f6f18def730..8a4c380a669a 100644 --- a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java +++ b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/AttachSourcesNotificationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -79,13 +79,14 @@ public class AttachSourcesNotificationProvider extends EditorNotifications.Provi }); } + @NotNull @Override public Key getKey() { return KEY; } @Override - public EditorNotificationPanel createNotificationPanel(final VirtualFile file, FileEditor fileEditor) { + public EditorNotificationPanel createNotificationPanel(@NotNull final VirtualFile file, @NotNull FileEditor fileEditor) { if (file.getFileType() != JavaClassFileType.INSTANCE) return null; final List libraries = findOrderEntriesContainingFile(file); if (libraries == null) return null; @@ -240,7 +241,7 @@ public class AttachSourcesNotificationProvider extends EditorNotifications.Provi if (modelsToCommit.isEmpty()) return new ActionCallback.Rejected(); new WriteAction() { @Override - protected void run(final Result result) { + protected void run(@NotNull final Result result) { for (Library.ModifiableModel model : modelsToCommit) { model.commit(); } @@ -253,7 +254,7 @@ public class AttachSourcesNotificationProvider extends EditorNotifications.Provi @Nullable private VirtualFile findRoot(Library library) { for (VirtualFile classesRoot : library.getFiles(OrderRootType.CLASSES)) { - if (VfsUtil.isAncestor(classesRoot, myClassFile, true)) { + if (VfsUtilCore.isAncestor(classesRoot, myClassFile, true)) { return classesRoot; } } diff --git a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java index 178c85584ae2..668f2cc97577 100644 --- a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java +++ b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,13 +53,14 @@ public class SetupSDKNotificationProvider extends EditorNotifications.Provider getKey() { return KEY; } @Override - public EditorNotificationPanel createNotificationPanel(VirtualFile file, FileEditor fileEditor) { + public EditorNotificationPanel createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor) { if (file.getFileType() == JavaClassFileType.INSTANCE) return null; final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java index 92b110caef43..c2d3d801a211 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * User: anna - * Date: 26-Dec-2007 - */ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.icons.AllIcons; @@ -30,11 +25,15 @@ import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; import javax.swing.*; +/** + * @author anna + * @since 26-Dec-2007 + */ public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { - @Override public SdkPathEditor createPathEditor(Sdk sdk) { - return new SdkPathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, new FileChooserDescriptor(true, true, true, false, true, true)); + FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, true, false, true, true); + return new SdkPathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, descriptor); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index ac3e7a6fd455..f1d847cb24c2 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -22,12 +22,11 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.impl.source.HierarchicalMethodSignatureImpl; +import com.intellij.psi.impl.source.PsiClassImpl; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; -import com.intellij.util.NotNullFunction; -import com.intellij.util.Processor; -import com.intellij.util.SmartList; +import com.intellij.util.*; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; @@ -143,7 +142,15 @@ public class PsiSuperMethodImplUtil { } }); - for (PsiMethod method : aClass.getMethods()) { + PsiMethod[] methods = aClass.getMethods(); + if (aClass instanceof PsiClassImpl) { + final PsiMethod valuesMethod = ((PsiClassImpl)aClass).getValuesMethod(); + if (valuesMethod != null) { + methods = ArrayUtil.append(methods, valuesMethod); + } + } + + for (PsiMethod method : methods) { if (!method.isValid()) { throw new PsiInvalidElementAccessException(method, "class.valid=" + aClass.isValid() + "; name=" + method.getName()); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/EnumValuesMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/EnumValuesMethod.java new file mode 100644 index 000000000000..14ad192c8823 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/EnumValuesMethod.java @@ -0,0 +1,25 @@ +import java.util.function.Supplier; + +class EnumValues { + + { + Supplier> supplier = () -> new C<>(ABC::values); + } + + private static interface I { + T get(); + } + + private static class C implements I { + C(Supplier supplier) {} + + @Override + public E get() { + return null; + } + } + + private static enum ABC { + A, B, C + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 0c61b63bfc8d..3cfdaa4071cc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -265,6 +265,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testEnumValuesMethod() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java index b832e65c7675..3cde353eded2 100644 --- a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java @@ -86,10 +86,8 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase { private static void doTest(String clsPath, String txtPath) { VirtualFileSystem fs = clsPath.contains("!/") ? JarFileSystem.getInstance() : LocalFileSystem.getInstance(); - VirtualFile vFile = fs.findFileByPath(clsPath); - assertNotNull(clsPath, vFile); - PsiFile clsFile = getPsiManager().findFile(vFile); - assertNotNull(vFile.getPath(), clsFile); + VirtualFile file = fs.findFileByPath(clsPath); + assertNotNull(clsPath, file); String expected; try { @@ -100,6 +98,6 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase { return; } - assertEquals(expected, ((ClsFileImpl)clsFile).getMirror().getText()); + assertEquals(expected, ClsFileImpl.decompile(file).toString()); } } diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java index 16392eb601d5..e8317415d8b3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java @@ -690,7 +690,6 @@ public class ClsRepositoryUseTest extends PsiTestCase { final PsiType returnType = methodsWithReturnType.getReturnType(); assert returnType != null : methodsWithReturnType; assertEquals("pack.Parametrized", returnType.getCanonicalText()); - assertEquals("public pack.Parametrized method() { /* compiled code */ }", methodsWithReturnType.getText()); } private static void checkEnumConstant(String name, PsiField field, PsiClassType type) { @@ -740,19 +739,20 @@ public class ClsRepositoryUseTest extends PsiTestCase { assertEquals(PsiWildcardType.createUnbounded(myPsiManager), substitution); } + @SuppressWarnings("ConstantConditions") public void testModifiers() throws Exception { - final PsiClass psiClass = myJavaFacade.findClass("pack.Modifiers", RESOLVE_SCOPE); + PsiClass psiClass = myJavaFacade.findClass("pack.Modifiers", RESOLVE_SCOPE); assertNotNull(psiClass); - assertEquals("public class Modifiers {\n" + - " private transient int f1;\n" + - " private volatile int f2;\n" + - "\n" + - " public Modifiers() { /* compiled code */ }\n" + - "\n" + - " private void m1(int... i) { /* compiled code */ }\n" + - "\n" + - " private synchronized void m2() { /* compiled code */ }\n" + - "}", - psiClass.getText().trim()); + + PsiField f1 = psiClass.findFieldByName("f1", false); + assertEquals("private transient", f1.getModifierList().getText()); + PsiField f2 = psiClass.findFieldByName("f2", false); + assertEquals("private volatile", f2.getModifierList().getText()); + PsiMethod init = psiClass.findMethodsByName("Modifiers", false)[0]; + assertEquals("public", init.getModifierList().getText()); + PsiMethod m1 = psiClass.findMethodsByName("m1", false)[0]; + assertEquals("private", m1.getModifierList().getText()); + PsiMethod m2 = psiClass.findMethodsByName("m2", false)[0]; + assertEquals("private synchronized", m2.getModifierList().getText()); } } diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy index 5e6adfdb4f55..ce04dd0ba20c 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy @@ -20,12 +20,12 @@ import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod +import com.intellij.psi.impl.source.PsiFileImpl import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.searches.ClassInheritorsSearch import com.intellij.psi.search.searches.OverridingMethodsSearch +import com.intellij.psi.stubs.StubTreeLoader import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase /** @@ -150,14 +150,12 @@ class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { Collection pkgDirs = pkg.directories.collect { it.virtualFile } Collection pkgChildren = pkgDirs.collect { it.children as List }.flatten() - PsiFile javaSrc = psiManager.findFile(pkgChildren.find { it.name == 'LibraryClass.java' }) - assert !javaSrc.contentsLoaded - assert !javaSrc.stub + VirtualFile javaSrc = pkgChildren.find { it.name == 'LibraryClass.java' } + checkFileIsNotLoadedAndHasNoIndexedStub(javaSrc) assert pkg.containsClassNamed('LibraryClass') - assert !javaSrc.contentsLoaded - assert !javaSrc.stub - assert !javaSrc.node.parsed + checkFileIsNotLoadedAndHasNoIndexedStub(javaSrc) + assert !((PsiFileImpl)psiManager.findFile(javaSrc)).treeElement } @Override @@ -174,7 +172,7 @@ class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { def localFile = myFixture.copyFileToProject(testDataPathForTest + File.separator + "Foo.java", 'Foo.java') assert localFile != null - checkFileIsNotLoadedAndHasNoStub(localFile) + checkFileIsNotLoadedAndHasNoIndexedStub(localFile) assert facade.findClasses('Foo', scope).size() == 0 PsiTestUtil.addLibrary(myModule, 'cas', lib.path, [] as String[], ["/classesAndSources.jar!/"] as String[]) @@ -187,14 +185,16 @@ class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase { assert facade.findClasses('LibraryClass', scope).size() == 0 - checkFileIsNotLoadedAndHasNoStub(vfile) + checkFileIsNotLoadedAndHasNoIndexedStub(vfile) } - private void checkFileIsNotLoadedAndHasNoStub(VirtualFile vfile) { - def file = PsiManager.getInstance(project).findFile(vfile); + private void checkFileIsNotLoadedAndHasNoIndexedStub(VirtualFile vfile) { + PsiFileImpl file = psiManager.findFile(vfile); assert file != null assert !file.contentsLoaded - assert !file.stub + assert !StubTreeLoader.instance.readFromVFile(project, vfile) + assert !StubTreeLoader.instance.canHaveStub(vfile) + assert file.stub // from text } } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index b8ecfc3dc017..68e8d2500314 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -23,6 +23,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.SmartList; import com.intellij.util.WalkingState; +import com.intellij.util.concurrency.AtomicFieldUpdater; import gnu.trove.TLongHashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -32,7 +33,6 @@ import java.lang.ref.WeakReference; import java.util.ConcurrentModificationException; import java.util.List; import java.util.NoSuchElementException; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -295,14 +295,14 @@ public abstract class IntervalTreeImpl extends RedBla } /** - * packing/unpacking cachedDeltaUpToRoot field parts - * Bits layout: - * XXXXXXXXNMMMMMMMM where - * XXXXXXXX - 31bit int containing cached delta up to root - * N - 1bit flag. if set then all deltas up to root are null - * MMMMMMMM - 32bit int containing this node modification count + * packing/unpacking cachedDeltaUpToRoot field parts + * Bits layout: + * XXXXXXXXNMMMMMMMM where + * XXXXXXXX - 31bit int containing cached delta up to root + * N - 1bit flag. if set then all deltas up to root are null + * MMMMMMMM - 32bit int containing this node modification count */ - private static final AtomicLongFieldUpdater cachedDeltaUpdater = AtomicLongFieldUpdater.newUpdater(IntervalNode.class, "cachedDeltaUpToRoot"); + private static final AtomicFieldUpdater cachedDeltaUpdater = AtomicFieldUpdater.forLongFieldIn(IntervalNode.class); private void setCachedValues(int deltaUpToRoot, boolean allDeltaUpToRootAreNull, int modCount) { cachedDeltaUpToRoot = packValues(deltaUpToRoot, allDeltaUpToRootAreNull, modCount); @@ -316,7 +316,7 @@ public abstract class IntervalTreeImpl extends RedBla if (myIntervalTree.modCount != treeModCount) return false; long newValue = packValues(deltaUpToRoot, allDeltasUpAreNull, treeModCount); long oldValue = cachedDeltaUpToRoot; - return cachedDeltaUpdater.compareAndSet(this, oldValue, newValue); + return cachedDeltaUpdater.compareAndSetLong(this, oldValue, newValue); } private static boolean allDeltasUpAreNull(long packedOffsets) { diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java index ee36676ec5fc..021c055dd70f 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * User: anna - * Date: 26-Dec-2007 - */ package com.intellij.openapi.roots.ui; import com.intellij.openapi.application.ApplicationManager; @@ -31,16 +26,20 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; +/** + * @author anna + * @since 26-Dec-2007 + */ public interface OrderRootTypeUIFactory { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.OrderRootTypeUI"); - KeyedExtensionFactory FACTORY = new KeyedExtensionFactory(OrderRootTypeUIFactory.class, EP_NAME, - ApplicationManager - .getApplication().getPicoContainer()) { - @Override - public String getKey(@NotNull final OrderRootType key) { - return key.name(); - } - }; + + KeyedExtensionFactory FACTORY = + new KeyedExtensionFactory(OrderRootTypeUIFactory.class, EP_NAME, ApplicationManager.getApplication().getPicoContainer()) { + @Override + public String getKey(@NotNull final OrderRootType key) { + return key.name(); + } + }; SdkPathEditor createPathEditor(Sdk sdk); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/AddSpaceInsertHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/AddSpaceInsertHandler.java index d0e990654f3d..d3cfedaf6a1a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/AddSpaceInsertHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/AddSpaceInsertHandler.java @@ -1,5 +1,6 @@ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -11,7 +12,14 @@ import com.intellij.psi.PsiDocumentManager; * @author zolotov */ public class AddSpaceInsertHandler implements InsertHandler { - public final static InsertHandler INSTANCE = new AddSpaceInsertHandler(); + public final static InsertHandler INSTANCE = new AddSpaceInsertHandler(false); + public final static InsertHandler INSTANCE_WITH_AUTO_POPUP = new AddSpaceInsertHandler(true); + + private final boolean myTriggerAutoPopup; + + public AddSpaceInsertHandler(boolean triggerAutoPopup) { + myTriggerAutoPopup = triggerAutoPopup; + } public void handleInsert(InsertionContext context, LookupElement item) { Editor editor = context.getEditor(); @@ -25,6 +33,9 @@ public class AddSpaceInsertHandler implements InsertHandler { else { editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1); } + if (myTriggerAutoPopup) { + AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null); + } } } 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 e776b30b7f98..ae9ba979e771 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 @@ -78,7 +78,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable private final Editor myEditor; private final JBList myList = new JBList(new CollectionListModel()) { @Override - protected void processKeyEvent(final KeyEvent e) { + protected void processKeyEvent(@NotNull final KeyEvent e) { final char keyChar = e.getKeyChar(); if (keyChar == KeyEvent.VK_ENTER || keyChar == KeyEvent.VK_TAB) { IdeFocusManager.getInstance(myProject).requestFocus(myEditor.getContentComponent(), true).doWhenDone(new Runnable() { @@ -590,7 +590,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable final String prefix = itemPattern(item); final int length = prefix.length(); - if (length == 0 || !StringUtil.startsWithIgnoreCase(lookupString, prefix)) return lookupString; + if (length == 0 || !itemMatcher(item).prefixMatches(prefix)) return lookupString; boolean isAllLower = true; boolean isAllUpper = true; boolean sameCase = true; @@ -771,7 +771,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable private LookupElement oldItem = null; @Override - public void valueChanged(ListSelectionEvent e){ + public void valueChanged(@NotNull ListSelectionEvent e){ final LookupElement item = getCurrentItem(); if (oldItem != item && !myList.isEmpty()) { // do not update on temporary model wipe fireCurrentItemChanged(item); diff --git a/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java b/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java index 5a6606be1c77..5b9e9a663b3f 100644 --- a/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.EditorNotificationPanel; import com.intellij.ui.EditorNotifications; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -33,6 +34,7 @@ public class GeneratedFileEditingNotificationProvider extends EditorNotification myChangeTracker = changeTracker; } + @NotNull @Override public Key getKey() { return KEY; @@ -40,7 +42,7 @@ public class GeneratedFileEditingNotificationProvider extends EditorNotification @Nullable @Override - public EditorNotificationPanel createNotificationPanel(VirtualFile file, FileEditor fileEditor) { + public EditorNotificationPanel createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor) { if (!myChangeTracker.isEditedGeneratedFile(file)) return null; EditorNotificationPanel panel = new EditorNotificationPanel(); diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java index 9a176e37aaf4..26537316b4e9 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java @@ -48,6 +48,8 @@ public class FragmentContent extends DiffContent { public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType) { RangeMarker rangeMarker = original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true); + rangeMarker.setGreedyToLeft(true); + rangeMarker.setGreedyToRight(true); mySynchonizer = new MyDocumentsSynchronizer(project, rangeMarker); myOriginal = original; myType = fileType; diff --git a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java index 8d26ee44031d..eed6946c86ff 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java @@ -23,9 +23,10 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; -import java.util.Map; -import java.util.TreeMap; /** * Created by IntelliJ IDEA. @@ -34,7 +35,7 @@ import java.util.TreeMap; * Time: 12:52 PM */ public class FragmentedEditorHighlighter implements EditorHighlighter { - private final TreeMap myPieces; + private final List myPieces; private final Document myDocument; private final int myAdditionalOffset; private final boolean myMergeByTextAttributes; @@ -49,52 +50,70 @@ public class FragmentedEditorHighlighter implements EditorHighlighter { boolean mergeByTextAttributes) { myMergeByTextAttributes = mergeByTextAttributes; myDocument = sourceIterator.getDocument(); - myPieces = new TreeMap(); + myPieces = new ArrayList(); myAdditionalOffset = additionalOffset; translate(sourceIterator, ranges); } private void translate(HighlighterIterator iterator, List ranges) { - if (iterator.atEnd()) return; int offset = 0; - for (TextRange range : ranges) { - while (range.getStartOffset() > iterator.getStart()) { + int index = 0; + + while (!iterator.atEnd() && index < ranges.size()) { + TextRange range = ranges.get(index); + + if (range.getStartOffset() >= iterator.getEnd()) { iterator.advance(); - if (iterator.atEnd()) return; + continue; } - while (range.getEndOffset() >= iterator.getEnd()) { - int relativeStart = iterator.getStart() - range.getStartOffset(); + + if (range.getEndOffset() >= iterator.getStart()) { + int relativeStart = Math.max(iterator.getStart() - range.getStartOffset(), 0); + int relativeEnd = Math.min(iterator.getEnd() - range.getStartOffset(), range.getLength()); boolean merged = false; if (myMergeByTextAttributes && !myPieces.isEmpty()) { - Map.Entry entry = myPieces.lastEntry(); - final Integer key = entry.getKey(); - final Element element = entry.getValue(); + Element element = myPieces.get(myPieces.size() - 1); if (element.getEnd() >= offset + relativeStart && element.getAttributes().equals(iterator.getTextAttributes()) && element.getElementType().equals(iterator.getTokenType())) { merged = true; - myPieces.put(key, new Element(key, - offset + (iterator.getEnd() - range.getStartOffset()), iterator.getTokenType(), - iterator.getTextAttributes())); + myPieces.add(new Element(element.getStart(), + offset + relativeEnd, + iterator.getTokenType(), + iterator.getTextAttributes())); } } if (!merged) { - myPieces.put(offset + relativeStart, new Element(offset + relativeStart, - offset + (iterator.getEnd() - range.getStartOffset()), iterator.getTokenType(), - iterator.getTextAttributes())); + myPieces.add(new Element(offset + relativeStart, + offset + relativeEnd, + iterator.getTokenType(), + iterator.getTextAttributes())); } - iterator.advance(); - if (iterator.atEnd()) return; } - offset += range.getLength() + 1 + myAdditionalOffset; // myAdditionalOffset because of extra line - for shoene separators + + if (range.getEndOffset() < iterator.getEnd()) { + offset += range.getLength() + 1 + myAdditionalOffset; // myAdditionalOffset because of extra line - for shoene separators + index++; + continue; + } + + iterator.advance(); } } @NotNull @Override public HighlighterIterator createIterator(int startOffset) { - Map.Entry entry = myPieces.ceilingEntry(startOffset); - return new ProxyIterator(myDocument, entry == null ? -1 : entry.getKey()); + int offset = Collections.binarySearch(myPieces, new Element(startOffset, 0, null, null), new Comparator() { + @Override + public int compare(Element o1, Element o2) { + return o1.getStart() - o2.getStart(); + } + }); + // offset: (-insertion point - 1), where insertionPoint is the index of the first element greater than the key + // and we need offset of the first element that is less or equal (floorElement) + if (offset < 0) offset = Math.max(-offset - 2, 0); + return new ProxyIterator(myDocument, offset); } @Override @@ -148,27 +167,21 @@ public class FragmentedEditorHighlighter implements EditorHighlighter { @Override public void advance() { - if (myIdx == myPieces.lastKey() || myIdx == -1) { - myIdx = -1; - return; + if (myIdx < myPieces.size()) { + myIdx++; } - Map.Entry entry = myPieces.tailMap(myIdx, false).firstEntry(); - myIdx = entry.getKey(); } @Override public void retreat() { - if (myIdx == myPieces.firstKey() || myIdx == -1) { - myIdx = -1; - return; + if (myIdx > -1) { + myIdx--; } - Map.Entry entry = myPieces.headMap(myIdx, false).lastEntry(); - myIdx = entry.getKey(); } @Override public boolean atEnd() { - return myIdx < 0; + return myIdx < 0 || myIdx >= myPieces.size(); } @Override diff --git a/platform/platform-api/src/com/intellij/ui/EditorNotifications.java b/platform/platform-api/src/com/intellij/ui/EditorNotifications.java index 4db32d94dd30..6805266e57ad 100644 --- a/platform/platform-api/src/com/intellij/ui/EditorNotifications.java +++ b/platform/platform-api/src/com/intellij/ui/EditorNotifications.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -31,10 +32,11 @@ import javax.swing.*; public abstract class EditorNotifications extends AbstractProjectComponent { public abstract static class Provider { + @NotNull public abstract Key getKey(); @Nullable - public abstract T createNotificationPanel(VirtualFile file, FileEditor fileEditor); + public abstract T createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor); } public static EditorNotifications getInstance(Project project) { @@ -45,7 +47,7 @@ public abstract class EditorNotifications extends AbstractProjectComponent { super(project); } - public abstract void updateNotifications(final VirtualFile file); + public abstract void updateNotifications(@NotNull VirtualFile file); public abstract void updateAllNotifications(); diff --git a/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java b/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java index cce510c0233d..fa975283d921 100644 --- a/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java @@ -79,6 +79,7 @@ public class FileChangedNotificationProvider extends EditorNotifications.Provide }); } + @NotNull @Override public Key getKey() { return KEY; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CopyPathsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CopyPathsAction.java index 388a446d991c..0bc0a50e1df8 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CopyPathsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CopyPathsAction.java @@ -20,70 +20,38 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.testFramework.LightVirtualFile; -import org.jetbrains.annotations.NotNull; import java.awt.datatransfer.StringSelection; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; public class CopyPathsAction extends AnAction implements DumbAware { - public CopyPathsAction() { setEnabledInModalContext(true); } + @Override public void actionPerformed(AnActionEvent e) { - final Collection files = getFiles(e); - if (files.isEmpty()) { - return; + VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(e.getDataContext()); + if (files != null && files.length > 0) { + CopyPasteManager.getInstance().setContents(new StringSelection(getPaths(files))); } - CopyPasteManager.getInstance().setContents(new StringSelection(getPaths(files))); } - private static String getPaths(Collection files) { - final StringBuilder buf = new StringBuilder(files.size() * 64); - boolean first = true; + private static String getPaths(VirtualFile[] files) { + StringBuilder buf = new StringBuilder(files.length * 64); for (VirtualFile file : files) { - if (first) { - first = false; - } - else { - buf.append("\n"); - } + if (buf.length() > 0) buf.append('\n'); buf.append(file.getPresentableUrl()); } return buf.toString(); } + @Override public void update(AnActionEvent event) { - final Collection files = getFiles(event); - final Presentation presentation = event.getPresentation(); - final boolean enabled = !files.isEmpty(); - presentation.setEnabled(enabled); - if (ActionPlaces.isPopupPlace(event.getPlace())) { - presentation.setVisible(enabled); - } - else { - presentation.setVisible(true); - } - presentation.setText((files.size() == 1) - ? IdeBundle.message("action.copy.path") - : IdeBundle.message("action.copy.paths")); + VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(event.getDataContext()); + int num = files != null ? files.length : 0; + Presentation presentation = event.getPresentation(); + presentation.setEnabled(num > 0); + presentation.setVisible(num > 0 || !ActionPlaces.isPopupPlace(event.getPlace())); + presentation.setText(IdeBundle.message(num == 1 ? "action.copy.path" : "action.copy.paths")); } - - @NotNull - private static Collection getFiles(AnActionEvent e) { - final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(e.getDataContext()); - if (files == null || files.length == 0) return Collections.emptyList(); - final ArrayList result = new ArrayList(files.length); - for (VirtualFile file : files) { - if (!(file instanceof LightVirtualFile)) { - result.add(file); - } - } - return result; - } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java index 4b5201e2c9ea..2143a176bd46 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java @@ -41,7 +41,7 @@ public class DeleteLineAction extends TextComponentEditorAction { } @Override - public void executeWriteAction(Editor editor, DataContext dataContext) { + public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) { CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP); CopyPasteManager.getInstance().stopKillRings(); SelectionModel selectionModel = editor.getSelectionModel(); @@ -76,7 +76,7 @@ public class DeleteLineAction extends TextComponentEditorAction { selectionModel.selectLineAtCaret(); boolean removeLastSymbol = selectionModel.getSelectionEnd() == document.getTextLength() && document.getLineCount() > 1; EditorModificationUtil.deleteSelectedText(editor); - if (removeLastSymbol) { + if (removeLastSymbol && document.getTextLength() > 0) { document.deleteString(document.getTextLength() - 1, document.getTextLength()); position = new VisualPosition(position.line - 1, position.column); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 83bb738ca263..109fe6b75d27 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2075,7 +2075,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private void paintComposedTextDecoration(@NotNull Graphics2D g) { - if (myInputMethodRequestsHandler != null && myInputMethodRequestsHandler.composedText != null) { + if (myInputMethodRequestsHandler != null + && myInputMethodRequestsHandler.composedText != null + && myInputMethodRequestsHandler.composedTextRange != null) { VisualPosition visStart = offsetToVisualPosition(Math.min(myInputMethodRequestsHandler.composedTextRange.getStartOffset(), myDocument.getTextLength())); int y = visibleLineToY(visStart.line) + getAscent() + 1; diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java index 18c5f76b670a..394dec20f4ef 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,7 @@ public class PluginAdvertiserEditorNotificationProvider extends EditorNotificati myNotifications = notifications; } + @NotNull @Override public Key getKey() { return KEY; @@ -59,7 +60,7 @@ public class PluginAdvertiserEditorNotificationProvider extends EditorNotificati @Nullable @Override - public EditorNotificationPanel createNotificationPanel(VirtualFile file, FileEditor fileEditor) { + public EditorNotificationPanel createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor) { if (file.getFileType() != PlainTextFileType.INSTANCE) return null; final String extension = file.getExtension(); diff --git a/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java index 24660c6674ab..800d8bd1dc63 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java @@ -90,6 +90,8 @@ public class EditorNotificationsImpl extends EditorNotifications { myCurrentUpdates.put(file, indicator); final ReadTask task = createTask(indicator, file); + if (task == null) return; + if (ApplicationManager.getApplication().isUnitTestMode()) { task.computeInReadAction(indicator); } @@ -106,11 +108,25 @@ public class EditorNotificationsImpl extends EditorNotifications { }); } + @Nullable private ReadTask createTask(final ProgressIndicator indicator, final VirtualFile file) { + final FileEditor[] editors = FileEditorManager.getInstance(myProject).getAllEditors(file); + if (editors.length == 0) return null; + return new ReadTask() { private boolean isOutdated() { - return myProject.isDisposed() || !file.isValid() || indicator != myCurrentUpdates.get(file); + if (myProject.isDisposed() || !file.isValid() || indicator != myCurrentUpdates.get(file)) { + return true; + } + + for (FileEditor editor : editors) { + if (!editor.isValid()) { + return true; + } + } + + return false; } @Override @@ -118,7 +134,7 @@ public class EditorNotificationsImpl extends EditorNotifications { if (isOutdated()) return; final List updates = ContainerUtil.newArrayList(); - for (final FileEditor editor : FileEditorManager.getInstance(myProject).getAllEditors(file)) { + for (final FileEditor editor : editors) { for (final Provider provider : Extensions.getExtensions(EXTENSION_POINT_NAME, myProject)) { final JComponent component = provider.createNotificationPanel(file, editor); updates.add(new Runnable() { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java index 63e040def381..deb63c13abf8 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java @@ -20,6 +20,8 @@ import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.testFramework.EditorTestUtil; import com.intellij.testFramework.TestFileType; +import java.io.IOException; + public class EditorActionTest extends AbstractEditorTest { public void testDownWithSelectionWhenCaretsAreAllowedInsideTabs() throws Exception { init("text", @@ -69,4 +71,35 @@ public class EditorActionTest extends AbstractEditorTest { executeAction("EditorTab"); checkResultByText("some text"); } + + public void testLineDeleteWithSelectionEndAtLineStart() throws IOException { + String text = + "line 1\n" + + "line 2\n" + + "line 3"; + init(text, TestFileType.TEXT); + deleteLine(); + checkResultByText( + "line 1\n" + + "line 3" + ); + } + + public void testDeleteLastLine() throws IOException { + String text = + "1\n" + + "2\n" + + "3"; + init(text, TestFileType.TEXT); + + deleteLine(); + deleteLine(); + checkResultByText("1"); + } + + public void testDeleteLastNonEmptyLine() throws IOException { + init("1\n", TestFileType.TEXT); + deleteLine(); + checkResultByText(""); + } } \ No newline at end of file diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java index 76157af7b808..39d5def0934f 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java @@ -25,6 +25,7 @@ public interface ScriptManager { * * @param newSource new text of script */ + @NotNull AsyncResult setSourceOnRemote(@NotNull Script script, @NotNull String newSource, boolean preview); void forEachScript(@NotNull Processor