From 1c7992ec752bcb2363b9fba5e7d5a99f29887ece Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Jul 2015 02:00:16 +0300 Subject: [PATCH 01/68] Fixed running Python plugin tests in IntelliJ The tests used to depend on python-community-tests, so some components from IdeaPlugin.xml didn't get initialized. Added a dependency on Python Community plugin resources for the correct plugin.xml. --- .../com/jetbrains/jython/PyJythonHighlightingTest.java | 4 ++-- .../com/jetbrains/jython/PyToJavaResolveTest.java | 4 ++-- python/python-plugin-tests.iml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/pluginTestSrc/com/jetbrains/jython/PyJythonHighlightingTest.java b/python/pluginTestSrc/com/jetbrains/jython/PyJythonHighlightingTest.java index 4ddef37bca86..744ee5cd98c7 100644 --- a/python/pluginTestSrc/com/jetbrains/jython/PyJythonHighlightingTest.java +++ b/python/pluginTestSrc/com/jetbrains/jython/PyJythonHighlightingTest.java @@ -16,7 +16,7 @@ package com.jetbrains.jython; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import com.jetbrains.python.PythonTestUtil; +import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.inspections.PyCallingNonCallableInspection; import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection; @@ -41,6 +41,6 @@ public class PyJythonHighlightingTest extends LightCodeInsightFixtureTestCase { @Override protected String getTestDataPath() { - return PythonTestUtil.getTestDataPath() + "/highlighting/jython/"; + return PythonHelpersLocator.getPythonCommunityPath() + "/testData/highlighting/jython/"; } } diff --git a/python/pluginTestSrc/com/jetbrains/jython/PyToJavaResolveTest.java b/python/pluginTestSrc/com/jetbrains/jython/PyToJavaResolveTest.java index a733592e0fef..1d9602795fa7 100644 --- a/python/pluginTestSrc/com/jetbrains/jython/PyToJavaResolveTest.java +++ b/python/pluginTestSrc/com/jetbrains/jython/PyToJavaResolveTest.java @@ -18,7 +18,7 @@ package com.jetbrains.jython; import com.intellij.psi.*; import com.intellij.testFramework.ResolveTestCase; import com.intellij.testFramework.TestDataPath; -import com.jetbrains.python.PythonTestUtil; +import com.jetbrains.python.PythonHelpersLocator; import junit.framework.Assert; /** @@ -87,6 +87,6 @@ public class PyToJavaResolveTest extends ResolveTestCase { @Override protected String getTestDataPath() { - return PythonTestUtil.getTestDataPath() + "/resolve/pyToJava/"; + return PythonHelpersLocator.getPythonCommunityPath() + "/testData/resolve/pyToJava/"; } } diff --git a/python/python-plugin-tests.iml b/python/python-plugin-tests.iml index 37a5ca500a58..7c666a1dd0a6 100644 --- a/python/python-plugin-tests.iml +++ b/python/python-plugin-tests.iml @@ -14,10 +14,10 @@ - + From c80b8263c77422f41a5977e551e8d70fd4a86dbb Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Jul 2015 13:10:43 +0300 Subject: [PATCH 02/68] Added a test for PY-14454 --- .../importSubModuleDunderAll/ImportSubModuleDunderAll.py | 4 ++++ .../multiFile/importSubModuleDunderAll/pkg1/__init__.py | 1 + .../resolve/multiFile/importSubModuleDunderAll/pkg1/m1.py | 2 ++ .../testSrc/com/jetbrains/python/PyMultiFileResolveTest.java | 3 +++ 4 files changed, 10 insertions(+) create mode 100644 python/testData/resolve/multiFile/importSubModuleDunderAll/ImportSubModuleDunderAll.py create mode 100644 python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/__init__.py create mode 100644 python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/m1.py diff --git a/python/testData/resolve/multiFile/importSubModuleDunderAll/ImportSubModuleDunderAll.py b/python/testData/resolve/multiFile/importSubModuleDunderAll/ImportSubModuleDunderAll.py new file mode 100644 index 000000000000..e5ee56c5fc66 --- /dev/null +++ b/python/testData/resolve/multiFile/importSubModuleDunderAll/ImportSubModuleDunderAll.py @@ -0,0 +1,4 @@ +from pkg1 import m1 + +print(m1) +# diff --git a/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/__init__.py b/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/__init__.py new file mode 100644 index 000000000000..a6d9575178da --- /dev/null +++ b/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/__init__.py @@ -0,0 +1 @@ +__all__ = ['m1'] diff --git a/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/m1.py b/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/m1.py new file mode 100644 index 000000000000..9332a2735b6a --- /dev/null +++ b/python/testData/resolve/multiFile/importSubModuleDunderAll/pkg1/m1.py @@ -0,0 +1,2 @@ +def foo(): + pass diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 97060e8922e3..fd5ee281e4a8 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -407,4 +407,7 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase { assertResolvesTo(PyFile.class, "z.py"); } + public void testImportSubModuleDunderAll() { + assertResolvesTo(PyFile.class, "m1.py"); + } } \ No newline at end of file From ca169137454dc4240680fa79d09ab88a47df98c1 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 30 Jun 2015 15:07:19 +0400 Subject: [PATCH 03/68] IDEA-141801 Undo applying patch should not be suggested in case of shelve * mark all locally exist files after unshelve as non undoable; * mark undo action invalidated for unshelved files --- .../src/git4idea/stash/GitShelveUtils.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java b/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java index 5629f96ded26..78b901fead73 100644 --- a/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java @@ -15,6 +15,10 @@ */ package git4idea.stash; +import com.intellij.openapi.command.impl.UndoManagerImpl; +import com.intellij.openapi.command.undo.DocumentReference; +import com.intellij.openapi.command.undo.DocumentReferenceManager; +import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.AsynchronousExecution; import com.intellij.openapi.project.Project; @@ -25,10 +29,14 @@ import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryFile; import com.intellij.openapi.vcs.changes.shelf.ShelvedChange; import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList; import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.continuation.ContinuationContext; import com.intellij.util.continuation.TaskDescriptor; import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,7 +68,7 @@ public class GitShelveUtils { VirtualFile baseDir = project.getBaseDir(); assert baseDir != null; final String projectPath = baseDir.getPath() + "/"; - + final List changes = shelvedChangeList.getChanges(project); context.next(new TaskDescriptor("Refreshing files before unshelve", Where.POOLED) { @Override public void run(ContinuationContext context) { @@ -76,11 +84,36 @@ public class GitShelveUtils { public void run(ContinuationContext context) { LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList); // we pass null as target change list for Patch Applier to do NOTHING with change lists - shelveManager.scheduleUnshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(project), + shelveManager.scheduleUnshelveChangeList(shelvedChangeList, changes, shelvedChangeList.getBinaryFiles(), null, false, context, true, true, leftConflictTitle, rightConflictTitle); } + }, new TaskDescriptor("", Where.AWT) { + @Override + public void run(ContinuationContext context) { + markUnshelvedFilesNonUndoable(project, changes); + } + }); + } + + @CalledInAwt + private static void markUnshelvedFilesNonUndoable(@NotNull final Project project, + @NotNull List changes) { + final UndoManagerImpl undoManager = (UndoManagerImpl)UndoManager.getInstance(project); + if (undoManager != null && !changes.isEmpty()) { + ContainerUtil.process(changes, new Processor() { + @Override + public boolean process(ShelvedChange change) { + final VirtualFile vfUnderProject = VfsUtil.findFileByIoFile(new File(project.getBasePath(), change.getAfterPath()), false); + if (vfUnderProject != null) { + final DocumentReference documentReference = DocumentReferenceManager.getInstance().create(vfUnderProject); + undoManager.nonundoableActionPerformed(documentReference, false); + undoManager.invalidateActionsFor(documentReference); + } + return true; + } }); + } } public static void refreshFilesBeforeUnshelve(final Project project, ShelvedChangeList shelvedChangeList, String projectPath) { From 0efca56879217838196f45bb45cf1603b388d781 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Mon, 29 Jun 2015 21:36:19 +0300 Subject: [PATCH 04/68] lost exclamation --- .../groovy/codeInsight/GroovyClsCustomNavigationPolicy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java index 6505e6e66044..ac9efb4e902f 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java @@ -31,7 +31,7 @@ public class GroovyClsCustomNavigationPolicy extends ClsCustomNavigationPolicyEx @Override @Nullable public PsiElement getNavigationElement(@NotNull ClsMethodImpl clsMethod) { - if (isGroovyLanguage(clsMethod)) return null; + if (!isGroovyLanguage(clsMethod)) return null; PsiMethod source = clsMethod.getSourceMirrorMethod(); if (source instanceof LightElement) { From ce93923e34caa685725a92cc54594d7d3d7c57ee Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 1 Jul 2015 15:11:28 +0300 Subject: [PATCH 05/68] PyCharm EDU jdk bundled linux artifact. --- python/edu/build/pycharm_edu_build.gant | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 6fb0e074345d..e1ed6b8f8aaf 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -203,6 +203,10 @@ public layoutEducational(String classesPath, Set usedJars) { String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix]) + if (p("jdk.bundled.linux") != "false") { + buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/bin/*"]) + } + String macAppRoot = isEap() ? "PyCharm Educational ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm Educational.app/Contents" buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac) From bc1876ca9f55037a2f9b67f55b6a070a225a7324 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 14:48:11 +0300 Subject: [PATCH 06/68] performance optimisation: do not call toString() repeatedly --- .../intellij/lang/impl/PsiBuilderImpl.java | 95 +++++++++++-------- .../psi/impl/source/tree/ASTStructure.java | 10 ++ .../src/com/intellij/util/diff/DiffTree.java | 18 +++- .../diff/FlyweightCapableTreeStructure.java | 3 + .../com/intellij/util/text/CharArrayUtil.java | 27 ++++-- .../com/intellij/util/diff/DiffTreeTest.java | 91 +++++++++++------- 6 files changed, 159 insertions(+), 85 deletions(-) diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 2a7a8075ad7e..7f2a21c2da20 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -97,28 +97,37 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private IElementType myCachedTokenType; private final LimitedPool START_MARKERS = new LimitedPool(2000, new LimitedPool.ObjectFactory() { + @NotNull @Override public StartMarker create() { return new StartMarker(); } @Override - public void cleanup(final StartMarker startMarker) { + public void cleanup(@NotNull final StartMarker startMarker) { startMarker.clean(); } }); private final LimitedPool DONE_MARKERS = new LimitedPool(2000, new LimitedPool.ObjectFactory() { + @NotNull @Override public DoneMarker create() { return new DoneMarker(); } @Override - public void cleanup(final DoneMarker doneMarker) { + public void cleanup(@NotNull final DoneMarker doneMarker) { doneMarker.clean(); } }); + private static final ArrayFactory myElementTypeArrayFactory = new ArrayFactory() { + @NotNull + @Override + public IElementType[] create(int count) { + return count == 0 ? IElementType.EMPTY_ARRAY : new IElementType[count]; + } + }; public static void registerWhitespaceToken(@NotNull IElementType type) { ourAnyLanguageWhitespaceTokens = TokenSet.orSet(ourAnyLanguageWhitespaceTokens, TokenSet.create(type)); @@ -190,11 +199,10 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @NotNull final LighterLazyParseableNode chameleon, @NotNull final CharSequence text) { this(project, chameleon.getContainingFile(), parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, - chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, ((LazyParseableToken)chameleon) - ); + chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, (LazyParseableToken)chameleon); } - private void cacheLexemes(LazyParseableToken parentToken) { + private void cacheLexemes(@Nullable LazyParseableToken parentToken) { int[] lexStarts = null; IElementType[] lexTypes = null; int lexemeCount = -1; @@ -418,6 +426,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } } + @NotNull @Override public Marker precede() { return myBuilder.precede(this); @@ -434,25 +443,25 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } @Override - public void done(IElementType type) { + public void done(@NotNull IElementType type) { myType = type; myBuilder.done(this); } @Override - public void collapse(IElementType type) { + public void collapse(@NotNull IElementType type) { myType = type; myBuilder.collapse(this); } @Override - public void doneBefore(IElementType type, Marker before) { + public void doneBefore(@NotNull IElementType type, @NotNull Marker before) { myType = type; myBuilder.doneBefore(this, before); } @Override - public void doneBefore(final IElementType type, final Marker before, final String errorMessage) { + public void doneBefore(@NotNull final IElementType type, @NotNull final Marker before, final String errorMessage) { final StartMarker marker = (StartMarker)before; myBuilder.myProduction.add(myBuilder.myProduction.lastIndexOf(marker), new ErrorItem(myBuilder, errorMessage, marker.myLexemeIndex)); @@ -466,7 +475,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } @Override - public void errorBefore(final String message, final Marker before) { + public void errorBefore(final String message, @NotNull final Marker before) { myType = TokenType.ERROR_ELEMENT; myBuilder.errorBefore(this, message, before); } @@ -509,6 +518,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } } + @NotNull private Marker precede(final StartMarker marker) { int idx = myProduction.lastIndexOf(marker); if (idx < 0) { @@ -680,7 +690,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private static class DoneWithErrorMarker extends DoneMarker { private String myMessage; - public DoneWithErrorMarker(final StartMarker marker, final int currentLexeme, final String message) { + private DoneWithErrorMarker(@NotNull StartMarker marker, final int currentLexeme, final String message) { super(marker, currentLexeme); myMessage = message; } @@ -871,14 +881,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } private void resizeLexemes(final int newSize) { - int count = Math.min(newSize, myLexTypes.length); - int[] newStarts = new int[newSize + 1]; - System.arraycopy(myLexStarts, 0, newStarts, 0, count); - myLexStarts = newStarts; - - IElementType[] newTypes = new IElementType[newSize]; - System.arraycopy(myLexTypes, 0, newTypes, 0, count); - myLexTypes = newTypes; + myLexStarts = ArrayUtil.realloc(myLexStarts, newSize+1); + myLexTypes = ArrayUtil.realloc(myLexTypes, newSize, myElementTypeArrayFactory); clearCachedTokenType(); } @@ -886,6 +890,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return myWhitespaces.contains(token) || myComments.contains(token); } + @NotNull @Override public Marker mark() { if (!myProduction.isEmpty()) { @@ -897,6 +902,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return marker; } + @NotNull private StartMarker createMarker(final int lexemeIndex) { StartMarker marker = START_MARKERS.alloc(); marker.myLexemeIndex = lexemeIndex; @@ -917,8 +923,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return myCurrentLexeme >= myLexemeCount; } - @SuppressWarnings("SuspiciousMethodCalls") - private void rollbackTo(Marker marker) { + private void rollbackTo(@NotNull Marker marker) { myCurrentLexeme = ((StartMarker)marker).myLexemeIndex; myTokenTypeChecked = true; int idx = myProduction.lastIndexOf(marker); @@ -934,7 +939,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { * * @return true if there are error elements created and not dropped after marker was created */ - public boolean hasErrorsAfter(Marker marker) { + public boolean hasErrorsAfter(@NotNull Marker marker) { assert marker instanceof StartMarker; int idx = myProduction.lastIndexOf(marker); if (idx < 0) { @@ -949,8 +954,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return false; } - @SuppressWarnings("SuspiciousMethodCalls") - public void drop(Marker marker) { + public void drop(@NotNull Marker marker) { final DoneMarker doneMarker = ((StartMarker)marker).myDoneMarker; if (doneMarker != null) { myProduction.remove(myProduction.lastIndexOf(doneMarker)); @@ -963,7 +967,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { START_MARKERS.recycle((StartMarker)marker); } - public void error(Marker marker, String message) { + public void error(@NotNull Marker marker, String message) { doValidityChecks(marker, null); DoneWithErrorMarker doneMarker = new DoneWithErrorMarker((StartMarker)marker, myCurrentLexeme, message); @@ -974,10 +978,10 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { myProduction.add(doneMarker); } - @SuppressWarnings("SuspiciousMethodCalls") - public void errorBefore(Marker marker, String message, Marker before) { + private void errorBefore(@NotNull Marker marker, String message, @NotNull Marker before) { doValidityChecks(marker, before); + @SuppressWarnings("SuspiciousMethodCalls") int beforeIndex = myProduction.lastIndexOf(before); DoneWithErrorMarker doneMarker = new DoneWithErrorMarker((StartMarker)marker, ((StartMarker)before).myLexemeIndex, message); @@ -988,7 +992,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { myProduction.add(beforeIndex, doneMarker); } - public void done(final Marker marker) { + public void done(@NotNull Marker marker) { doValidityChecks(marker, null); DoneMarker doneMarker = DONE_MARKERS.alloc(); @@ -1002,10 +1006,10 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { myProduction.add(doneMarker); } - @SuppressWarnings("SuspiciousMethodCalls") - public void doneBefore(Marker marker, Marker before) { + public void doneBefore(@NotNull Marker marker, @NotNull Marker before) { doValidityChecks(marker, before); + @SuppressWarnings("SuspiciousMethodCalls") int beforeIndex = myProduction.lastIndexOf(before); DoneMarker doneMarker = DONE_MARKERS.alloc(); @@ -1027,13 +1031,13 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return true; } - public void collapse(final Marker marker) { + public void collapse(@NotNull Marker marker) { done(marker); ((StartMarker)marker).myDoneMarker.myCollapse = true; } - @SuppressWarnings({"UseOfSystemOutOrSystemErr", "SuspiciousMethodCalls", "ThrowableResultOfMethodCallIgnored"}) - private void doValidityChecks(final Marker marker, @Nullable final Marker before) { + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + private void doValidityChecks(@NotNull Marker marker, @Nullable final Marker before) { final DoneMarker doneMarker = ((StartMarker)marker).myDoneMarker; if (doneMarker != null) { LOG.error("Marker already done."); @@ -1048,6 +1052,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { int endIdx = myProduction.size(); if (before != null) { + //noinspection SuspiciousMethodCalls endIdx = myProduction.lastIndexOf(before); if (endIdx < 0) { LOG.error("'Before' marker has never been added."); @@ -1330,6 +1335,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } @Override + @NotNull public CharSequence get(int i) { return myText.subSequence(myLexStarts[myStart + i], myLexStarts[myStart + i + 1]); } @@ -1349,7 +1355,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } } - private void bind(final StartMarker rootMarker, final CompositeElement rootNode) { + private void bind(@NotNull StartMarker rootMarker, @NotNull CompositeElement rootNode) { StartMarker curMarker = rootMarker; CompositeElement curNode = rootNode; @@ -1407,7 +1413,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return curToken; } - private int collapseLeaves(final CompositeElement ast, final StartMarker startMarker) { + private int collapseLeaves(@NotNull CompositeElement ast, @NotNull StartMarker startMarker) { final int start = myLexStarts[startMarker.myLexemeIndex]; final int end = myLexStarts[startMarker.myDoneMarker.myLexemeIndex]; final TreeElement leaf = createLeaf(startMarker.myType, start, end); @@ -1431,7 +1437,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } @Nullable - public static String getErrorMessage(final LighterASTNode node) { + public static String getErrorMessage(@NotNull LighterASTNode node) { if (node instanceof ErrorItem) return ((ErrorItem)node).myMessage; if (node instanceof StartMarker) { final StartMarker marker = (StartMarker)node; @@ -1448,7 +1454,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private final MyTreeStructure myTreeStructure; private MyComparator(TripleFunction, ThreeState> custom, - MyTreeStructure treeStructure) { + @NotNull MyTreeStructure treeStructure) { this.custom = custom; myTreeStructure = treeStructure; } @@ -1570,10 +1576,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { if (parentTree == null) { myPool = new LimitedPool(1000, new LimitedPool.ObjectFactory() { @Override - public void cleanup(final Token token) { + public void cleanup(@NotNull final Token token) { token.clean(); } + @NotNull @Override public Token create() { return new TokenNode(); @@ -1581,10 +1588,11 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { }); myLazyPool = new LimitedPool(200, new LimitedPool.ObjectFactory() { @Override - public void cleanup(final LazyParseableToken token) { + public void cleanup(@NotNull final LazyParseableToken token) { token.clean(); } + @NotNull @Override public LazyParseableToken create() { return new LazyParseableToken(); @@ -1727,6 +1735,15 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return myRoot.myBuilder.myText.subSequence(node.getStartOffset(), node.getEndOffset()); } + @Override + public int getStartOffset(@NotNull LighterASTNode node) { + return node.getStartOffset(); + } + + @Override + public int getEndOffset(@NotNull LighterASTNode node) { + return node.getEndOffset(); + } } private static class ASTConverter implements Convertor { diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ASTStructure.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ASTStructure.java index 947d7480bf67..9bb063f45973 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ASTStructure.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ASTStructure.java @@ -83,4 +83,14 @@ public class ASTStructure implements FlyweightCapableTreeStructure { public CharSequence toString(@NotNull ASTNode node) { return node.getChars(); } + + @Override + public int getStartOffset(@NotNull ASTNode node) { + return node.getStartOffset(); + } + + @Override + public int getEndOffset(@NotNull ASTNode node) { + return node.getStartOffset() + node.getTextLength(); + } } diff --git a/platform/util/src/com/intellij/util/diff/DiffTree.java b/platform/util/src/com/intellij/util/diff/DiffTree.java index e1f03bdb6e66..a04626f499aa 100644 --- a/platform/util/src/com/intellij/util/diff/DiffTree.java +++ b/platform/util/src/com/intellij/util/diff/DiffTree.java @@ -16,8 +16,8 @@ package com.intellij.util.diff; import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ThreeState; +import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -34,6 +34,10 @@ public class DiffTree { private final ShallowNodeComparator myComparator; private final List> myOldChildrenLists = new ArrayList>(); private final List> myNewChildrenLists = new ArrayList>(); + private final CharSequence myOldText; + private final CharSequence myNewText; + private final int myOldTreeStart; + private final int myNewTreeStart; private DiffTree(@NotNull FlyweightCapableTreeStructure oldTree, @NotNull FlyweightCapableTreeStructure newTree, @@ -41,6 +45,10 @@ public class DiffTree { myOldTree = oldTree; myNewTree = newTree; myComparator = comparator; + myOldText = oldTree.toString(oldTree.getRoot()); + myOldTreeStart = oldTree.getStartOffset(oldTree.getRoot()); + myNewText = newTree.toString(newTree.getRoot()); + myNewTreeStart = newTree.getStartOffset(newTree.getRoot()); } public static void diff(@NotNull FlyweightCapableTreeStructure oldTree, @@ -263,10 +271,12 @@ public class DiffTree { CompareResult c11 = looksEqual(myComparator, oldChild, newChild); if (c11 == CompareResult.DRILL_DOWN_NEEDED) { - CharSequence oldText = myOldTree.toString(oldChild); - CharSequence newText = myNewTree.toString(newChild); + int oldStart = myOldTree.getStartOffset(oldChild) - myOldTreeStart; + int oldEnd = myOldTree.getEndOffset(oldChild) - myOldTreeStart; + int newStart = myNewTree.getStartOffset(newChild) - myNewTreeStart; + int newEnd = myNewTree.getEndOffset(newChild) - myNewTreeStart; // drill down only if node texts match, but when they do, match all the way down unconditionally - c11 = StringUtil.equals(oldText, newText) + c11 = CharArrayUtil.regionMatches(myOldText, oldStart, oldEnd, myNewText, newStart, newEnd) ? build(oldChild, newChild, level + 1, DiffTree.emptyConsumer()) : CompareResult.NOT_EQUAL; } diff --git a/platform/util/src/com/intellij/util/diff/FlyweightCapableTreeStructure.java b/platform/util/src/com/intellij/util/diff/FlyweightCapableTreeStructure.java index df5da69b0a96..5e6cc3b1974c 100644 --- a/platform/util/src/com/intellij/util/diff/FlyweightCapableTreeStructure.java +++ b/platform/util/src/com/intellij/util/diff/FlyweightCapableTreeStructure.java @@ -39,4 +39,7 @@ public interface FlyweightCapableTreeStructure { @NotNull CharSequence toString(@NotNull T node); + + int getStartOffset(@NotNull T node); + int getEndOffset(@NotNull T node); } diff --git a/platform/util/src/com/intellij/util/text/CharArrayUtil.java b/platform/util/src/com/intellij/util/text/CharArrayUtil.java index 8ab04ee87055..b2adcad7df50 100644 --- a/platform/util/src/com/intellij/util/text/CharArrayUtil.java +++ b/platform/util/src/com/intellij/util/text/CharArrayUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -288,27 +288,36 @@ public class CharArrayUtil { return offset; } - public static boolean regionMatches(@NotNull char[] buffer, int offset, int bufferEnd, @NotNull CharSequence s) { + public static boolean regionMatches(@NotNull char[] buffer, int start, int end, @NotNull CharSequence s) { final int len = s.length(); - if (offset + len > bufferEnd) return false; - if (offset < 0) return false; + if (start + len > end) return false; + if (start < 0) return false; for (int i = 0; i < len; i++) { - if (buffer[offset + i] != s.charAt(i)) return false; + if (buffer[start + i] != s.charAt(i)) return false; } return true; } - public static boolean regionMatches(@NotNull CharSequence buffer, int offset, int bufferEnd, @NotNull CharSequence s) { + public static boolean regionMatches(@NotNull CharSequence buffer, int start, int end, @NotNull CharSequence s) { final int len = s.length(); - if (offset + len > bufferEnd) return false; - if (offset < 0) return false; + if (start + len > end) return false; + if (start < 0) return false; //if (buffer instanceof String && s instanceof String) { // return ((String)buffer).regionMatches(offset, (String)s, 0, len); //} for (int i = 0; i < len; i++) { - if (buffer.charAt(offset + i) != s.charAt(i)) return false; + if (buffer.charAt(start + i) != s.charAt(i)) return false; + } + return true; + } + + public static boolean regionMatches(@NotNull CharSequence s1, int start1, int end1, @NotNull CharSequence s2, int start2, int end2) { + if (end1-start1 != end2-start2) return false; + + for (int i = start1,j=start2; i < end1; i++,j++) { + if (s1.charAt(i) != s2.charAt(j)) return false; } return true; } diff --git a/platform/util/testSrc/com/intellij/util/diff/DiffTreeTest.java b/platform/util/testSrc/com/intellij/util/diff/DiffTreeTest.java index f3e5a1fd91c0..3e144b208b91 100644 --- a/platform/util/testSrc/com/intellij/util/diff/DiffTreeTest.java +++ b/platform/util/testSrc/com/intellij/util/diff/DiffTreeTest.java @@ -16,6 +16,9 @@ package com.intellij.util.diff; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; import com.intellij.util.ThreeState; import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; @@ -30,11 +33,13 @@ import java.util.List; @SuppressWarnings({"HardCodedStringLiteral"}) public class DiffTreeTest extends TestCase { private static class Node { + private final int myStartOffset; @NotNull private final Node[] myChildren; private final int myId; - public Node(final int id, @NotNull Node... children) { + public Node(final int id, int startOffset, @NotNull Node... children) { + myStartOffset = startOffset; myChildren = children; myId = id; } @@ -55,7 +60,17 @@ public class DiffTreeTest extends TestCase { @Override public String toString() { - return String.valueOf(myId); + return getChildren().length == 0 ? String.valueOf(myId) : StringUtil.join(myChildren, new Function() { + @Override + public String fun(Node node) { + return node.toString(); + } + }, ""); + } + + public TextRange getTextRange() { + int endOffset = myChildren.length == 0 ? myStartOffset + toString().length() : myChildren[myChildren.length-1].getTextRange().getEndOffset(); + return new TextRange(myStartOffset, endOffset); } } @@ -98,6 +113,16 @@ public class DiffTreeTest extends TestCase { public CharSequence toString(@NotNull Node node) { return node.toString(); } + + @Override + public int getStartOffset(@NotNull Node node) { + return node.getTextRange().getStartOffset(); + } + + @Override + public int getEndOffset(@NotNull Node node) { + return node.getTextRange().getEndOffset(); + } } private static class NodeComparator implements ShallowNodeComparator { @@ -123,17 +148,17 @@ public class DiffTreeTest extends TestCase { @Override public void nodeReplaced(@NotNull final Node oldNode, @NotNull final Node newNode) { - myResults.add("REPLACED: " + oldNode + " to " + newNode); + myResults.add("REPLACED: " + oldNode.getId() + " to " + newNode.getId()); } @Override public void nodeDeleted(@NotNull final Node parent, @NotNull final Node child) { - myResults.add("DELETED from " + parent + ": " + child); + myResults.add("DELETED from " + parent.getId() + ": " + child.getId()); } @Override public void nodeInserted(@NotNull final Node oldParent, @NotNull final Node node, final int pos) { - myResults.add("INSERTED to " + oldParent + ": " + node + " at " + pos); + myResults.add("INSERTED to " + oldParent.getId() + ": " + node.getId() + " at " + pos); } public List getEvents() { @@ -142,32 +167,32 @@ public class DiffTreeTest extends TestCase { } public void testEmptyEqualRoots() throws Exception { - Node r1 = new Node(0); - Node r2 = new Node(0); + Node r1 = new Node(0,0); + Node r2 = new Node(0,0); final String expected = ""; performTest(r1, r2, expected); } public void testSingleChildEqualRoots() throws Exception { - Node r1 = new Node(0, new Node(1)); - Node r2 = new Node(0, new Node(1)); + Node r1 = new Node(0,0, new Node(1,0)); + Node r2 = new Node(0,0, new Node(1,0)); final String expected = ""; performTest(r1, r2, expected); } public void testTheOnlyChildRemoved() throws Exception { - Node r1 = new Node(0, new Node(1)); - Node r2 = new Node(0); + Node r1 = new Node(0,0, new Node(1,0)); + Node r2 = new Node(0,0); String expected = "DELETED from 0: 1"; performTest(r1, r2, expected); } public void testTheOnlyChildAdded() throws Exception { - Node r1 = new Node(0); - Node r2 = new Node(0, new Node(1)); + Node r1 = new Node(0,0); + Node r2 = new Node(0,0, new Node(1,0)); String expected = "INSERTED to 0: 1 at 0"; performTest(r1, r2, expected); @@ -175,56 +200,56 @@ public class DiffTreeTest extends TestCase { } public void testTheOnlyChildReplaced() throws Exception { - Node r1 = new Node(0, new Node(1)); - Node r2 = new Node(0, new Node(2)); + Node r1 = new Node(0,0, new Node(1,0)); + Node r2 = new Node(0,0, new Node(2,0)); String expected = "REPLACED: 1 to 2"; performTest(r1, r2, expected); } public void testInsertedIntoTheMiddle() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(21), new Node(23))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(22), new Node(23))); - String expected = "INSERTED to 1: 22 at 1"; + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1))); + Node r2 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(4,1), new Node(3,2))); + String expected = "INSERTED to 1: 4 at 1"; performTest(r1, r2, expected); } public void testInsertedFirst() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(22), new Node(23))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(22), new Node(23))); - String expected = "INSERTED to 1: 21 at 0"; + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(4,1))); + Node r2 = new Node(0,0, new Node(1,0, new Node(3,0), new Node(2,1), new Node(4,2))); + String expected = "INSERTED to 1: 3 at 0"; performTest(r1, r2, expected); } public void testInsertedLast() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(21), new Node(22))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(22), new Node(23))); - String expected = "INSERTED to 1: 23 at 2"; + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1))); + Node r2 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1), new Node(4,2))); + String expected = "INSERTED to 1: 4 at 2"; performTest(r1, r2, expected); } public void testInsertedTwoLast() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(21), new Node(22))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(22), new Node(23), new Node(24))); + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1))); + Node r2 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1), new Node(4,2), new Node(5,3))); - performTest(r1, r2, "INSERTED to 1: 24 at 2", "INSERTED to 1: 23 at 2"); + performTest(r1, r2, "INSERTED to 1: 5 at 2", "INSERTED to 1: 4 at 2"); } public void testSubtreeAppears() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(21), new Node(22), new Node(23))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(22, new Node(221)), new Node(23))); + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1), new Node(4,2))); + Node r2 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1, new Node(6,1)), new Node(4,2))); - performTest(r1, r2, "INSERTED to 22: 221 at 0"); + performTest(r1, r2, "INSERTED to 3: 6 at 0"); } public void testSubtreeChanges() throws Exception { - Node r1 = new Node(0, new Node(1, new Node(21), new Node(22, new Node(221)), new Node(23))); - Node r2 = new Node(0, new Node(1, new Node(21), new Node(250, new Node(222)), new Node(23))); + Node r1 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(3,1, new Node(6,1)), new Node(4,2))); + Node r2 = new Node(0,0, new Node(1,0, new Node(2,0), new Node(5,1, new Node(6,1)), new Node(4,2))); - performTest(r1, r2, "REPLACED: 22 to 250"); + performTest(r1, r2, "REPLACED: 3 to 5"); } private static void performTest(final Node r1, final Node r2, final String... expected) { From dca0b4ec8c82db5fba84fad64a8b810f72147412 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 14:51:13 +0300 Subject: [PATCH 07/68] protection against incorrectly implemented createFile() which could lead to mysterious invalidations, especially in Kotlin --- .../src/com/intellij/psi/SingleRootFileViewProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index f4eca37a558e..9741110e23cf 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -180,6 +180,9 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi boolean set = myPsiFile.compareAndSet(null, psiFile); if (!set) { if (psiFile instanceof PsiFileImpl) { + if (myPsiFile.get() == psiFile) { + LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); + } ((PsiFileImpl)psiFile).markInvalidated(); } psiFile = myPsiFile.get(); From 9ee75aaf085feb7d3b8e8e648b827a72387224d4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 1 Jul 2015 13:59:33 +0200 Subject: [PATCH 08/68] clear Introspector caches without reflection --- .../testFramework/LightPlatformTestCase.java | 2 +- .../src/com/intellij/util/GCUtil.java | 20 +++---------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 79abae8f7bea..d19ec3da8c49 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -594,7 +594,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da if (ourTestCount++ % 100 == 0) { // some tests are written in Groovy, and running all of them may result in some 40M of memory wasted on bean infos // so let's clear the cache every now and then to ensure it doesn't grow too large - GCUtil.tryClearBeanInfoCache(); + GCUtil.clearBeanInfoCache(); } } diff --git a/platform/testFramework/src/com/intellij/util/GCUtil.java b/platform/testFramework/src/com/intellij/util/GCUtil.java index 78c1013373fe..a179692dca9a 100644 --- a/platform/testFramework/src/com/intellij/util/GCUtil.java +++ b/platform/testFramework/src/com/intellij/util/GCUtil.java @@ -15,14 +15,13 @@ */ package com.intellij.util; -import com.intellij.openapi.util.SystemInfo; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.TestOnly; +import java.beans.Introspector; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; -import java.lang.reflect.Method; import java.util.ArrayList; public class GCUtil { @@ -79,25 +78,12 @@ public class GCUtil { return o == null ? 0 : Math.abs(o.hashCode()) % 10; } - private static final boolean ourHasBeanInfoCache = SystemInfo.isJavaVersionAtLeast("1.7"); - /** * Using java beans (e.g. Groovy does it) results in all referenced class infos being cached in ThreadGroupContext. A valid fix * would be to hold BeanInfo objects on soft references, but that should be done in JDK. So let's clear this cache manually for now, * in clients that are known to create bean infos. */ - public static void tryClearBeanInfoCache() { - if (ourHasBeanInfoCache) { - try { - Class aClass = Class.forName("java.beans.ThreadGroupContext"); - Method getContextMethod = aClass.getDeclaredMethod("getContext"); - getContextMethod.setAccessible(true); - Object contextForThreadGroup = getContextMethod.invoke(null); - Method clearBeanInfoCacheMethod = contextForThreadGroup.getClass().getDeclaredMethod("clearBeanInfoCache"); - clearBeanInfoCacheMethod.setAccessible(true); - clearBeanInfoCacheMethod.invoke(contextForThreadGroup); - } - catch (Throwable ignore) {} - } + public static void clearBeanInfoCache() { + Introspector.flushCaches(); } } From c0b811434124d55583a2e84babedf4edd0eb3f4d Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 1 Jul 2015 14:08:30 +0200 Subject: [PATCH 09/68] schedule update in dumb mode once requestRebuild was called. Previously, requestRebuild only marked need for rebuild and index access causes rebuild to start. --- .../util/indexing/FileBasedIndexImpl.java | 115 ++++++++---------- 1 file changed, 51 insertions(+), 64 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 00d746ad469e..52f6d4ae20ea 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -122,7 +122,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { private static final int OK = 1; private static final int REQUIRES_REBUILD = 2; - private static final int REBUILD_IN_PROGRESS = 3; private static final Map, AtomicInteger> ourRebuildStatus = new THashMap, AtomicInteger>(); private final MessageBusConnection myConnection; @@ -679,7 +678,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { for (ID indexId : myIndices.keySet()) { final UpdatableIndex index = getIndex(indexId); assert index != null; - checkRebuild(indexId, true); // if the index was scheduled for rebuild, only clean it + if(ourRebuildStatus.get(indexId).get() != OK) { + doClearIndex(indexId); // if the index was scheduled for rebuild, only clean it + } index.dispose(); } @@ -825,7 +826,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { myChangedFilesCollector.tryToEnsureAllInvalidateTasksCompleted(); if (isUpToDateCheckEnabled()) { try { - checkRebuild(indexId, false); + if (ourRebuildStatus.get(indexId).get() != OK) { + throw new ProcessCanceledException(); + } myChangedFilesCollector.forceUpdate(project, filter, restrictedFile); indexUnsavedDocuments(indexId, project, filter, restrictedFile); } @@ -1225,65 +1228,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { @Override public void scheduleRebuild(@NotNull final ID indexId, @NotNull final Throwable e) { requestRebuild(indexId, new Throwable(e)); - try { - checkRebuild(indexId, false); - } - catch (ProcessCanceledException ignored) { - } - } - - private void checkRebuild(@NotNull final ID indexId, final boolean cleanupOnly) { - final AtomicInteger status = ourRebuildStatus.get(indexId); - if (status.get() == OK) { - return; - } - if (status.compareAndSet(REQUIRES_REBUILD, REBUILD_IN_PROGRESS)) { - cleanupProcessedFlag(); - - advanceIndexVersion(indexId); - - final Runnable rebuildRunnable = new Runnable() { - @Override - public void run() { - try { - doClearIndex(indexId); - if (!cleanupOnly) { - scheduleIndexRebuild("checkRebuild"); - } - } - catch (StorageException e) { - requestRebuild(indexId); - LOG.info(e); - } - finally { - status.compareAndSet(REBUILD_IN_PROGRESS, OK); - } - } - }; - - if (cleanupOnly || myIsUnitTestMode) { - rebuildRunnable.run(); - } - else { - //noinspection SSBasedInspection - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - new Task.Modal(null, "Updating index", false) { - @Override - public void run(@NotNull final ProgressIndicator indicator) { - indicator.setIndeterminate(true); - rebuildRunnable.run(); - } - }.queue(); - } - }, ModalityState.NON_MODAL); - } - } - - if (status.get() == REBUILD_IN_PROGRESS) { - throw new ProcessCanceledException(); - } } private static void scheduleIndexRebuild(String reason) { @@ -1547,9 +1491,11 @@ public class FileBasedIndexImpl extends FileBasedIndex { } @Override - public void requestRebuild(ID indexId, Throwable throwable) { + public void requestRebuild(final ID indexId, final Throwable throwable) { cleanupProcessedFlag(); - boolean requiresRebuildWasSet = ourRebuildStatus.get(indexId).compareAndSet(OK, REQUIRES_REBUILD); + final AtomicInteger status = ourRebuildStatus.get(indexId); + boolean requiresRebuildWasSet = status.compareAndSet(OK, REQUIRES_REBUILD); + if (requiresRebuildWasSet) { String message = "Rebuild requested for index " + indexId; Application app = ApplicationManager.getApplication(); @@ -1560,6 +1506,47 @@ public class FileBasedIndexImpl extends FileBasedIndex { } else { LOG.info(message, throwable); } + + cleanupProcessedFlag(); + + advanceIndexVersion(indexId); + + final Runnable rebuildRunnable = new Runnable() { + @Override + public void run() { + try { + doClearIndex(indexId); + scheduleIndexRebuild("checkRebuild"); + } + catch (StorageException e) { + requestRebuild(indexId); + LOG.info(e); + } + finally { + status.compareAndSet(REQUIRES_REBUILD, OK); + } + } + }; + + if (myIsUnitTestMode) { + rebuildRunnable.run(); + } + else { + // we do invoke later since we can have read lock acquired + //noinspection SSBasedInspection + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new Task.Modal(null, "Updating index", false) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + indicator.setIndeterminate(true); + rebuildRunnable.run(); + } + }.queue(); + } + }, ModalityState.NON_MODAL); + } } } From 5835c04c6bd384f16c4d515a9d6a6d5a09037d2d Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 1 Jul 2015 14:12:58 +0200 Subject: [PATCH 10/68] IDETalk added to list of checked plugins --- platform/platform-resources/src/checkedPlugins.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-resources/src/checkedPlugins.txt b/platform/platform-resources/src/checkedPlugins.txt index 1209f9d9be25..7d80cf054556 100644 --- a/platform/platform-resources/src/checkedPlugins.txt +++ b/platform/platform-resources/src/checkedPlugins.txt @@ -19,4 +19,5 @@ com.jetbrains.plugins.ini4idea com.jetbrains.plugins.meteor AWSCloudFormation Dart -IdeaVIM \ No newline at end of file +IdeaVIM +IDETalk \ No newline at end of file From 648fe87a05b590e5a8f975d9ffa9b041f428ab1c Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Jul 2015 15:51:54 +0300 Subject: [PATCH 11/68] Prefer submodules to '__all__' defined in the package (PY-14454) We resolved references to attributes / submodules of a package to '__all__' if we found the name of the attribute in '__all__'. That is OK as a fallback if there is no appropriate submodule, but in other cases we now resolve the reference to a submodule, not to '__all__'. --- .../python/psi/resolve/ResolveImportUtil.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 7f2596e9c0c6..4889a02c01ff 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -257,8 +257,7 @@ public class ResolveImportUtil { } /** - * Tries to find referencedName under the parent element. Used to resolve any names that look imported. - * Parent might happen to be a PyFile(__init__.py), then it is treated both as a file and as ist base dir. + * Tries to find referencedName under the parent element. * * @param parent element under which to look for referenced name; if null, null is returned. * @param referencedName which name to look for. @@ -266,17 +265,15 @@ public class ResolveImportUtil { * @param fileOnly if true, considers only a PsiFile child as a valid result; non-file hits are ignored. * @param checkForPackage if true, directories are returned only if they contain __init__.py * @return the element the referencedName resolves to, or null. - * @todo: Honor module's __all__ value. - * @todo: Honor package's __path__ value (hard). */ @Nullable public static PsiElement resolveChild(@Nullable final PsiElement parent, @NotNull final String referencedName, @Nullable final PsiFile containingFile, boolean fileOnly, boolean checkForPackage) { PsiDirectory dir = null; PsiElement resultElement = null; - PsiElement possibleResult = null; final PyResolveContext resolveContext = PyResolveContext.defaultContext(); if (parent instanceof PyFileImpl) { + PsiElement possibleResult = null; if (PyNames.INIT_DOT_PY.equals(((PyFile)parent).getName())) { // gobject does weird things like '_gobject = sys.modules['gobject._gobject'], so it's preferable to look at // files before looking at names exported from __init__.py @@ -294,11 +291,15 @@ public class ResolveImportUtil { resultElement = moduleMember; } if (resultElement != null && !PyUtil.instanceOf(resultElement, PsiFile.class, PsiDirectory.class) && - PsiTreeUtil.getStubOrPsiParentOfType(resultElement, PyExceptPart.class) == null) { + PsiTreeUtil.getStubOrPsiParentOfType(resultElement, PyExceptPart.class) == null && !isDunderAll(resultElement)) { return resultElement; } if (possibleResult != null) return possibleResult; + + if (resultElement != null) { + return resultElement; + } } else if (parent instanceof PsiDirectory) { dir = (PsiDirectory)parent; @@ -325,7 +326,11 @@ public class ResolveImportUtil { } } } - return resultElement; + return null; + } + + private static boolean isDunderAll(@NotNull PsiElement element) { + return (element instanceof PyElement) && PyNames.ALL.equals(((PyElement)element).getName()); } @Nullable From a6e287397357faa53d874cf1165db9a00e49c9b6 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Jul 2015 16:01:30 +0300 Subject: [PATCH 12/68] Removed unnecessary comments --- .../com/jetbrains/python/psi/resolve/ResolveImportUtil.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 4889a02c01ff..b156b608c6bb 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -275,14 +275,10 @@ public class ResolveImportUtil { if (parent instanceof PyFileImpl) { PsiElement possibleResult = null; if (PyNames.INIT_DOT_PY.equals(((PyFile)parent).getName())) { - // gobject does weird things like '_gobject = sys.modules['gobject._gobject'], so it's preferable to look at - // files before looking at names exported from __init__.py dir = ((PyFile)parent).getContainingDirectory(); possibleResult = resolveInDirectory(referencedName, containingFile, dir, fileOnly, checkForPackage); } - // OTOH, quite often a module named foo exports a class or function named foo, which is used as a fallback - // by a module one level higher (e.g. curses.set_key). Prefer it to submodule if possible. final PyModuleType moduleType = new PyModuleType((PyFile)parent); final List results = moduleType.resolveMember(referencedName, null, AccessDirection.READ, resolveContext); @@ -315,7 +311,6 @@ public class ResolveImportUtil { } if (dir != null) { final PsiElement result = resolveInDirectory(referencedName, containingFile, dir, fileOnly, checkForPackage); - //if (fileOnly && ! (result instanceof PsiFile) && ! (result instanceof PsiDirectory)) return null; if (result != null) { return result; } From 815f30f45551390a8ecb33467660753c0a1fa36c Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 1 Jul 2015 16:03:13 +0300 Subject: [PATCH 13/68] IDEA-142156 Project leak on SheetController$2 --- .../src/com/intellij/ui/messages/SheetController.java | 4 ++++ .../src/com/intellij/ui/messages/SheetMessage.java | 1 + 2 files changed, 5 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java index 86edcab49f22..ab68db206d15 100755 --- a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java +++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java @@ -492,4 +492,8 @@ public class SheetController { public String getResult() { return myResult; } + + public void dispose() { + mySheetPanel.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)); + } } diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java index e9627386eb88..0b2eb2ecd1a2 100755 --- a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java +++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java @@ -228,6 +228,7 @@ public class SheetMessage { if (restoreFullScreenButton) { FullScreenUtilities.setWindowCanFullScreen(myParent, true); } + myController.dispose(); myWindow.dispose(); } } From 7e7210381735cda65e141960ecec76a7f09ec7f3 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 1 Jul 2015 13:06:53 +0200 Subject: [PATCH 14/68] don't fail on null file path #IDEA-142041 fixed --- .../plugincomponents/SettingsProviderComponent.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java index 0d2c59e931cc..1655e5f3105e 100644 --- a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java @@ -31,6 +31,8 @@ public class SettingsProviderComponent { } public List getOutPairs(Project project, String filePath) { + if (filePath == null) return Collections.emptyList(); + final List outPairs; try { final Set rootDirs = getRootDirs(project); From 6abee65b9c72b844007a336c85835f18e70b6c90 Mon Sep 17 00:00:00 2001 From: Pavel Fatin Date: Wed, 1 Jul 2015 15:28:29 +0200 Subject: [PATCH 15/68] DocumentationManager: don't depend on ActionManagerEx unnecessarily (relevant for Upsource) --- .../documentation/DocumentationManager.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 995110c7d172..0a1d25315b42 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -33,7 +33,6 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguageDocumentation; import com.intellij.lang.documentation.*; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -96,7 +95,7 @@ public class DocumentationManager extends DockablePopupManager ORIGINAL_ELEMENT_KEY = Key.create("Original element"); - private final ActionManagerEx myActionManagerEx; + private final ActionManager myActionManager; private final TargetElementUtil myTargetElementUtil; @@ -161,9 +160,9 @@ public class DocumentationManager extends DockablePopupManager> actions = ContainerUtil.newSmartList(); - AnAction quickDocAction = ActionManagerEx.getInstanceEx().getAction(IdeActions.ACTION_QUICK_JAVADOC); + AnAction quickDocAction = ActionManager.getInstance().getAction(IdeActions.ACTION_QUICK_JAVADOC); for (Shortcut shortcut : quickDocAction.getShortcutSet().getShortcuts()) { if (!(shortcut instanceof KeyboardShortcut)) continue; actions.add(Pair.create(actionListener, ((KeyboardShortcut)shortcut).getFirstKeyStroke())); From 2328919c0e6698031d84a3c539e4ea7506cfc7bb Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 1 Jul 2015 16:06:09 +0200 Subject: [PATCH 16/68] - use fileId for updateSingleIndex - extracted common method --- .../util/indexing/FileBasedIndexImpl.java | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 52f6d4ae20ea..e327cf9e2d6f 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1623,6 +1623,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { try { PsiFile psiFile = null; FileContentImpl fc = null; + int inputId = -1; final List> affectedIndexCandidates = getAffectedIndexCandidates(file); //noinspection ForLoopReplaceableByForEach @@ -1658,11 +1659,12 @@ public class FileBasedIndexImpl extends FileBasedIndex { psiFile = content.getUserData(IndexingDataKeys.PSI_FILE); initFileContent(fc, project, psiFile); + inputId = Math.abs(getFileId(file)); } try { ProgressManager.checkCanceled(); - updateSingleIndex(indexId, file, fc); + updateSingleIndex(indexId, inputId, fc); } catch (ProcessCanceledException e) { cleanFileContent(fc, psiFile); @@ -1714,14 +1716,13 @@ public class FileBasedIndexImpl extends FileBasedIndex { fc.putUserData(IndexingDataKeys.PROJECT, project); } - private void updateSingleIndex(@NotNull ID indexId, @NotNull final VirtualFile file, @Nullable FileContent currentFC) + private void updateSingleIndex(@NotNull ID indexId, final int inputId, @Nullable FileContent currentFC) throws StorageException { if (ourRebuildStatus.get(indexId).get() == REQUIRES_REBUILD) { return; // the index is scheduled for rebuild, no need to update } myLocalModCount++; - final int inputId = Math.abs(getFileId(file)); final UpdatableIndex index = getIndex(indexId); assert index != null; @@ -1736,7 +1737,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { try { scheduleUpdate(indexId, createUpdateComputableWithBufferingDisabled(update), - createIndexedStampUpdateRunnable(indexId, file, currentFC != null) + createIndexedStampUpdateRunnable(indexId, inputId, currentFC != null) ); } catch (RuntimeException exception) { Throwable causeToRebuildIndex = getCauseToRebuildIndex(exception); @@ -1753,21 +1754,18 @@ public class FileBasedIndexImpl extends FileBasedIndex { @NotNull private Runnable createIndexedStampUpdateRunnable(@NotNull final ID indexId, - @NotNull final VirtualFile file, + final int fileId, final boolean hasContent) { return new Runnable() { @Override public void run() { - if (file.isValid()) { - int fileId = getIdMaskingNonIdBasedFile(file); - if (hasContent) { - IndexingStamp.setFileIndexedStateCurrent(fileId, indexId); - } - else { - IndexingStamp.setFileIndexedStateUnindexed(fileId, indexId); - } - if (myNotRequiringContentIndices.contains(indexId)) IndexingStamp.flushCache(fileId); + if (hasContent) { + IndexingStamp.setFileIndexedStateCurrent(fileId, indexId); } + else { + IndexingStamp.setFileIndexedStateUnindexed(fileId, indexId); + } + if (myNotRequiringContentIndices.contains(indexId)) IndexingStamp.flushCache(fileId); } }; } @@ -1934,13 +1932,15 @@ public class FileBasedIndexImpl extends FileBasedIndex { boolean fileIsDirectory = file.isDirectory(); if (!contentChange) { FileContent fileContent = null; + int inputId = -1; for (ID indexId : fileIsDirectory ? myIndicesForDirectories : myNotRequiringContentIndices) { if (getInputFilter(indexId).acceptInput(file)) { try { if (fileContent == null) { fileContent = new FileContentImpl(file); + inputId = Math.abs(getFileId(file)); } - updateSingleIndex(indexId, file, fileContent); + updateSingleIndex(indexId, inputId, fileContent); } catch (StorageException e) { LOG.info(e); @@ -2035,16 +2035,16 @@ public class FileBasedIndexImpl extends FileBasedIndex { private void invalidateIndicesForFile(@NotNull final VirtualFile file, boolean markForReindex) { cleanProcessedFlag(file); - IndexingStamp.flushCache(file); - final int fileId = getIdMaskingNonIdBasedFile(file); + final int fileId = Math.abs(getIdMaskingNonIdBasedFile(file)); + IndexingStamp.flushCache(fileId); List> nontrivialFileIndexedStates = IndexingStamp.getNontrivialFileIndexedStates(fileId); if (!markForReindex) { // markForReindex really means content changed for (ID indexId : nontrivialFileIndexedStates) { if (myNotRequiringContentIndices.contains(indexId)) { try { - updateSingleIndex(indexId, file, null); + updateSingleIndex(indexId, fileId, null); } catch (StorageException e) { LOG.info(e); @@ -2080,19 +2080,19 @@ public class FileBasedIndexImpl extends FileBasedIndex { myFutureInvalidations.offer(new InvalidationTask(file) { @Override public void run() { - removeFileDataFromIndices(finalFileIndexedStatesToUpdate, getSubj()); + removeFileDataFromIndices(finalFileIndexedStatesToUpdate, fileId); } }); } - IndexingStamp.flushCache(file); + IndexingStamp.flushCache(fileId); } - private void removeFileDataFromIndices(@NotNull Collection> affectedIndices, @NotNull VirtualFile file) { + private void removeFileDataFromIndices(@NotNull Collection> affectedIndices, int inputId) { Throwable unexpectedError = null; for (ID indexId : affectedIndices) { try { - updateSingleIndex(indexId, file, null); + updateSingleIndex(indexId, inputId, null); } catch (StorageException e) { LOG.info(e); @@ -2108,7 +2108,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } } - IndexingStamp.flushCache(file); + IndexingStamp.flushCache(inputId); if (unexpectedError != null) { LOG.error(unexpectedError); } @@ -2228,7 +2228,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { try { if (isTooLarge(file)) { List> nontrivialFileIndexedStates = IndexingStamp.getNontrivialFileIndexedStates(fileId); - removeFileDataFromIndices(ContainerUtil.intersection(nontrivialFileIndexedStates, myRequiringContentIndices), file); + removeFileDataFromIndices(ContainerUtil.intersection(nontrivialFileIndexedStates, myRequiringContentIndices), Math.abs(fileId)); } else { doIndexFileContent(project, fileContent); @@ -2250,10 +2250,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { myContentlessIndicesUpdateQueue.ensureUpToDate(); for (VFileEvent event : events) { - Object requestor = event.getRequestor(); - if (requestor instanceof FileDocumentManager || - requestor instanceof PsiManager || - requestor == LocalHistory.VFS_EVENT_REQUESTOR) { + if (memoryStorageCleaningNeeded(event)) { cleanupMemoryStorage(); break; } @@ -2263,6 +2260,13 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } + private boolean memoryStorageCleaningNeeded(VFileEvent event) { + Object requestor = event.getRequestor(); + return requestor instanceof FileDocumentManager || + requestor instanceof PsiManager || + requestor == LocalHistory.VFS_EVENT_REQUESTOR; + } + @Override public void after(@NotNull List events) { myContentlessIndicesUpdateQueue.ensureUpToDate(); @@ -2377,14 +2381,16 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } FileContent fileContent = null; + int inputId = -1; for (ID indexId : myNotRequiringContentIndices) { if (shouldIndexFile(file, indexId)) { oldStuff = false; try { if (fileContent == null) { fileContent = new FileContentImpl(file); + inputId = Math.abs(getFileId(file)); } - updateSingleIndex(indexId, file, fileContent); + updateSingleIndex(indexId, inputId, fileContent); } catch (StorageException e) { LOG.info(e); From 7313ffded5823e42b1bb3dbf6e7267809c8eeef6 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 15:08:21 +0200 Subject: [PATCH 17/68] dumb-aware GutterIconRenderer (EA-66681 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../editor/markup/GutterIconRenderer.java | 7 +++- .../impl/EditorGutterComponentImpl.java | 39 ++++++++++--------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java index b4f3dcbc30e8..ad865eae4bed 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/markup/GutterIconRenderer.java @@ -26,10 +26,13 @@ import javax.swing.*; /** * Interface which should be implemented in order to draw icons in the gutter area and handle events * for them. Gutter icons are drawn to the left of the folding area and can be used, for example, - * to mark implemented or overridden methods. + * to mark implemented or overridden methods.

* * Daemon code analyzer checks newly arrived gutter icon renderer against the old one and if they are equal, does not redraw the icon. - * So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new. + * So it is highly advisable to override hashCode()/equals() methods to avoid icon flickering when old gutter renderer gets replaced with the new.

+ * + * During indexing, click handlers are only invoked for renderers implementing {@link com.intellij.openapi.project.DumbAware}. + * * @author max * @see RangeHighlighter#setGutterIconRenderer(GutterIconRenderer) */ diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 98051d1ef8b2..8cb96e2e8af3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -45,7 +45,7 @@ import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.IndexNotReadyException; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; @@ -1379,31 +1379,32 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } GutterIconRenderer renderer = getGutterRenderer(e); + final Project project = myEditor.getProject(); + if (project != null && DumbService.isDumb(project) && !DumbService.isDumbAware(renderer)) { + DumbService.getInstance(project).showDumbModeNotification("Navigation is not available during indexing"); + return; + } + AnAction clickAction = null; if (renderer != null && e.getButton() < 4) { clickAction = (InputEvent.BUTTON2_MASK & e.getModifiers()) > 0 ? renderer.getMiddleButtonClickAction() : renderer.getClickAction(); } - try { - if (clickAction != null) { - clickAction.actionPerformed(new AnActionEvent(e, myEditor.getDataContext(), "ICON_NAVIGATION", clickAction.getTemplatePresentation(), - ActionManager.getInstance(), - e.getModifiers())); - e.consume(); - repaint(); - } - else { - ActiveGutterRenderer lineRenderer = getActiveRendererByMouseEvent(e); - if (lineRenderer != null) { - lineRenderer.doAction(myEditor, e); - } else { - fireEventToTextAnnotationListeners(e); - } - } + if (clickAction != null) { + clickAction.actionPerformed(new AnActionEvent(e, myEditor.getDataContext(), "ICON_NAVIGATION", clickAction.getTemplatePresentation(), + ActionManager.getInstance(), + e.getModifiers())); + e.consume(); + repaint(); } - catch (IndexNotReadyException e1) { - DumbService.getInstance(myEditor.getProject()).showDumbModeNotification("Navigation is not available during indexing"); + else { + ActiveGutterRenderer lineRenderer = getActiveRendererByMouseEvent(e); + if (lineRenderer != null) { + lineRenderer.doAction(myEditor, e); + } else { + fireEventToTextAnnotationListeners(e); + } } } From 40183cb6d523bf0ce87db78d2ab760a2a0bde5e9 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 15:17:23 +0200 Subject: [PATCH 18/68] wait for smart mode in JavaDirectInheritorsSearcher (EA-70282 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../search/JavaDirectInheritorsSearcher.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java index acbf02209732..b24fcfc87c21 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java @@ -101,12 +101,14 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor candidates = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Collection compute() { - return JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope); - } - }); + Collection candidates = MethodUsagesSearcher.resolveInReadAction(project, + new Computable>() { + @Override + public Collection compute() { + return JavaSuperClassNameOccurenceIndex + .getInstance().get(searchKey, project, scope); + } + }); Map> classes = new HashMap>(); @@ -118,7 +120,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() { @Override @@ -142,16 +144,19 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor anonymousCandidates = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Collection compute() { - return JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, project, scope); - } - }); + Collection anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project, + new Computable>() { + @Override + public Collection compute() { + return JavaAnonymousClassBaseRefOccurenceIndex + .getInstance() + .get(searchKey, project, scope); + } + }); for (PsiAnonymousClass candidate : anonymousCandidates) { ProgressIndicatorProvider.checkCanceled(); - if (!checkInheritance(p, aClass, candidate)) continue; + if (!checkInheritance(p, aClass, candidate, project)) continue; if (!consumer.process(candidate)) return false; } @@ -190,8 +195,8 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() { + private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate, Project project) { + return MethodUsagesSearcher.resolveInReadAction(project, new Computable() { @Override public Boolean compute() { return !p.isCheckInheritance() || candidate.isInheritor(aClass, false); From ec39d130a41e4222d262ecbd9ff1b6bb9b2e834b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 15:19:34 +0200 Subject: [PATCH 19/68] disable usage view action button in dumb mode (EA-70280 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../usageView/src/com/intellij/usages/impl/UsageViewImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 82e9bf9e1bcc..7b4ac5dbee00 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -31,6 +31,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.util.ProgressWrapper; import com.intellij.openapi.progress.util.TooManyUsagesStatus; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -1612,7 +1613,8 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra final JButton button = new JButton(UIUtil.replaceMnemonicAmpersand(text)); DialogUtil.registerMnemonic(button); - + DumbService.getInstance(myProject).makeDumbAware(button, UsageViewImpl.this); + button.setFocusable(false); button.addActionListener(new ActionListener() { @Override From c4a7f15102dd01e9167fee7e860094be03336e3d Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 15:51:31 +0200 Subject: [PATCH 20/68] usage view: dumber settings action name in dumb mode (EA-70208 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../src/com/intellij/usages/impl/UsageViewImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 7b4ac5dbee00..a6da1b610072 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -655,7 +655,15 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra @NotNull private AnAction showSettings() { final ConfigurableUsageTarget configurableUsageTarget = getConfigurableTarget(myTargets); - String description = configurableUsageTarget == null ? "Show find usages settings dialog" : "Show settings for "+configurableUsageTarget.getLongDescriptiveName(); + String description = null; + try { + description = configurableUsageTarget == null ? null : "Show settings for "+configurableUsageTarget.getLongDescriptiveName(); + } + catch (IndexNotReadyException ignored) { + } + if (description == null) { + description = "Show find usages settings dialog"; + } return new AnAction("Settings...", description, AllIcons.General.ProjectSettings) { { KeyboardShortcut shortcut = configurableUsageTarget == null ? getShowUsagesWithSettingsShortcut() : configurableUsageTarget.getShortcut(); From b41d037b09ea149c64d09d7747a5551afe80c00a Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 15:56:45 +0200 Subject: [PATCH 21/68] no recent usages in dumb mode (EA-70195 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java index ccbb9962831c..c030e9281fab 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java +++ b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java @@ -19,6 +19,7 @@ package com.intellij.find.impl; import com.intellij.find.FindManager; import com.intellij.find.findUsages.FindUsagesManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.usages.ConfigurableUsageTarget; import com.intellij.usages.impl.UsageViewImpl; @@ -45,7 +46,7 @@ public class ShowRecentFindUsagesGroup extends ActionGroup { public AnAction[] getChildren(@Nullable final AnActionEvent e) { if (e == null) return EMPTY_ARRAY; Project project = e.getData(CommonDataKeys.PROJECT); - if (project == null) return EMPTY_ARRAY; + if (project == null || DumbService.isDumb(project)) return EMPTY_ARRAY; final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); List history = new ArrayList(findUsagesManager.getHistory().getAll()); Collections.reverse(history); From 2911bd5d1e18545fa7d37538e2fc97769525cb1c Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 16:03:59 +0200 Subject: [PATCH 22/68] make GenerateToStringAction non-dumb-aware (EA-70179 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../java/generate/GenerateToStringAction.java | 12 +++------ .../GenerateToStringActionHandlerImpl.java | 25 ++++++++----------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringAction.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringAction.java index c46b70b1d4cc..987a854dee42 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringAction.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringAction.java @@ -15,20 +15,16 @@ */ package org.jetbrains.java.generate; -import com.intellij.openapi.editor.actionSystem.EditorAction; +import com.intellij.codeInsight.generation.actions.BaseGenerateAction; /** - * The IDEA action for this plugin. - *

* This action handles the generation of a toString() method that dumps the fields * of the class. */ -public class GenerateToStringAction extends EditorAction { +public class GenerateToStringAction extends BaseGenerateAction { - /** - * Constructor. - */ public GenerateToStringAction() { - super(new GenerateToStringActionHandlerImpl()); // register our action handler + super(new GenerateToStringActionHandlerImpl()); } + } \ No newline at end of file diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringActionHandlerImpl.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringActionHandlerImpl.java index 38631f596d73..e574c9278598 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringActionHandlerImpl.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/GenerateToStringActionHandlerImpl.java @@ -15,16 +15,14 @@ */ package org.jetbrains.java.generate; +import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.generation.PsiElementClassMember; import com.intellij.codeInsight.hint.HintManager; import com.intellij.ide.util.MemberChooser; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.ShowSettingsUtil; @@ -56,14 +54,17 @@ import java.util.List; /** * The action-handler that does the code generation. */ -public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler implements GenerateToStringActionHandler { +public class GenerateToStringActionHandlerImpl implements GenerateToStringActionHandler, CodeInsightActionHandler { private static final Logger logger = Logger.getInstance("#GenerateToStringActionHandlerImpl"); - public void executeWriteAction(Editor editor, DataContext dataContext) { - final Project project = CommonDataKeys.PROJECT.getData(dataContext); - assert project != null; + @Override + public boolean startInWriteAction() { + return true; + } - PsiClass clazz = getSubjectClass(editor, dataContext); + @Override + public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { + PsiClass clazz = getSubjectClass(editor, file); assert clazz != null; doExecuteAction(project, clazz, editor); @@ -145,14 +146,8 @@ public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler return GenerationUtil.combineToClassMemberList(filteredFields, filteredMethods); } - @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return getSubjectClass(editor, dataContext) != null; - } - @Nullable - private static PsiClass getSubjectClass(Editor editor, DataContext dataContext) { - PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext); + private static PsiClass getSubjectClass(Editor editor, final PsiFile file) { if (file == null) return null; int offset = editor.getCaretModel().getOffset(); From 9099828c7045b1bde169d6cb2c1461cd6cd903ab Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 16:21:38 +0200 Subject: [PATCH 23/68] maven: invoke importers in smart mode (EA-63588 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../maven/importing/MavenModuleImporter.java | 47 +++++++++++-------- .../jetbrains/idea/maven/utils/MavenUtil.java | 23 +++++++++ 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index a10ef9750eea..cb7396dfb85b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -18,6 +18,8 @@ package org.jetbrains.idea.maven.importing; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; @@ -121,33 +123,38 @@ public class MavenModuleImporter { } public void configFacets(final List postTasks) { - MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { + MavenUtil.smartInvokeAndWait(myModule.getProject(), ModalityState.defaultModalityState(), new Runnable() { public void run() { if (myModule.isDisposed()) return; final ModuleType moduleType = ModuleType.get(myModule); - for (final MavenImporter importer : getSuitableImporters()) { - final MavenProjectChanges changes; - if (myMavenProjectChanges == null) { - if (importer.processChangedModulesOnly()) continue; - changes = MavenProjectChanges.NONE; - } - else { - changes = myMavenProjectChanges; - } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } - if (importer.getModuleType() == moduleType) { - importer.process(myModifiableModelsProvider, - myModule, - myRootModelAdapter, - myMavenTree, - myMavenProject, - changes, - myMavenProjectToModuleName, - postTasks); + if (importer.getModuleType() == moduleType) { + importer.process(myModifiableModelsProvider, + myModule, + myRootModelAdapter, + myMavenTree, + myMavenProject, + changes, + myMavenProjectToModuleName, + postTasks); + } + } } - } + }); } }); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index 47b0e2ec36c4..d92fc84b6731 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -59,6 +59,7 @@ import com.intellij.psi.PsiManager; import com.intellij.util.DisposeAwareRunnable; import com.intellij.util.Function; import com.intellij.util.SystemProperties; +import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import icons.MavenIcons; @@ -162,6 +163,28 @@ public class MavenUtil { } } } + + public static void smartInvokeAndWait(final Project p, final ModalityState state, final Runnable r) { + if (isNoBackgroundMode() || ApplicationManager.getApplication().isDispatchThread()) { + r.run(); + } + else { + final Semaphore semaphore = new Semaphore(); + semaphore.down(); + DumbService.getInstance(p).smartInvokeLater(new Runnable() { + @Override + public void run() { + try { + r.run(); + } + finally { + semaphore.up(); + } + } + }, state); + semaphore.waitFor(); + } + } public static void invokeAndWaitWriteAction(Project p, final Runnable r) { invokeAndWait(p, new Runnable() { From 40b275a4dd9b30f9a604ba118f532c079c7621d6 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 16:24:52 +0200 Subject: [PATCH 24/68] wait until smart mode before processing file roots while searching for usages (EA-65020 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../com/intellij/psi/impl/search/PsiSearchHelperImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 704aae2194bb..0969093acc78 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -312,7 +312,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } // we failed to run read action in job launcher thread // run read action in our thread instead to wait for a write action to complete and resume parallel processing - ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance()); + DumbService.getInstance(myManager.getProject()).runReadActionInSmartMode(EmptyRunnable.getInstance()); files = failedList; } return completed; @@ -347,7 +347,10 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { ApplicationUtil.tryRunReadAction(new Computable() { @Override public Void compute() { - if (myManager.getProject().isDisposed()) throw new ProcessCanceledException(); + final Project project = myManager.getProject(); + if (project.isDisposed()) throw new ProcessCanceledException(); + if (DumbService.isDumb(project)) throw new ApplicationUtil.CannotRunReadActionException(); + List psiRoots = file.getViewProvider().getAllFiles(); Set processed = new THashSet(psiRoots.size() * 2, (float)0.5); for (final PsiFile psiRoot : psiRoots) { From de79143688a8bb5ae2413dab6970aacefc157c8b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 1 Jul 2015 16:28:53 +0200 Subject: [PATCH 25/68] disable PyMethodNameTypedHandler in dumb mode (EA-70199 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../jetbrains/python/codeInsight/PyMethodNameTypedHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java index dd9d3ef9dc00..d2b01b388544 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -40,7 +41,7 @@ import com.jetbrains.python.psi.PyUtil; public class PyMethodNameTypedHandler extends TypedHandlerDelegate { @Override public Result beforeCharTyped(char character, Project project, Editor editor, PsiFile file, FileType fileType) { - if (!(fileType instanceof PythonFileType)) return Result.CONTINUE; // else we'd mess up with other file types! + if (DumbService.isDumb(project) || !(fileType instanceof PythonFileType)) return Result.CONTINUE; // else we'd mess up with other file types! if (character == '(') { if (!PyCodeInsightSettings.getInstance().INSERT_SELF_FOR_METHODS) { return Result.CONTINUE; From 324e0d924b896924532339b9fb7f0d45075cc3fd Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 30 Jun 2015 17:48:00 +0300 Subject: [PATCH 26/68] IDEA-79921 Suspend one thread while debugging --- .../src/com/intellij/debugger/actions/ResumeThreadAction.java | 1 - .../src/com/intellij/debugger/engine/DebugProcessImpl.java | 1 + .../impl/src/com/intellij/debugger/impl/DebuggerSession.java | 4 +++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java index 709383481549..4c9e57aa13c7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java @@ -45,7 +45,6 @@ public class ResumeThreadAction extends DebuggerAction{ final ThreadReferenceProxyImpl thread = threadDescriptor.getThreadReference(); debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) { public void contextAction() throws Exception { - debugProcess.getSession().getXDebugSession().sessionResumed(); debugProcess.createResumeThreadCommand(getSuspendContext(), thread).run(); debuggerTreeNode.calcValue(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 43149c603d8f..fa3cfe540b65 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1694,6 +1694,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb final Set suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread); for (SuspendContextImpl suspendContext : suspendingContexts) { if (suspendContext.getThread() == myThread) { + getSession().getXDebugSession().sessionResumed(); getManagerThread().invoke(createResumeCommand(suspendContext)); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index 04bf6d8aa302..42d19808729e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -589,7 +589,9 @@ public class DebuggerSession implements AbstractDebuggerSession { @Override public void resumed(final SuspendContextImpl suspendContext) { - final SuspendContextImpl currentContext = isSteppingThrough(suspendContext.getThread()) ? null : getProcess().getSuspendManager().getPausedContext(); + final SuspendContextImpl currentContext = suspendContext != null && isSteppingThrough(suspendContext.getThread()) + ? null + : getProcess().getSuspendManager().getPausedContext(); DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() { @Override public void run() { From 45715dab3cbf198f82c897946d9bf5ac77fa242f Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 1 Jul 2015 17:49:43 +0300 Subject: [PATCH 27/68] fixed breakpoints in anonymous classes in decompiled code --- .../debugger/engine/PositionManagerImpl.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 77b1c44f093d..6ec3eefddb17 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -28,16 +28,14 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.NullableComputable; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.DocumentUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.EmptyIterable; @@ -285,13 +283,12 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio if (document == null || lineNumber >= document.getLineCount()) { return EmptyIterable.getInstance(); } - final int startOffset = document.getLineStartOffset(lineNumber); - final int endOffset = document.getLineEndOffset(lineNumber); + final TextRange lineRange = DocumentUtil.getLineTextRange(document, lineNumber); return new Iterable() { @Override public Iterator iterator() { return new Iterator() { - PsiElement myElement = file.findElementAt(startOffset); + PsiElement myElement = DebuggerUtilsEx.findElementAt(file, lineRange.getStartOffset()); @Override public boolean hasNext() { @@ -303,7 +300,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio PsiElement res = myElement; do { myElement = PsiTreeUtil.nextLeaf(myElement); - if (myElement == null || myElement.getTextOffset() > endOffset) { + if (myElement == null || myElement.getTextOffset() > lineRange.getEndOffset()) { myElement = null; break; } From 4885c0aebbece72e1ca4d6e3c753eb08af4518c7 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 1 Jul 2015 18:02:15 +0300 Subject: [PATCH 28/68] IDEA-140989 Cannot select item from completion popup using mouse --- .../src/com/intellij/ui/BalloonImpl.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 8c593a69d52c..d60649e096a0 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -106,7 +106,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { final boolean insideBalloon = isInsideBalloon(me); if (myHideOnMouse && id == MouseEvent.MOUSE_PRESSED) { - if (!insideBalloon && !hasModalDialog(me)) { + if (!insideBalloon && !hasModalDialog(me) && !isWithinChildWindow(me)) { hide(); } return; @@ -159,6 +159,21 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { } }; + private boolean isWithinChildWindow(MouseEvent event) { + Component owner = UIUtil.getWindow(myContent); + if (owner != null) { + Component child = UIUtil.getWindow(event.getComponent()); + if (child != owner) { + for (; child != null; child = child.getParent()) { + if (child == owner) { + return true; + } + } + } + } + return false; + } + private static boolean hasModalDialog(MouseEvent e) { final Component c = e.getComponent(); final DialogWrapper dialog = DialogWrapper.findInstance(c); From fdc45ffe96a6112dde9dedb60f9e4753fc2d8401 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 1 Jul 2015 18:27:22 +0300 Subject: [PATCH 29/68] vcs: fix double click listener in ChangesBrowser * check for checkbox area only if checkboxes are shown --- .../vcs/changes/ui/ChangesTreeList.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index a94a1af63689..05fab9131753 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -203,13 +203,15 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP public boolean onClick(@NotNull MouseEvent e, int clickCount) { final int idx = myList.locationToIndex(e.getPoint()); if (idx >= 0) { - final Rectangle baseRect = myList.getCellBounds(idx, idx); - baseRect.setSize(checkboxWidth, baseRect.height); - if (baseRect.contains(e.getPoint())) { - toggleSelection(); - return true; + if (myShowCheckboxes) { + final Rectangle baseRect = myList.getCellBounds(idx, idx); + baseRect.setSize(checkboxWidth, baseRect.height); + if (baseRect.contains(e.getPoint())) { + toggleSelection(); + return true; + } } - else if (clickCount == 2) { + if (clickCount == 2) { myDoubleClickHandler.run(); return true; } @@ -228,9 +230,11 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP final int row = myTree.getRowForLocation(e.getPoint().x, e.getPoint().y); if (row >= 0) { - final Rectangle baseRect = myTree.getRowBounds(row); - baseRect.setSize(checkboxWidth, baseRect.height); - if (baseRect.contains(e.getPoint())) return false; + if (myShowCheckboxes) { + final Rectangle baseRect = myTree.getRowBounds(row); + baseRect.setSize(checkboxWidth, baseRect.height); + if (baseRect.contains(e.getPoint())) return false; + } } myDoubleClickHandler.run(); From ecb0d36fde261037619f031a03237b1f37ec767f Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 1 Jul 2015 19:00:25 +0300 Subject: [PATCH 30/68] cleanup --- .../com/intellij/execution/impl/RunConfigurableTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java index 629f102de77d..847dc0f64d64 100644 --- a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java +++ b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.java @@ -131,7 +131,7 @@ public class RunConfigurableTest extends LightIdeaTestCase { private void doExpand() { List toExpand = new ArrayList(); RunConfigurable.collectNodesRecursively(myRoot, toExpand, FOLDER); - assertEquals(toExpand.size(), 5); + assertEquals(5, toExpand.size()); List toExpand2 = new ArrayList(); RunConfigurable.collectNodesRecursively(myRoot, toExpand2, CONFIGURATION_TYPE); toExpand.addAll(toExpand2); From c226409f8afbb1008a3270d1931491a74f2e1121 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 1 Jul 2015 18:45:37 +0300 Subject: [PATCH 31/68] IDEA-142086 diff: mark files dirty if launched from command line they can be not under FileWatcher, so refresh() will do nothing even if they were changed --- .../com/intellij/diff/applications/DiffApplication.java | 4 ++-- .../src/com/intellij/ide/diff/VirtualFileDiffElement.java | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 0bbc064b3cab..9e2f84f0b1ca 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.diff.DiffBundle; import com.intellij.openapi.project.DefaultProjectFactory; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,8 +58,7 @@ public class DiffApplication extends ApplicationStarterBase { if (file1 == null) throw new Exception("Can't find file " + path1); if (file2 == null) throw new Exception("Can't find file " + path2); - file1.refresh(false, true); - file2.refresh(false, true); + VfsUtil.markDirtyAndRefresh(false, false, false, file1, file2); DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2); Project project = DefaultProjectFactory.getInstance().getDefaultProject(); diff --git a/platform/platform-impl/src/com/intellij/ide/diff/VirtualFileDiffElement.java b/platform/platform-impl/src/com/intellij/ide/diff/VirtualFileDiffElement.java index b697be14276f..13826a6ae112 100644 --- a/platform/platform-impl/src/com/intellij/ide/diff/VirtualFileDiffElement.java +++ b/platform/platform-impl/src/com/intellij/ide/diff/VirtualFileDiffElement.java @@ -32,10 +32,7 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VFileProperty; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.*; import com.intellij.util.PlatformIcons; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -301,7 +298,7 @@ public class VirtualFileDiffElement extends DiffElement { }.execute(); } - virtualFile.refresh(true, true); + VfsUtil.markDirtyAndRefresh(true, true, true, virtualFile); } } } From 2bc3208360575ac5a5232bec8c10db504668aeb2 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 1 Jul 2015 18:13:33 +0200 Subject: [PATCH 32/68] ThreeStateCheckBox eats CPU. A lot. --- .../intellij/util/ui/ThreeStateCheckBox.java | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java b/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java index 8f9bbc29bb9d..8f7bd5bbf3b1 100644 --- a/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java +++ b/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java @@ -63,7 +63,7 @@ public class ThreeStateCheckBox extends JCheckBox { @Override public boolean isSelected() { - return myState == State.SELECTED; + return myState == State.SELECTED || (UIUtil.isUnderAquaLookAndFeel() && myState == State.DONT_CARE); } }); @@ -101,6 +101,10 @@ public class ThreeStateCheckBox extends JCheckBox { public void setState(State state) { myState = state; + + String value = state == State.DONT_CARE ? "indeterminate" : null; + putClientProperty("JButton.selectedState", value); + repaint(); } @@ -111,12 +115,11 @@ public class ThreeStateCheckBox extends JCheckBox { @Override protected void paintComponent(Graphics g) { + super.paintComponent(g); if (UIUtil.isUnderAquaLookAndFeel()) { - paintIndeterminateIcon(g); return; } - super.paintComponent(g); switch (getState()) { case DONT_CARE: Icon icon = getIcon(); @@ -155,19 +158,4 @@ public class ThreeStateCheckBox extends JCheckBox { break; } } - - protected void paintIndeterminateIcon(Graphics g) { - State initial = getState(); - try { - if (getState() == State.DONT_CARE) { - setSelected(true); - putClientProperty("JButton.selectedState", "indeterminate"); - } else { - putClientProperty("JButton.selectedState", null); - } - super.paintComponent(g); - } finally { - setState(initial); - } - } } From 5fb0836db1d1214ea88752fe1969c53d5a991112 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 1 Jul 2015 19:58:02 +0300 Subject: [PATCH 33/68] fixed exec permission for binaries into unix jre bundled. --- python/edu/build/pycharm_edu_build.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index e1ed6b8f8aaf..b5ae93ba586a 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -204,7 +204,7 @@ public layoutEducational(String classesPath, Set usedJars) { String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}" buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix]) if (p("jdk.bundled.linux") != "false") { - buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/bin/*"]) + buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/jre/bin/*"]) } From 96628e419e5bd4fdc4f8e5f920c2c20277aebba0 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 1 Jul 2015 20:45:27 +0300 Subject: [PATCH 34/68] EA-69844 - OCE: DebugProcessImpl.deleteStepRequests --- .../impl/src/com/intellij/debugger/engine/DebugProcessImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index fa3cfe540b65..9da93a15cda6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -456,6 +456,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb catch (IllegalThreadStateException e) { LOG.info(e); // undocumented by JDI: may be thrown when querying thread status } + catch (ObjectCollectedException ignored) { + } } requestManager.deleteEventRequests(toDelete); } From 69e60465d56b1dd468deb9c9e89b8c00e9a6e392 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 1 Jul 2015 20:10:53 +0300 Subject: [PATCH 35/68] Extracted several logically independent parts from resolveChild() --- .../python/psi/resolve/ResolveImportUtil.java | 115 +++++++++++------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index b156b608c6bb..5475aa969896 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -269,56 +269,83 @@ public class ResolveImportUtil { @Nullable public static PsiElement resolveChild(@Nullable final PsiElement parent, @NotNull final String referencedName, @Nullable final PsiFile containingFile, boolean fileOnly, boolean checkForPackage) { - PsiDirectory dir = null; - PsiElement resultElement = null; - final PyResolveContext resolveContext = PyResolveContext.defaultContext(); - if (parent instanceof PyFileImpl) { - PsiElement possibleResult = null; - if (PyNames.INIT_DOT_PY.equals(((PyFile)parent).getName())) { - dir = ((PyFile)parent).getContainingDirectory(); - possibleResult = resolveInDirectory(referencedName, containingFile, dir, fileOnly, checkForPackage); - } - - final PyModuleType moduleType = new PyModuleType((PyFile)parent); - final List results = moduleType.resolveMember(referencedName, null, AccessDirection.READ, - resolveContext); - final PsiElement moduleMember = results != null && !results.isEmpty() ? results.get(0).getElement() : null; - if (!fileOnly || PyUtil.instanceOf(moduleMember, PsiFile.class, PsiDirectory.class)) { - resultElement = moduleMember; - } - if (resultElement != null && !PyUtil.instanceOf(resultElement, PsiFile.class, PsiDirectory.class) && - PsiTreeUtil.getStubOrPsiParentOfType(resultElement, PyExceptPart.class) == null && !isDunderAll(resultElement)) { - return resultElement; - } - - if (possibleResult != null) return possibleResult; - - if (resultElement != null) { - return resultElement; - } + if (parent == null) { + return null; + } + else if (parent instanceof PyFile) { + return resolveInPackageModule((PyFile)parent, referencedName, containingFile, fileOnly, checkForPackage); } else if (parent instanceof PsiDirectory) { - dir = (PsiDirectory)parent; + return resolveInPackageDirectory(parent, referencedName, containingFile, fileOnly, checkForPackage); } - else if (parent != null) { - PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, resolveContext.getTypeEvalContext(), null); - if (refType != null) { - final List result = refType.resolveMember(referencedName, null, AccessDirection.READ, resolveContext); - if (result != null && !result.isEmpty()) { - return result.get(0).getElement(); - } - } + else { + return resolveMemberFromReferenceTypeProviders(parent, referencedName); } - if (dir != null) { - final PsiElement result = resolveInDirectory(referencedName, containingFile, dir, fileOnly, checkForPackage); - if (result != null) { - return result; + } + + @Nullable + private static PsiElement resolveInPackageModule(@NotNull PyFile parent, @NotNull String referencedName, + @Nullable PsiFile containingFile, boolean fileOnly, boolean checkForPackage) { + final PsiElement moduleMember = resolveModuleMember(parent, referencedName); + final PsiElement resolved = !fileOnly || PyUtil.instanceOf(moduleMember, PsiFile.class, PsiDirectory.class) ? + moduleMember : null; + if (resolved != null && !preferResolveInDirectoryOverModule(resolved)) { + return resolved; + } + + final PsiElement resolvedInDirectory = resolveInPackageDirectory(parent, referencedName, containingFile, fileOnly, checkForPackage); + if (resolvedInDirectory != null) { + return resolvedInDirectory; + } + + return resolved; + } + + private static boolean preferResolveInDirectoryOverModule(@NotNull PsiElement resolved) { + return PsiTreeUtil.getStubOrPsiParentOfType(resolved, PyExceptPart.class) != null || + PyUtil.instanceOf(resolved, PsiFile.class, PsiDirectory.class) || // XXX: Workaround for PY-9439 + isDunderAll(resolved); + } + + @Nullable + private static PsiElement resolveModuleMember(@NotNull PyFile file, @NotNull String referencedName) { + final PyModuleType moduleType = new PyModuleType(file); + final PyResolveContext resolveContext = PyResolveContext.defaultContext(); + final List results = moduleType.resolveMember(referencedName, null, AccessDirection.READ, + resolveContext); + return results != null && !results.isEmpty() ? results.get(0).getElement() : null; + } + + @Nullable + private static PsiElement resolveInPackageDirectory(@Nullable PsiElement parent, @NotNull String referencedName, + @Nullable PsiFile containingFile, boolean fileOnly, + boolean checkForPackage) { + final PsiElement parentDir = PyUtil.turnInitIntoDir(parent); + if (parentDir instanceof PsiDirectory) { + final PsiElement resolved = resolveInDirectory(referencedName, containingFile, (PsiDirectory)parentDir, fileOnly, checkForPackage); + if (resolved != null) { + return resolved; } if (parent instanceof PsiFile) { - final PsiElement element = new QualifiedNameResolverImpl(referencedName).fromElement(parent).withoutRoots().firstResult(); - if (element != null) { - return element; - } + return resolveForeignImports((PsiFile)parent, referencedName); + } + } + return null; + } + + @Nullable + private static PsiElement resolveForeignImports(@NotNull PsiFile foothold, @NotNull String referencedName) { + return new QualifiedNameResolverImpl(referencedName).fromElement(foothold).withoutRoots().firstResult(); + } + + @Nullable + private static PsiElement resolveMemberFromReferenceTypeProviders(@NotNull PsiElement parent, @NotNull String referencedName) { + final PyResolveContext resolveContext = PyResolveContext.defaultContext(); + PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, resolveContext.getTypeEvalContext(), null); + if (refType != null) { + final List result = refType.resolveMember(referencedName, null, AccessDirection.READ, resolveContext); + if (result != null && !result.isEmpty()) { + return result.get(0).getElement(); } } return null; From b063f4d30fe65c30090bd97384fbfa6c2a5c9586 Mon Sep 17 00:00:00 2001 From: Andrey Sokolov Date: Wed, 1 Jul 2015 20:52:21 +0300 Subject: [PATCH 36/68] StringBasedPostfixTemplate api - added new method getElementToRemove --- .../postfix/templates/StringBasedPostfixTemplate.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java index 85e71d73b247..0f7b93ef98ea 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java @@ -37,7 +37,7 @@ public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpr public final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull Editor editor) { Project project = expr.getProject(); Document document = editor.getDocument(); - PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr; + PsiElement elementForRemoving = getElementToRemove(expr); document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset()); TemplateManager manager = TemplateManager.getInstance(project); @@ -78,7 +78,16 @@ public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpr return true; } + /** @deprecated use {@link StringBasedPostfixTemplate#getElementToRemove(PsiElement)} (idea 16 to remove) */ protected boolean shouldRemoveParent() { return true; } + + protected PsiElement getElementToRemove(PsiElement expr) { + if (shouldRemoveParent()) { + return expr.getParent(); + } else { + return expr; + } + } } From 2a063c19d422b99424a652e78f08d8f8b01c7a51 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 1 Jul 2015 21:03:30 +0300 Subject: [PATCH 37/68] Cleanup (formatting) --- .../parser/partial/DeclarationParserTest.java | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java index 960417707dda..4f0ecb3d6e7a 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java @@ -34,19 +34,12 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testPines() { doParserTest("{ class A> extends List> { } }"); } public void testIncompleteAnnotation() { doParserTest("{ public class Foo { public void testSomething(); @Null } }"); } public void testClassInit() { doParserTest("{ { /*comment*/ } }"); } - public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); } - public void testEnumSmartTypeCompletion() { doParserTest("{ @Preliminary(A.B\n#) public class TimeTravel {}\n" + - " @Preliminary(a=A.B\n#) public class TimeTravel {}\n" + - " @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }"); } - public void testTypeAnno() { - doParserTest("{ class C<@D T extends @F Object> extends @F Object {\n" + - " @F int @F[] method() throws @F Exception {\n" + - " a = this instanceof @F C;\n" + - " C<@F @G C> c = new @Q C<@F C>();\n" + - " c = (@F Object)c;\n" + - " Class c = @TA String.class;\n" + - " @F C.field++;\n" + - " }\n} }"); + + public void testEnumSmartTypeCompletion() { + doParserTest( + "{ @Preliminary(A.B\n#) public class TimeTravel {}\n" + + " @Preliminary(a=A.B\n#) public class TimeTravel {}\n" + + " @Preliminary(a=A.B\n#, b=c) public class TimeTravel {} }"); } public void testEnumBody0() { doParserTest("{ ; }", false, true); } @@ -59,6 +52,7 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testEnumWithInitializedConstants() { doParserTest("{ A(10) { },\n B { void method() {} } }", false, true); } public void testEnumWithoutConstants() { doParserTest("{ private A }", false, true); } + public void testAnnoDeclaration() { doParserTest("{ public @interface Annotation {} }"); } public void testAnnoSimple() { doParserTest("{ int foo (); }", true, false); } public void testAnnoDefault() { doParserTest("{ Class foo() default String.class; }", true, false); } public void testAnnoNested() { doParserTest("{ @interface Inner { String bar () default \"\"; } }", true, false); } @@ -66,6 +60,18 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testAnnoOtherMembers() { doParserTest("{ int field;\n void m() {}\n class C {}\n interface I {} }", true, false); } public void testAnnoLoop() { doParserTest("{ @@@ int i; }"); } + public void testTypeAnno() { + doParserTest( + "{ class C<@D T extends @F Object> extends @F Object {\n" + + " @F int @F[] method() throws @F Exception {\n" + + " a = this instanceof @F C;\n" + + " C<@F @G C> c = new @Q C<@F C>();\n" + + " c = (@F Object)c;\n" + + " Class c = @TA String.class;\n" + + " @F C.field++;\n" + + " }\n} }"); + } + public void testFieldSimple() { doParserTest("{ int field = 0; }"); } public void testFieldMulti() { doParserTest("{ int field1 = 0, field2; }"); } public void testUnclosedBracket() { doParserTest("{ int field[ }"); } @@ -94,9 +100,13 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testConstructorBrackets() { doParserTest("{ A() [] { } }"); } public void testVarArgBrackets() { doParserTest("{ void foo(int... x[]); }"); } - public void testGenericMethod() { doParserTest("{ public static test();\n" + - " void test1();\n" + - " String test2(); }"); } + public void testGenericMethod() { + doParserTest( + "{ public static test();\n" + + " void test1();\n" + + " String test2(); }"); + } + public void testGenericMethodErrors() { doParserTest("{ test (); }"); } public void testErrors() { doParserTest("{ public static protected int f1 = 0; }"); } public void testCompletionHack0() { doParserTest("{ \n String s = \"\"; }"); } From afbe2e071748bd94d55429c6a7bd47d4499f184f Mon Sep 17 00:00:00 2001 From: Andrey Sokolov Date: Wed, 1 Jul 2015 21:27:21 +0300 Subject: [PATCH 38/68] FormatPostfixTemplate replace deprecated usage of method shouldRemoveParent with usage of getElementToRemove --- .../template/postfix/templates/FormatPostfixTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java index 5b88af016709..9d90c20d2e5b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/FormatPostfixTemplate.java @@ -50,7 +50,7 @@ public class FormatPostfixTemplate extends StringBasedPostfixTemplate { } @Override - protected boolean shouldRemoveParent() { - return false; + protected PsiElement getElementToRemove(PsiElement expr) { + return expr; } } From 1d09eff133e9e347580a235392514c54250ddf5b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 1 Jul 2015 18:51:28 +0300 Subject: [PATCH 39/68] mark tests progress grey if terminated and was green (IDEA-142074) --- .../testframework/sm/runner/ui/SMTestRunnerResultsForm.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java index 24ba21837c54..99f70a67f5c6 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java @@ -319,6 +319,10 @@ public class SMTestRunnerResultsForm extends TestResultsPanel } fireOnTestingFinished(); + + if (testsRoot.wasTerminated() && myStatusLine.getStatusColor() == ColorProgressBar.GREEN) { + myStatusLine.setStatusColor(JBColor.LIGHT_GRAY); + } if (testsRoot.isEmptySuite() && testsRoot.isTestsReporterAttached() && From 01d259f8cccff87078679ca4bcf34631a6a4490d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 1 Jul 2015 19:21:40 +0300 Subject: [PATCH 40/68] import tests: ensure additional actions are included into imported view; runner is chosen according to initial configuration (IDEA-142115) --- .../history/ImportedTestConsoleProperties.java | 10 ++++++++++ .../actions/AbstractImportTestsAction.java | 15 ++++++++++++++- .../testframework/TestConsoleProperties.java | 2 +- .../ui/properties/JUnitConsoleProperties.java | 4 ++-- .../testng/model/TestNGConsoleProperties.java | 2 +- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java index 0b529b46083d..4241ba73fa57 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java @@ -28,11 +28,14 @@ import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties import com.intellij.execution.testframework.sm.runner.SMTestLocator; import com.intellij.execution.testframework.sm.runner.TestProxyFilterProvider; import com.intellij.execution.ui.ConsoleView; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.Project; import com.intellij.pom.Navigatable; +import com.intellij.util.config.ToggleBooleanProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; public class ImportedTestConsoleProperties extends SMTRunnerConsoleProperties implements SMCustomMessagesParsing { @@ -111,4 +114,11 @@ public class ImportedTestConsoleProperties extends SMTRunnerConsoleProperties im public AbstractRerunFailedTestsAction createRerunFailedTestsAction(ConsoleView consoleView) { return myProperties == null ? null : myProperties.createRerunFailedTestsAction(consoleView); } + + @Override + public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent) { + if (myProperties != null) { + myProperties.appendAdditionalActions(actionGroup, parent); + } + } } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/actions/AbstractImportTestsAction.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/actions/AbstractImportTestsAction.java index cab2b7f18147..efd1d7342f62 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/actions/AbstractImportTestsAction.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/actions/AbstractImportTestsAction.java @@ -18,6 +18,7 @@ package com.intellij.execution.testframework.sm.runner.history.actions; import com.intellij.execution.ExecutionException; import com.intellij.execution.Executor; import com.intellij.execution.ExecutorRegistry; +import com.intellij.execution.RunnerRegistry; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; @@ -26,6 +27,7 @@ import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ProgramRunner; import com.intellij.execution.testframework.export.TestResultsXmlFormatter; import com.intellij.execution.testframework.sm.runner.history.ImportedTestRunnableState; import com.intellij.execution.testframework.sm.runner.SMRunnerConsolePropertiesProvider; @@ -115,7 +117,14 @@ public abstract class AbstractImportTestsAction extends AnAction { } final Executor executor = properties != null ? properties.getExecutor() : ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID); - ExecutionEnvironmentBuilder.create(project, executor, profile).buildAndExecute(); + ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder.create(project, executor, profile); + final RunConfiguration initialConfiguration = profile.getInitialConfiguration(); + final ProgramRunner runner = + initialConfiguration != null ? RunnerRegistry.getInstance().getRunner(executor.getId(), initialConfiguration) : null; + if (runner != null) { + builder = builder.runner(runner); + } + builder.buildAndExecute(); } catch (ExecutionException e1) { Messages.showErrorDialog(project, e1.getMessage(), "Import Failed"); @@ -214,6 +223,10 @@ public abstract class AbstractImportTestsAction extends AnAction { return myProperties; } + public RunConfiguration getInitialConfiguration() { + return mySettings != null ? mySettings.getConfiguration() : null; + } + public Project getProject() { return myProject; } diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java index 7a94049bd415..5c8ab91ca7ca 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java @@ -195,7 +195,7 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp myUsePredefinedMessageFilter = usePredefinedMessageFilter; } - protected void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent) { } + public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent) { } @Nullable protected AnAction createImportAction() { diff --git a/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java b/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java index 24fcb2a87aba..b6ee77a9639d 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java +++ b/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java @@ -58,8 +58,8 @@ public class JUnitConsoleProperties extends JavaAwareTestConsoleProperties Date: Wed, 1 Jul 2015 20:08:36 +0300 Subject: [PATCH 41/68] import/export tests: include successful configs according to setting; allow to change view after import accordingly --- .../ImportedTestConsoleProperties.java | 5 ++-- .../history/ImportedTestContentHandler.java | 7 +++++- .../sm/runner/ui/SMTestRunnerResultsForm.java | 4 +++- .../testframework/TestConsoleProperties.java | 10 ++++---- .../execution/testframework/ToolbarPanel.java | 3 +-- .../export/ExportTestResultsAction.java | 2 +- .../export/TestResultsXmlFormatter.java | 23 ++++++++++++------- .../ui/properties/JUnitConsoleProperties.java | 7 +++--- .../testng/model/TestNGConsoleProperties.java | 9 ++++---- 9 files changed, 42 insertions(+), 28 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java index 4241ba73fa57..faba4f0d2e5a 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestConsoleProperties.java @@ -31,7 +31,6 @@ import com.intellij.execution.ui.ConsoleView; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.Project; import com.intellij.pom.Navigatable; -import com.intellij.util.config.ToggleBooleanProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,9 +115,9 @@ public class ImportedTestConsoleProperties extends SMTRunnerConsoleProperties im } @Override - public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent) { + public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent, TestConsoleProperties target) { if (myProperties != null) { - myProperties.appendAdditionalActions(actionGroup, parent); + myProperties.appendAdditionalActions(actionGroup, parent, this); } } } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestContentHandler.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestContentHandler.java index f00a994ba7cd..b949df18d78c 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestContentHandler.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/history/ImportedTestContentHandler.java @@ -52,7 +52,12 @@ public class ImportedTestContentHandler extends DefaultHandler { myCurrentTest = name; myDuration = attributes.getValue(TestResultsXmlFormatter.ATTR_DURATION); myStatus = attributes.getValue(TestResultsXmlFormatter.ATTR_STATUS); - myProcessor.onTestStarted(new TestStartedEvent(name, attributes.getValue(TestResultsXmlFormatter.ATTR_LOCATION))); + final String isConfig = attributes.getValue(TestResultsXmlFormatter.ATTR_CONFIG); + final TestStartedEvent startedEvent = new TestStartedEvent(name, attributes.getValue(TestResultsXmlFormatter.ATTR_LOCATION)); + if (isConfig != null && Boolean.valueOf(isConfig)) { + startedEvent.setConfig(true); + } + myProcessor.onTestStarted(startedEvent); currentValue.setLength(0); } else if (TestResultsXmlFormatter.ELEM_OUTPUT.equals(qName)) { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java index 99f70a67f5c6..e2ebf8500fd6 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java @@ -777,12 +777,14 @@ public class SMTestRunnerResultsForm extends TestResultsPanel private static class MySaveHistoryTask extends Task.Backgroundable { + private final TestConsoleProperties myConsoleProperties; private SMTestProxy.SMRootTestProxy myRoot; private RunConfiguration myConfiguration; private String myOutput; public MySaveHistoryTask(TestConsoleProperties consoleProperties, SMTestProxy.SMRootTestProxy root, RunConfiguration configuration) { super(consoleProperties.getProject(), "Save Test Results", true); + myConsoleProperties = consoleProperties; myRoot = root; myConfiguration = configuration; } @@ -800,7 +802,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel final SMTestProxy.SMRootTestProxy root = myRoot; final RunConfiguration configuration = myConfiguration; if (root != null && configuration != null) { - TestResultsXmlFormatter.execute(root, configuration, handler); + TestResultsXmlFormatter.execute(root, configuration, myConsoleProperties, handler); } myOutput = w.toString(); } diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java index 5c8ab91ca7ca..b756ba624505 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java @@ -195,7 +195,7 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp myUsePredefinedMessageFilter = usePredefinedMessageFilter; } - public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent) { } + public void appendAdditionalActions(DefaultActionGroup actionGroup, JComponent parent, TestConsoleProperties target) { } @Nullable protected AnAction createImportAction() { @@ -203,16 +203,16 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp } @NotNull - protected ToggleBooleanProperty createIncludeNonStartedInRerun() { + protected ToggleBooleanProperty createIncludeNonStartedInRerun(TestConsoleProperties target) { String text = ExecutionBundle.message("junit.runing.info.include.non.started.in.rerun.failed.action.name"); - return new ToggleBooleanProperty(text, null, null, this, INCLUDE_NON_STARTED_IN_RERUN_FAILED); + return new ToggleBooleanProperty(text, null, null, target, INCLUDE_NON_STARTED_IN_RERUN_FAILED); } @NotNull - protected ToggleBooleanProperty createHideSuccessfulConfig() { + protected ToggleBooleanProperty createHideSuccessfulConfig(TestConsoleProperties target) { String text = ExecutionBundle.message("junit.runing.info.hide.successful.config.action.name"); setIfUndefined(HIDE_SUCCESSFUL_CONFIG, true); - return new ToggleBooleanProperty(text, null, null, this, HIDE_SUCCESSFUL_CONFIG); + return new ToggleBooleanProperty(text, null, null, target, HIDE_SUCCESSFUL_CONFIG); } @JdkConstants.TreeSelectionMode diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java index d0f1dc44d6b4..6955be5cd2ba 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java @@ -23,7 +23,6 @@ package com.intellij.execution.testframework; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.configurations.RunProfile; -import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.testframework.actions.ScrollToTestSourceAction; import com.intellij.execution.testframework.actions.ShowStatisticsAction; import com.intellij.execution.testframework.actions.TestFrameworkActions; @@ -155,7 +154,7 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab secondaryGroup.addSeparator(); secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.select.first.failed.action.name"), null, null, properties, TestConsoleProperties.SELECT_FIRST_DEFECT)); - properties.appendAdditionalActions(secondaryGroup, parent); + properties.appendAdditionalActions(secondaryGroup, parent, properties); actionGroup.add(secondaryGroup); add(ActionManager.getInstance(). diff --git a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java index 644ddfa40a67..331ee9e8791b 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java @@ -307,7 +307,7 @@ public class ExportTestResultsAction extends DumbAwareAction { StringWriter w = new StringWriter(); handler.setResult(new StreamResult(w)); try { - TestResultsXmlFormatter.execute(myModel.getRoot(), myRunConfiguration, handler); + TestResultsXmlFormatter.execute(myModel.getRoot(), myRunConfiguration, myModel.getProperties(), handler); } catch (ProcessCanceledException e) { return null; diff --git a/platform/testRunner/src/com/intellij/execution/testframework/export/TestResultsXmlFormatter.java b/platform/testRunner/src/com/intellij/execution/testframework/export/TestResultsXmlFormatter.java index c12d8fc15dfb..ed93d178dc2a 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/export/TestResultsXmlFormatter.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/export/TestResultsXmlFormatter.java @@ -18,12 +18,10 @@ package com.intellij.execution.testframework.export; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.filters.*; +import com.intellij.execution.filters.Filter; import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl; -import com.intellij.execution.testframework.AbstractTestProxy; -import com.intellij.execution.testframework.Printable; -import com.intellij.execution.testframework.Printer; -import com.intellij.execution.testframework.TestProxyRoot; +import com.intellij.execution.testframework.*; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.extensions.Extensions; @@ -59,6 +57,7 @@ public class TestResultsXmlFormatter { public static final String ATTR_STATUS = "status"; public static final String TOTAL_STATUS = "total"; private static final String ATTR_FOORTER_TEXT = "footerText"; + public static final String ATTR_CONFIG = "isConfig"; public static final String STATUS_PASSED = "passed"; public static final String STATUS_FAILED = "failed"; public static final String STATUS_ERROR = "error"; @@ -72,16 +71,21 @@ public class TestResultsXmlFormatter { private final RunConfiguration myRuntimeConfiguration; private final ContentHandler myResultHandler; private final AbstractTestProxy myTestRoot; + private final boolean myHidePassedConfig; - public static void execute(AbstractTestProxy root, RunConfiguration runtimeConfiguration, ContentHandler resultHandler) + public static void execute(AbstractTestProxy root, RunConfiguration runtimeConfiguration, TestConsoleProperties properties, ContentHandler resultHandler) throws SAXException { - new TestResultsXmlFormatter(root, runtimeConfiguration, resultHandler).execute(); + new TestResultsXmlFormatter(root, runtimeConfiguration, properties, resultHandler).execute(); } - private TestResultsXmlFormatter(AbstractTestProxy root, RunConfiguration runtimeConfiguration, ContentHandler resultHandler) { + private TestResultsXmlFormatter(AbstractTestProxy root, + RunConfiguration runtimeConfiguration, + TestConsoleProperties properties, + ContentHandler resultHandler) { myRuntimeConfiguration = runtimeConfiguration; myTestRoot = root; myResultHandler = resultHandler; + myHidePassedConfig = TestConsoleProperties.HIDE_SUCCESSFUL_CONFIG.value(properties); } private void execute() throws SAXException { @@ -205,6 +209,9 @@ public class TestResultsXmlFormatter { if (locationUrl != null) { attrs.put(ATTR_LOCATION, locationUrl); } + if (node.isConfig()) { + attrs.put(ATTR_CONFIG, "true"); + } String elemName = node.isLeaf() ? ELEM_TEST : ELEM_SUITE; startElement(elemName, attrs); if (node.isLeaf()) { @@ -250,7 +257,7 @@ public class TestResultsXmlFormatter { } else { for (AbstractTestProxy child : node.getChildren()) { - if (child.isConfig() && child.isPassed()) { + if (myHidePassedConfig && child.isConfig() && child.isPassed()) { //ignore configurations during export continue; } diff --git a/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java b/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java index b6ee77a9639d..0bbde43947cb 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java +++ b/plugins/junit/src/com/intellij/execution/junit2/ui/properties/JUnitConsoleProperties.java @@ -21,6 +21,7 @@ import com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction; import com.intellij.execution.testframework.JavaAwareTestConsoleProperties; import com.intellij.execution.testframework.JavaTestLocator; import com.intellij.execution.testframework.SourceScope; +import com.intellij.execution.testframework.TestConsoleProperties; import com.intellij.execution.testframework.actions.AbstractRerunFailedTestsAction; import com.intellij.execution.testframework.sm.runner.SMTestLocator; import com.intellij.execution.ui.ConsoleView; @@ -59,9 +60,9 @@ public class JUnitConsoleProperties extends JavaAwareTestConsoleProperties Date: Wed, 1 Jul 2015 20:36:26 +0300 Subject: [PATCH 42/68] testng: hide suite with only config methods if hide successful configs is on --- .../com/intellij/execution/testframework/Filter.java | 12 ++++++++++-- .../testframework/actions/TestFrameworkActions.java | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/platform/testRunner/src/com/intellij/execution/testframework/Filter.java b/platform/testRunner/src/com/intellij/execution/testframework/Filter.java index d4c6b1f9105a..6c35b7891da5 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/Filter.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/Filter.java @@ -127,10 +127,18 @@ public abstract class Filter { } }); - public static final Filter SUCCESSFUL_CONFIGS = new Filter() { + public static final Filter HIDE_SUCCESSFUL_CONFIGS = new Filter() { @Override public boolean shouldAccept(AbstractTestProxy test) { - return !test.isConfig() || !test.isPassed(); + final List children = test.getChildren(); + if (!children.isEmpty()) { + for (AbstractTestProxy proxy : children) { + if (!proxy.isConfig() || !proxy.isPassed()) return true; + } + return false; + } + + return !(test.isConfig() && test.isPassed()); } }; diff --git a/platform/testRunner/src/com/intellij/execution/testframework/actions/TestFrameworkActions.java b/platform/testRunner/src/com/intellij/execution/testframework/actions/TestFrameworkActions.java index 1ee357d4d0d0..712b1bdb483a 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/actions/TestFrameworkActions.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/actions/TestFrameworkActions.java @@ -56,7 +56,7 @@ public class TestFrameworkActions { } final boolean hideSuccessfulConfigs = TestConsoleProperties.HIDE_SUCCESSFUL_CONFIG.value(properties); - final Filter hideConfigsFilter = hideSuccessfulConfigs ? Filter.SUCCESSFUL_CONFIGS : Filter.NO_FILTER; + final Filter hideConfigsFilter = hideSuccessfulConfigs ? Filter.HIDE_SUCCESSFUL_CONFIGS : Filter.NO_FILTER; return hidePassedFilter.and(hideIgnoredFilter).and(hideConfigsFilter); } From fd33468767ba5c02e58971f0429054b337b74eb1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 1 Jul 2015 21:29:22 +0300 Subject: [PATCH 43/68] junit: fully ignore test class with @Ignore annotation --- .../com/intellij/junit4/JUnit4TestListener.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java index 6bbe7bd28b9f..6d4e5e33fb7e 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java @@ -211,6 +211,19 @@ public class JUnit4TestListener extends RunListener { } public synchronized void testIgnored(Description description) throws Exception { + final String methodName = getFullMethodName(description); + if (methodName == null) { + for (Iterator iterator = description.getChildren().iterator(); iterator.hasNext(); ) { + final Description testDescription = (Description)iterator.next(); + testIgnored(testDescription, getFullMethodName(testDescription)); + } + } + else { + testIgnored(description, methodName); + } + } + + private void testIgnored(Description description, String methodName) throws Exception { testStarted(description); Map attrs = new HashMap(); try { @@ -225,7 +238,7 @@ public class JUnit4TestListener extends RunListener { catch (NoSuchMethodError ignored) { //junit < 4.4 } - attrs.put("name", getFullMethodName(description)); + attrs.put("name", methodName); myPrintStream.println(MapSerializerUtil.asString(MapSerializerUtil.TEST_IGNORED, attrs)); testFinished(description); } From c0f23414de09d99477544081b0856ba3da4ffc5c Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 1 Jul 2015 22:01:01 +0300 Subject: [PATCH 44/68] close-then-save to avoid confusion as save may take some time --- .../options/ex/SingleConfigurableEditor.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java index f114fc2becad..612715b43bfa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java @@ -47,7 +47,7 @@ public class SingleConfigurableEditor extends DialogWrapper { private JComponent myCenterPanel; private final String myDimensionKey; private final boolean myShowApplyButton; - private boolean myChangesWereApplied; + private boolean mySaveAllOnClose; public SingleConfigurableEditor(@Nullable Project project, Configurable configurable, @@ -166,18 +166,16 @@ public class SingleConfigurableEditor extends DialogWrapper { @Override public void doCancelAction() { - if (myChangesWereApplied) { - ApplicationManager.getApplication().saveAll(); - } super.doCancelAction(); } @Override protected void doOKAction() { try { - if (myConfigurable.isModified()) myConfigurable.apply(); - - ApplicationManager.getApplication().saveAll(); + if (myConfigurable.isModified()) { + myConfigurable.apply(); + mySaveAllOnClose = true; + } } catch (ConfigurationException e) { if (e.getMessage() != null) { @@ -237,7 +235,7 @@ public class SingleConfigurableEditor extends DialogWrapper { myPerformAction = true; if (myConfigurable.isModified()) { myConfigurable.apply(); - myChangesWereApplied = true; + mySaveAllOnClose = true; setCancelButtonText(CommonBundle.getCloseButtonText()); } } @@ -275,5 +273,9 @@ public class SingleConfigurableEditor extends DialogWrapper { super.dispose(); myConfigurable.disposeUIResources(); myConfigurable = null; + + if (mySaveAllOnClose) { + ApplicationManager.getApplication().saveAll(); + } } } From a6e21812c010d9829498b42ece0f3322ec6403c4 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 1 Jul 2015 21:28:19 +0200 Subject: [PATCH 45/68] IDEA-142182 File templates variables table size is inconsistent --- .../Groovy JUnit SetUp Method.groovy.html | 4 +-- .../Groovy JUnit TearDown Method.groovy.html | 4 +-- .../code/Groovy JUnit Test Case.groovy.html | 4 +-- .../code/Groovy JUnit Test Method.groovy.html | 4 +-- .../code/Groovy New Method Body.groovy.html | 10 +++---- .../code/Spock Test Method.groovy.html | 4 +-- .../code/Spock cleanup Method.groovy.html | 4 +-- .../code/Spock_SetUp_Method.groovy.html | 4 +-- .../code/JUnit3 SetUp Method.java.html | 4 +-- .../code/JUnit3 TearDown Method.java.html | 4 +-- .../code/JUnit3 Test Class.java.html | 6 ++--- .../code/JUnit3 Test Method.java.html | 4 +-- .../code/JUnit4 Parameters Method.java.html | 4 +-- .../code/JUnit4 SetUp Method.java.html | 4 +-- .../code/JUnit4 TearDown Method.java.html | 4 +-- .../code/JUnit4 Test Class.java.html | 6 ++--- .../code/JUnit4 Test Method.java.html | 4 +-- .../code/TestNG Parameters Method.java.html | 4 +-- .../code/TestNG SetUp Method.java.html | 4 +-- .../code/TestNG TearDown Method.java.html | 4 +-- .../code/TestNG Test Class.java.html | 6 ++--- .../code/TestNG Test Method.java.html | 4 +-- .../code/Catch Statement Body.java.html | 4 +-- .../code/I18nized Concatenation.java.html | 8 +++--- .../code/I18nized Expression.java.html | 6 ++--- .../code/I18nized JSP Expression.jsp.html | 4 +-- .../code/Implemented Method Body.java.html | 10 +++---- .../code/New Method Body.java.html | 10 +++---- .../code/Overridden Method Body.java.html | 12 ++++----- resources-en/src/fileTemplates/default.html | 26 +++++++++---------- .../includes/File Header.java.html | 24 ++++++++--------- .../src/fileTemplates/includes/default.html | 24 ++++++++--------- .../internal/AnnotationType.java.html | 26 +++++++++---------- .../fileTemplates/internal/Class.java.html | 26 +++++++++---------- .../src/fileTemplates/internal/Enum.java.html | 26 +++++++++---------- .../internal/Interface.java.html | 26 +++++++++---------- .../internal/package-info.java.html | 24 ++++++++--------- 37 files changed, 178 insertions(+), 178 deletions(-) diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit SetUp Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit SetUp Method.groovy.html index 59bf56df03e5..3b29eed03d8d 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit SetUp Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit SetUp Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit TearDown Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit TearDown Method.groovy.html index b31948642b23..08b75d0b30b4 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit TearDown Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit TearDown Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.html index d5fe228ec24e..de03ccf75d81 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created class. + name of the created class. ${BODY}   - generated class body. + generated class body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Method.groovy.html index 2f27795254f2..adb72f10c452 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy New Method Body.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy New Method Body.groovy.html index a98243ef53ce..411a720471ae 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy New Method Body.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy New Method Body.groovy.html @@ -16,27 +16,27 @@ ${RETURN_TYPE}   - a return type of a created method + a return type of a created method ${DEFAULT_RETURN_VALUE}   - a value returned by the method by default + a value returned by the method by default ${METHOD_NAME}   - name of the created method + name of the created method ${CLASS_NAME}   - qualified name of the class where method is created + qualified name of the class where method is created ${SIMPLE_CLASS_NAME}   - non-qualified name of the class where method is implemented + non-qualified name of the class where method is implemented diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock Test Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock Test Method.groovy.html index 8a162f4ad3a8..19225e3347eb 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock Test Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock Test Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock cleanup Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock cleanup Method.groovy.html index 538317fa6376..aa8a3b993a57 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock cleanup Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock cleanup Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html index 0ae62ac4e8b8..af1715cabe1e 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Spock_SetUp_Method.groovy.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 SetUp Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit3 SetUp Method.java.html index d41bedc88e66..da9481ce7e71 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 SetUp Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit3 SetUp Method.java.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 TearDown Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit3 TearDown Method.java.html index a20a8a351f81..af95f9eb9f0d 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 TearDown Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit3 TearDown Method.java.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.html b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.html index fa8f461d46c9..55a3babbf7cc 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.html @@ -14,17 +14,17 @@ ${NAME}   - name of the created class. + name of the created class. ${CLASS_NAME}   - name of the tested class. + name of the tested class. ${BODY}   - generated class body. + generated class body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 Test Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit3 Test Method.java.html index 738f32f0401f..2c5b0884c599 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 Test Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit3 Test Method.java.html @@ -15,12 +15,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 Parameters Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit4 Parameters Method.java.html index 7844aa2260b0..84955b94bb57 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 Parameters Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit4 Parameters Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 SetUp Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit4 SetUp Method.java.html index b48a5a892f58..3108d0d2d617 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 SetUp Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit4 SetUp Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 TearDown Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit4 TearDown Method.java.html index 199a4ec1e722..9f1134fc5285 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 TearDown Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit4 TearDown Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.html b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.html index 17c69ded9d16..d69748372fd8 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.html @@ -14,17 +14,17 @@ ${NAME}   - name of the created class. + name of the created class. ${CLASS_NAME}   - name of the tested class. + name of the tested class. ${BODY}   - generated class body. + generated class body. diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 Test Method.java.html b/plugins/junit/src/fileTemplates/code/JUnit4 Test Method.java.html index 1b7bde93b677..2bc910979a2d 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 Test Method.java.html +++ b/plugins/junit/src/fileTemplates/code/JUnit4 Test Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/testng/src/fileTemplates/code/TestNG Parameters Method.java.html b/plugins/testng/src/fileTemplates/code/TestNG Parameters Method.java.html index da1766197222..4096b1bbec5a 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG Parameters Method.java.html +++ b/plugins/testng/src/fileTemplates/code/TestNG Parameters Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/testng/src/fileTemplates/code/TestNG SetUp Method.java.html b/plugins/testng/src/fileTemplates/code/TestNG SetUp Method.java.html index 9736ca8b96e1..83e384012d4c 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG SetUp Method.java.html +++ b/plugins/testng/src/fileTemplates/code/TestNG SetUp Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/testng/src/fileTemplates/code/TestNG TearDown Method.java.html b/plugins/testng/src/fileTemplates/code/TestNG TearDown Method.java.html index f7f3b58393d1..db29f0bf12b9 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG TearDown Method.java.html +++ b/plugins/testng/src/fileTemplates/code/TestNG TearDown Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.html b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.html index f068ea33a622..4fbd57c7ce0e 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.html +++ b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.html @@ -14,17 +14,17 @@ ${NAME}   - name of the created class. + name of the created class. ${CLASS_NAME}   - name of the tested class. + name of the tested class. ${BODY}   - generated class body. + generated class body. diff --git a/plugins/testng/src/fileTemplates/code/TestNG Test Method.java.html b/plugins/testng/src/fileTemplates/code/TestNG Test Method.java.html index 81b82b324de1..19e8b49beb94 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG Test Method.java.html +++ b/plugins/testng/src/fileTemplates/code/TestNG Test Method.java.html @@ -14,12 +14,12 @@ ${NAME}   - name of the created method. + name of the created method. ${BODY}   - generated method body. + generated method body. diff --git a/resources-en/src/fileTemplates/code/Catch Statement Body.java.html b/resources-en/src/fileTemplates/code/Catch Statement Body.java.html index 06712437b6e9..4b521ae28a86 100644 --- a/resources-en/src/fileTemplates/code/Catch Statement Body.java.html +++ b/resources-en/src/fileTemplates/code/Catch Statement Body.java.html @@ -17,12 +17,12 @@ ${EXCEPTION}   - name of the Exception variable specified as a catch parameter + name of the Exception variable specified as a catch parameter ${EXCEPTION_TYPE}   - type of the catch parameter + type of the catch parameter diff --git a/resources-en/src/fileTemplates/code/I18nized Concatenation.java.html b/resources-en/src/fileTemplates/code/I18nized Concatenation.java.html index 5eac1093e7e0..882c67d95e9a 100644 --- a/resources-en/src/fileTemplates/code/I18nized Concatenation.java.html +++ b/resources-en/src/fileTemplates/code/I18nized Concatenation.java.html @@ -18,24 +18,24 @@ ${RESOURCE_BUNDLE}   - Expression of type java.util.ResourceBundle, instance of which is available in this context. + Expression of type java.util.ResourceBundle, instance of which is available in this context. ${PARAMETERS}   - Variables used in the string concatenation, usually passed as arguments to the internationalized expression. + Variables used in the string concatenation, usually passed as arguments to the internationalized expression. ${PROPERTY_KEY}   - Property key name which is defined in the corresponding properties file. + Property key name which is defined in the corresponding properties file. Typically it is the value that is used for ResourceBundle.getString() method parameter. ${PROPERTY_VALUE}   - Property value which is defined in the corresponding properties file. + Property value which is defined in the corresponding properties file. This is the original Java string literal value. diff --git a/resources-en/src/fileTemplates/code/I18nized Expression.java.html b/resources-en/src/fileTemplates/code/I18nized Expression.java.html index 9b6decffb14e..c2bdc0bb9666 100644 --- a/resources-en/src/fileTemplates/code/I18nized Expression.java.html +++ b/resources-en/src/fileTemplates/code/I18nized Expression.java.html @@ -18,19 +18,19 @@ ${RESOURCE_BUNDLE}   - Expression of type java.util.ResourceBundle, instance of which is available in this context. + Expression of type java.util.ResourceBundle, instance of which is available in this context. ${PROPERTY_KEY}   - Property key name which is specified in the corresponding properties file. + Property key name which is specified in the corresponding properties file. Typically it is the value that is used for ResourceBundle.getString() method parameter. ${PROPERTY_VALUE}   - Property value which is defined in the corresponding properties file. + Property value which is defined in the corresponding properties file. This is the original Java string literal value. diff --git a/resources-en/src/fileTemplates/code/I18nized JSP Expression.jsp.html b/resources-en/src/fileTemplates/code/I18nized JSP Expression.jsp.html index 7ee26d1ee527..ddbdf586ebb1 100644 --- a/resources-en/src/fileTemplates/code/I18nized JSP Expression.jsp.html +++ b/resources-en/src/fileTemplates/code/I18nized JSP Expression.jsp.html @@ -28,13 +28,13 @@ ${PROPERTY_KEY}   - Property key name which is specified in the corresponding properties file. + Property key name which is specified in the corresponding properties file. ${PROPERTY_VALUE}   - Property value which is specified in the corresponding properties file. + Property value which is specified in the corresponding properties file. This is an original JSP text selection value. diff --git a/resources-en/src/fileTemplates/code/Implemented Method Body.java.html b/resources-en/src/fileTemplates/code/Implemented Method Body.java.html index 3e9ab3db7b87..5ace03af656b 100644 --- a/resources-en/src/fileTemplates/code/Implemented Method Body.java.html +++ b/resources-en/src/fileTemplates/code/Implemented Method Body.java.html @@ -18,27 +18,27 @@ ${RETURN_TYPE}   - return type of a created method + return type of a created method ${DEFAULT_RETURN_VALUE}   - value returned by the method by default + value returned by the method by default ${METHOD_NAME}   - name of the method that is implemented + name of the method that is implemented ${CLASS_NAME}   - qualified name of the class where method is implemented + qualified name of the class where method is implemented ${SIMPLE_CLASS_NAME}   - non-qualified name of the class where method is implemented + non-qualified name of the class where method is implemented All the predefined variables from the File Header template (Includes tab) are also available diff --git a/resources-en/src/fileTemplates/code/New Method Body.java.html b/resources-en/src/fileTemplates/code/New Method Body.java.html index 73d7741a07ee..9510ae63d65c 100644 --- a/resources-en/src/fileTemplates/code/New Method Body.java.html +++ b/resources-en/src/fileTemplates/code/New Method Body.java.html @@ -16,27 +16,27 @@ ${RETURN_TYPE}   - return type of a created method + return type of a created method ${DEFAULT_RETURN_VALUE}   - value returned by the method by default + value returned by the method by default ${METHOD_NAME}   - name of the created method + name of the created method ${CLASS_NAME}   - qualified name of the class where method is created + qualified name of the class where method is created ${SIMPLE_CLASS_NAME}   - non-qualified name of the class where method is implemented + non-qualified name of the class where method is implemented All the predefined variables from the File Header template (Includes tab) are also available diff --git a/resources-en/src/fileTemplates/code/Overridden Method Body.java.html b/resources-en/src/fileTemplates/code/Overridden Method Body.java.html index fe9e5ef4d871..bf6621df421f 100644 --- a/resources-en/src/fileTemplates/code/Overridden Method Body.java.html +++ b/resources-en/src/fileTemplates/code/Overridden Method Body.java.html @@ -17,34 +17,34 @@ ${CALL_SUPER}   - a super method call, for void methods - super.method_name(); with or without parameters; + a super method call, for void methods - super.method_name(); with or without parameters; for other methods - return super.method_name(); with or without parameters ${RETURN_TYPE}   - return type of a created method + return type of a created method ${DEFAULT_RETURN_VALUE}   - value returned by the method by default + value returned by the method by default ${METHOD_NAME}   - name of the method that is overridden + name of the method that is overridden ${CLASS_NAME}   - qualified name of the class where method is overridden + qualified name of the class where method is overridden ${SIMPLE_CLASS_NAME}   - non-qualified name of the class where method is implemented + non-qualified name of the class where method is implemented All the predefined variables from the File Header template (Includes tab) are also available diff --git a/resources-en/src/fileTemplates/default.html b/resources-en/src/fileTemplates/default.html index 3f274894834c..a3edd5bf792a 100644 --- a/resources-en/src/fileTemplates/default.html +++ b/resources-en/src/fileTemplates/default.html @@ -22,67 +22,67 @@ ${PACKAGE_NAME}   - name of the package in which the new file is created + name of the package in which the new file is created ${NAME}   - name of the new file specified by you in the New <TEMPLATE_NAME> dialog + name of the new file specified by you in the New <TEMPLATE_NAME> dialog ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/includes/File Header.java.html b/resources-en/src/fileTemplates/includes/File Header.java.html index 620246af9ae1..30b9700b873d 100644 --- a/resources-en/src/fileTemplates/includes/File Header.java.html +++ b/resources-en/src/fileTemplates/includes/File Header.java.html @@ -16,62 +16,62 @@ ${PACKAGE_NAME}   - name of the package in which the new file is created + name of the package in which the new file is created ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/includes/default.html b/resources-en/src/fileTemplates/includes/default.html index 0a6692ce8c10..372c29c20d90 100644 --- a/resources-en/src/fileTemplates/includes/default.html +++ b/resources-en/src/fileTemplates/includes/default.html @@ -17,62 +17,62 @@ ${PACKAGE_NAME}   - name of the package in which the new file is created + name of the package in which the new file is created ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/internal/AnnotationType.java.html b/resources-en/src/fileTemplates/internal/AnnotationType.java.html index 9a9f1cda42df..9e5bd43ed021 100644 --- a/resources-en/src/fileTemplates/internal/AnnotationType.java.html +++ b/resources-en/src/fileTemplates/internal/AnnotationType.java.html @@ -24,67 +24,67 @@ ${PACKAGE_NAME}   - name of the package in which the new annotation is created + name of the package in which the new annotation is created ${NAME}   - name of the new annotation specified by you in the Create New Class dialog + name of the new annotation specified by you in the Create New Class dialog ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/internal/Class.java.html b/resources-en/src/fileTemplates/internal/Class.java.html index a997ed46bf96..b9e263e38536 100644 --- a/resources-en/src/fileTemplates/internal/Class.java.html +++ b/resources-en/src/fileTemplates/internal/Class.java.html @@ -24,67 +24,67 @@ ${PACKAGE_NAME}   - name of the package in which the new class is created + name of the package in which the new class is created ${NAME}   - name of the new class specified by you in the Create New Class dialog + name of the new class specified by you in the Create New Class dialog ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/internal/Enum.java.html b/resources-en/src/fileTemplates/internal/Enum.java.html index be18942b1cb6..2ef442b8fcc5 100644 --- a/resources-en/src/fileTemplates/internal/Enum.java.html +++ b/resources-en/src/fileTemplates/internal/Enum.java.html @@ -24,67 +24,67 @@ ${PACKAGE_NAME}   - name of the package in which the new enum is created + name of the package in which the new enum is created ${NAME}   - name of the new enum specified by you in the Create New Class dialog + name of the new enum specified by you in the Create New Class dialog ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/internal/Interface.java.html b/resources-en/src/fileTemplates/internal/Interface.java.html index b172b381ff20..c1f0bbc67755 100644 --- a/resources-en/src/fileTemplates/internal/Interface.java.html +++ b/resources-en/src/fileTemplates/internal/Interface.java.html @@ -24,67 +24,67 @@ ${PACKAGE_NAME}   - name of the package in which the new interface is created + name of the package in which the new interface is created ${NAME}   - name of the new interface specified by you in the Create New Class dialog + name of the new interface specified by you in the Create New Class dialog ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project diff --git a/resources-en/src/fileTemplates/internal/package-info.java.html b/resources-en/src/fileTemplates/internal/package-info.java.html index 32529e35dc6d..6698e0c822db 100644 --- a/resources-en/src/fileTemplates/internal/package-info.java.html +++ b/resources-en/src/fileTemplates/internal/package-info.java.html @@ -24,62 +24,62 @@ ${PACKAGE_NAME}   - name of the package in which the new package-info.java file is created + name of the package in which the new package-info.java file is created ${USER}   - current user system login name + current user system login name ${DATE}   - current system date + current system date ${TIME}   - current system time + current system time ${YEAR}   - current year + current year ${MONTH}   - current month + current month ${MONTH_NAME_SHORT}   - first 3 letters of the current month name. Example: Jan, Feb, etc. + first 3 letters of the current month name. Example: Jan, Feb, etc. ${MONTH_NAME_FULL}   - full name of the current month. Example: January, February, etc. + full name of the current month. Example: January, February, etc. ${DAY}   - current day of the month + current day of the month ${HOUR}   - current hour + current hour ${MINUTE}   - current minute + current minute ${PROJECT_NAME}   - the name of the current project + the name of the current project From a99d360907baff04abfcccea688072c2f2876988 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 29 Jun 2015 18:11:16 +0200 Subject: [PATCH 46/68] EA-70172 (CCE: EqualityToEqualsFix.doFix) --- .../src/com/siyeh/ig/fixes/EqualityToEqualsFix.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java index 184ae86ffbbf..e9c4f86eb4ba 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,11 +48,11 @@ public class EqualityToEqualsFix extends InspectionGadgetsFix { @Override public void doFix(Project project, ProblemDescriptor descriptor) { final PsiElement comparisonToken = descriptor.getPsiElement(); - final PsiBinaryExpression expression = (PsiBinaryExpression) - comparisonToken.getParent(); - if (expression == null) { + final PsiElement parent = comparisonToken.getParent(); + if (!(parent instanceof PsiBinaryExpression)) { return; } + final PsiBinaryExpression expression = (PsiBinaryExpression)parent; boolean negated = false; final IElementType tokenType = expression.getOperationTokenType(); if (JavaTokenType.NE.equals(tokenType)) { From 63de69e0fe29a9f9b067d3c8ff16dcea7feea453 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 30 Jun 2015 16:24:15 +0200 Subject: [PATCH 47/68] IDEA-141811 (Cannot Add Files to CVS in Unversioned Files Window) --- .../actions/AddFileOrDirectoryAction.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java index 9a9d4f77b3a4..212c6f680d40 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,6 +31,9 @@ import com.intellij.cvsSupport2.cvsoperations.cvsAdd.ui.AbstractAddOptionsDialog import com.intellij.cvsSupport2.ui.CvsTabbedWindow; import com.intellij.cvsSupport2.ui.Options; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.actions.VcsContext; @@ -100,14 +103,26 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { LOG.error(filesToAdd); } - if (showDialog) { - final AbstractAddOptionsDialog dialog = AbstractAddOptionsDialog.createDialog(project, roots, dialogOptions); - if (!dialog.showAndGet()) { - return CvsHandler.NULL; + if (!showDialog) { + return CommandCvsHandler.createAddFilesHandler(project, roots); + } + final CvsHandler[] handler = new CvsHandler[1]; + final Runnable runnable = new Runnable() { + @Override + public void run() { + final AbstractAddOptionsDialog dialog = AbstractAddOptionsDialog.createDialog(project, roots, dialogOptions); + handler[0] = !dialog.showAndGet() ? CvsHandler.NULL : CommandCvsHandler.createAddFilesHandler(project, roots); } + }; + final Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + runnable.run(); + } + else { + application.invokeAndWait(runnable, ModalityState.any()); } - return CommandCvsHandler.createAddFilesHandler(project, roots); + return handler[0]; } @Override From d01aa8187ab7e51884300daf2d6d532b2dc37589 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 1 Jul 2015 22:04:27 +0200 Subject: [PATCH 48/68] IG: cleanup --- .../ig/psiutils/DefiniteAssignmentUtil.java | 73 +++++++++---------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DefiniteAssignmentUtil.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DefiniteAssignmentUtil.java index a5932ffc0ec2..765df624c522 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DefiniteAssignmentUtil.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DefiniteAssignmentUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,10 +30,29 @@ import org.jetbrains.annotations.Nullable; public final class DefiniteAssignmentUtil { public static void checkVariable(PsiVariable variable, DefiniteAssignment definiteAssignment) { + if (variable.getInitializer() != null) { + throw new IllegalArgumentException("variable has initializer, check for assignment to the field"); + } if (variable instanceof PsiField) { final PsiField field = (PsiField)variable; checkField(field, definiteAssignment); } + else if (variable instanceof PsiParameter) { + throw new IllegalArgumentException("parameter has implicit initializer, check for assignment to the parameter"); + } + else if (variable instanceof PsiLocalVariable) { + final PsiLocalVariable localVariable = (PsiLocalVariable)variable; + final PsiElement parent = localVariable.getParent(); + assert parent instanceof PsiDeclarationStatement; + PsiStatement statement = (PsiStatement)parent; + while (statement != null) { + checkStatement(statement, definiteAssignment); + statement = PsiTreeUtil.getNextSiblingOfType(statement, PsiStatement.class); + } + } + else { + assert false; + } } private static void checkField(PsiField field, DefiniteAssignment definiteAssignment) { @@ -44,42 +64,22 @@ public final class DefiniteAssignmentUtil { return; } final PsiElement[] children = aClass.getChildren(); - if (field.hasModifierProperty(PsiModifier.STATIC)) { - for (PsiElement child : children) { - if (child instanceof PsiField) { - final PsiField otherField = (PsiField)child; - if (!otherField.hasModifierProperty(PsiModifier.STATIC)) { - continue; - } + final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); + for (PsiElement child : children) { + if (child instanceof PsiField) { + final PsiField otherField = (PsiField)child; + if (otherField.hasModifierProperty(PsiModifier.STATIC) == isStatic) { checkExpression(otherField.getInitializer(), definiteAssignment, BooleanExpressionValue.UNDEFINED); } - else if (child instanceof PsiClassInitializer) { - final PsiClassInitializer classInitializer = (PsiClassInitializer)child; - if (!classInitializer.hasModifierProperty(PsiModifier.STATIC)) { - continue; - } + } + else if (child instanceof PsiClassInitializer) { + final PsiClassInitializer classInitializer = (PsiClassInitializer)child; + if (classInitializer.hasModifierProperty(PsiModifier.STATIC) == isStatic) { checkCodeBlock(classInitializer.getBody(), definiteAssignment); } } } - else { - for (PsiElement child : children) { - if (child instanceof PsiField) { - final PsiField otherField = (PsiField)child; - if (otherField.hasModifierProperty(PsiModifier.STATIC)) { - continue; - } - checkExpression(otherField.getInitializer(), definiteAssignment, BooleanExpressionValue.UNDEFINED); - } - else if (child instanceof PsiClassInitializer) { - final PsiClassInitializer classInitializer = (PsiClassInitializer)child; - if (classInitializer.hasModifierProperty(PsiModifier.STATIC)) { - continue; - } - checkCodeBlock(classInitializer.getBody(), definiteAssignment); - } - if (definiteAssignment.stop()) return; - } + if (!isStatic) { final PsiMethod[] constructors = aClass.getConstructors(); if (constructors.length != 0) { // missing from spec? final boolean da = definiteAssignment.isDefinitelyAssigned(); @@ -481,14 +481,9 @@ public final class DefiniteAssignmentUtil { } if (PsiType.BOOLEAN.equals(expression.getType())) { final Object result = ExpressionUtils.computeConstantExpression(expression); - if (Boolean.TRUE == result) { - if (BooleanExpressionValue.WHEN_FALSE == value) { - definiteAssignment.set(true, true); - } - return; - } - else if (Boolean.FALSE == result) { - if (BooleanExpressionValue.WHEN_TRUE == value) { + if (result != null) { + if (Boolean.TRUE == result && BooleanExpressionValue.WHEN_FALSE == value || + Boolean.FALSE == result && BooleanExpressionValue.WHEN_TRUE == value) { definiteAssignment.set(true, true); } return; From 7ea2d6d175c9379d39b4aca2566dfdb741a6dc6f Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 1 Jul 2015 22:21:31 +0200 Subject: [PATCH 49/68] IG: check fields with initializers correctly in "Field may be final" inspection --- .../src/com/siyeh/ig/psiutils/FinalUtils.java | 6 ++++- .../ig/psiutils/VariableAccessUtils.java | 27 +++++++++++++++++++ .../style/field_final/FieldMayBeFinal.java | 12 +++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java index 1155a1083906..e320e35b1c2f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2013 Bas Leijdekkers + * Copyright 2009-2015 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,10 @@ public class FinalUtils { private FinalUtils() {} public static boolean canBeFinal(@NotNull PsiVariable variable) { + if (variable.getInitializer() != null || variable instanceof PsiParameter) { + // parameters hava implicit initializer + return !VariableAccessUtils.variableIsAssigned(variable); + } final FinalDefiniteAssignment definiteAssignment = new FinalDefiniteAssignment(variable); DefiniteAssignmentUtil.checkVariable(variable, definiteAssignment); return definiteAssignment.isDefinitelyAssigned() && diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java index 03bf5937d44f..a6639f51d1e8 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java @@ -16,7 +16,10 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -79,6 +82,30 @@ public class VariableAccessUtils { return visitor.isPassed(); } + public static boolean variableIsAssigned(@NotNull PsiVariable variable) { + if (variable instanceof PsiField) { + if (variable.hasModifierProperty(PsiModifier.PRIVATE)) { + final PsiClass aClass = PsiUtil.getTopLevelClass(variable); + return variableIsAssigned(variable, aClass); + } + return !ReferencesSearch.search(variable, variable.getUseScope()).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + if (!(element instanceof PsiExpression)) { + return true; + } + final PsiExpression expression = (PsiExpression)element; + return !PsiUtil.isAccessedForWriting(expression); + } + }); + } + final PsiElement context = + PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class, PsiMethod.class, PsiLambdaExpression.class, + PsiCatchSection.class, PsiForStatement.class, PsiForeachStatement.class); + return variableIsAssigned(variable, context); + } + public static boolean variableIsAssigned( @NotNull PsiVariable variable, @Nullable PsiElement context) { if (context == null) { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/field_final/FieldMayBeFinal.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/field_final/FieldMayBeFinal.java index e532626bfd39..299549b239ed 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/field_final/FieldMayBeFinal.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/field_final/FieldMayBeFinal.java @@ -886,6 +886,18 @@ class T58 { x = 3; } } +class T59 { + private int i = 0; + { + assert true : i++; + } +} +class T60 { + private int i = 1; + { + if (false) i = 2; + } +} class Foo { public interface Accessor { From 71aaf4065dd567c9a0e708e7f8609ba1d5de8b5d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 1 Jul 2015 22:37:10 +0200 Subject: [PATCH 50/68] IDEA-142052 ("'try finally' replaceable with 'try' with resources" inspection creates non compiling code) --- ...ryFinallyCanBeTryWithResourcesInspection.java | 6 +++++- .../src/com/siyeh/ig/psiutils/FinalUtils.java | 2 +- .../TryFinallyCanBeTryWithResources.java | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java index 3ac50a5fbfe6..2dd21f4b8ed7 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -27,6 +27,7 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.FinalUtils; import com.siyeh.ig.psiutils.PsiElementOrderComparator; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; @@ -352,6 +353,9 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection { } static boolean isVariableUsedOutsideContext(PsiVariable variable, PsiElement context) { + if (!FinalUtils.canBeFinal(variable)) { + return true; + } final VariableUsedOutsideContextVisitor visitor = new VariableUsedOutsideContextVisitor(variable, context); final PsiElement declarationScope = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class); if (declarationScope == null) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java index e320e35b1c2f..d51d94ca0f58 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/FinalUtils.java @@ -25,7 +25,7 @@ public class FinalUtils { public static boolean canBeFinal(@NotNull PsiVariable variable) { if (variable.getInitializer() != null || variable instanceof PsiParameter) { - // parameters hava implicit initializer + // parameters have an implicit initializer return !VariableAccessUtils.variableIsAssigned(variable); } final FinalDefiniteAssignment definiteAssignment = new FinalDefiniteAssignment(variable); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/try_finally_can_be_try_with_resources/TryFinallyCanBeTryWithResources.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/try_finally_can_be_try_with_resources/TryFinallyCanBeTryWithResources.java index ab34d8d4c15f..83cd11796df7 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/try_finally_can_be_try_with_resources/TryFinallyCanBeTryWithResources.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/try_finally_can_be_try_with_resources/TryFinallyCanBeTryWithResources.java @@ -1,5 +1,6 @@ package com.siyeh.igtest.migration.try_finally_can_be_try_with_resources; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -33,4 +34,19 @@ class TryFinallyCanBeTryWithResources { stream.close(); } } + + public void write3() throws IOException { + InputStream in = true ? new FileInputStream("null") : null; + try { + byte[] magicNumber = new byte[2]; + in.mark(2); + in.read(magicNumber); + in.reset(); + if (false) { + in = new FileInputStream("in"); // var can't be (implicitly final) resource var, because it is reassigned here + } + } finally { + in.close(); + } + } } \ No newline at end of file From bac27e2d1322002ed30ab1c5e57b62b6ba0082e0 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Thu, 25 Jun 2015 17:20:34 +0400 Subject: [PATCH 51/68] IDEA-44866 Shelve Changes: Cancel should work * Disable cancel button when non cancelable section starts in ProgressWindow --- .../progress/impl/ProgressManagerImpl.java | 6 +++--- .../openapi/progress/util/ProgressDialog.java | 11 +++++++--- .../openapi/progress/util/ProgressWindow.java | 20 +++++++++++++++++++ .../src/messages/VcsBundle.properties | 1 + .../changes/shelf/ShelveChangesManager.java | 10 +++++++++- .../changes/ui/CommitChangeListDialog.java | 6 +++--- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index b10d4a2ddc60..59cb98f268b2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -108,9 +108,9 @@ public class ProgressManagerImpl extends CoreProgressManager implements Disposab @Override @NotNull public Future runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task, - @NotNull final ProgressIndicator progressIndicator, - @Nullable final Runnable continuation, - @NotNull final ModalityState modalityState) { + @NotNull final ProgressIndicator progressIndicator, + @Nullable final Runnable continuation, + @NotNull final ModalityState modalityState) { if (progressIndicator instanceof Disposable) { Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java index 1af8c87d2444..ac3cd0066991 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java @@ -17,6 +17,7 @@ package com.intellij.openapi.progress.util; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.DialogWrapperPeer; @@ -221,13 +222,17 @@ class ProgressDialog implements Disposable { } void cancel() { + enableCancelButtonIfNeeded(false); + } + + void enableCancelButtonIfNeeded(final boolean enable) { if (myProgressWindow.myShouldShowCancel) { - SwingUtilities.invokeLater(new Runnable() { + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - myCancelButton.setEnabled(false); + myCancelButton.setEnabled(enable); } - }); + }, ModalityState.any()); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 4cdbb8b60242..9487ec1cce9a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -241,6 +241,22 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro } } + @Override + public void startNonCancelableSection() { + if (isCancelable()) { + enableCancel(false); + } + super.startNonCancelableSection(); + } + + @Override + public void finishNonCancelableSection() { + super.finishNonCancelableSection(); + if (isCancelable()) { + enableCancel(true); + } + } + @Override public void setIndeterminate(boolean indeterminate) { super.setIndeterminate(indeterminate); @@ -384,4 +400,8 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro public boolean isPopupWasShown() { return myDialog != null && myDialog.myPopup != null && myDialog.myPopup.isShowing(); } + + protected void enableCancel(boolean enable) { + myDialog.enableCancelButtonIfNeeded(enable); + } } diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties index 495e33efca33..3346f02c164d 100644 --- a/platform/platform-resources-en/src/messages/VcsBundle.properties +++ b/platform/platform-resources-en/src/messages/VcsBundle.properties @@ -352,6 +352,7 @@ patch.apply.conflict.patched.version=Patched Version patch.apply.select.title=Select Patch File patch.apply.select.base.directory.title=Select Base Directory shelve.changes.action=Shelve Changes +shelve.changes.progress.title=Shelving Changes... patch.apply.already.applied=All of the changes in the specified patch are already contained in the code patch.apply.partially.applied=Some of the changes in the specified patch were skipped because they are already contained in the code patch.apply.success.applied.text=Patch successfully applied diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java index fc14371c55b5..bf934fa68569 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java @@ -34,6 +34,7 @@ import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase; import com.intellij.openapi.diff.impl.patch.formove.CustomBinaryPatchApplier; import com.intellij.openapi.diff.impl.patch.formove.PatchApplier; import com.intellij.openapi.progress.AsynchronousExecution; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; @@ -146,6 +147,10 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD public ShelvedChangeList shelveChanges(final Collection changes, final String commitMessage, final boolean rollback) throws IOException, VcsException { + final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + if (progressIndicator != null) { + progressIndicator.setText(VcsBundle.message("shelve.changes.progress.title")); + } final List textChanges = new ArrayList(); final List binaryFiles = new ArrayList(); for (Change change : changes) { @@ -180,12 +185,15 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD patchPath, commitContext); changeList = new ShelvedChangeList(patchPath.toString(), commitMessage.replace('\n', ' '), binaryFiles); - myShelvedChangeLists.add(changeList); ProgressManager.checkCanceled(); + myShelvedChangeLists.add(changeList); if (rollback) { final String operationName = UIUtil.removeMnemonic(RollbackChangesDialog.operationNameByChanges(myProject, changes)); boolean modalContext = ApplicationManager.getApplication().isDispatchThread() && LaterInvocator.isInModalContext(); + if (progressIndicator != null) { + progressIndicator.startNonCancelableSection(); + } new RollbackWorker(myProject, operationName, modalContext). doRollback(changes, true, null, VcsBundle.message("shelve.changes.action")); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index 3125ab0d34e4..d83564e213ed 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.DataSink; import com.intellij.openapi.actionSystem.TypeSafeDataProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressManager; @@ -68,6 +69,7 @@ import java.util.List; public class CommitChangeListDialog extends DialogWrapper implements CheckinProjectPanel, TypeSafeDataProvider { private final static String outCommitHelpId = "reference.dialogs.vcs.commit"; private static final int LAYOUT_VERSION = 2; + private static final Logger LOG = Logger.getInstance(CommitChangeListDialog.class); private final CommitContext myCommitContext; private final CommitMessage myCommitMessageArea; private Splitter mySplitter; @@ -692,7 +694,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj commitExecutor.getActionText()); for (CheckinHandler handler : myHandlers) { - handler.checkinFailed(Arrays.asList(new VcsException(e))); + handler.checkinFailed(Collections.singletonList(new VcsException(e))); } } finally { @@ -707,8 +709,6 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj } } }, commitExecutor); - - } else { session.executionCanceled(); From dab52f5ff80e48c32ba91b81931994667f2f2101 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 24 Jun 2015 18:48:00 +0400 Subject: [PATCH 52/68] Create patch additional component panel optimized * unused dvcsUsed variable and appropriate for-statement removed; * cache additionalUIPanel instead of double creation; * new patch dialog creation become 2 times faster when called from commitChanges dialog --- .../patch/CreatePatchCommitExecutor.java | 39 +++++++------------ .../patch/CreatePatchConfigurationPanel.java | 4 +- .../changes/ui/CommitChangeListDialog.java | 5 ++- .../openapi/vcs/changes/ui/SessionDialog.java | 11 +++++- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java index 4e2d89ac752c..7c9a1bfaf5f9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java @@ -29,14 +29,15 @@ import com.intellij.openapi.diff.impl.patch.IdeaTextPatchBuilder; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.DefaultJDOMExternalizer; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMExternalizable; -import com.intellij.openapi.util.WriteExternalException; -import com.intellij.openapi.vcs.*; +import com.intellij.openapi.util.*; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsApplicationSettings; +import com.intellij.openapi.vcs.VcsBundle; +import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; @@ -54,7 +55,7 @@ import java.util.List; */ public class CreatePatchCommitExecutor extends LocalCommitExecutor implements ProjectComponent, JDOMExternalizable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.patch.CreatePatchCommitExecutor"); - + private final Project myProject; private final ChangeListManager myChangeListManager; @@ -139,24 +140,13 @@ public class CreatePatchCommitExecutor extends LocalCommitExecutor implements Pr myPanel.setFileName(ShelveChangesManager.suggestPatchName(myProject, commitMessage, new File(PATCH_PATH), null)); myPanel.setReversePatch(false); - boolean dvcsIsUsed = false; - - if (ProjectLevelVcsManager.getInstance(myProject).dvcsUsedInProject()) { - for (Change change : changes) { - final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myProject); - if (vcs != null && VcsType.distributed.equals(vcs.getType())) { - dvcsIsUsed = true; - break; - } + myPanel.setChanges(ContainerUtil.filter(changes, new Condition() { + @Override + public boolean value(Change change) { + return change.getBeforeRevision() != null && change.getAfterRevision() != null; } - } - final List modified = new ArrayList(); - for (Change change : changes) { - if (change.getBeforeRevision() == null || change.getAfterRevision() == null) continue; - modified.add(change); - } - myPanel.setChanges(modified); - myPanel.showTextStoreOption(dvcsIsUsed); + })); + myPanel.showTextStoreOption(); return myPanel.getPanel(); } @@ -258,7 +248,8 @@ public class CreatePatchCommitExecutor extends LocalCommitExecutor implements Pr LOG.info(ex); WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { public void run() { - Messages.showErrorDialog(myProject, VcsBundle.message("create.patch.error.title", ex.getMessage()), CommonBundle.getErrorTitle()); + Messages.showErrorDialog(myProject, VcsBundle.message("create.patch.error.title", ex.getMessage()), + CommonBundle.getErrorTitle()); } }, null, myProject); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java index c398b5fbd62c..131d7e707661 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java @@ -66,7 +66,6 @@ public class CreatePatchConfigurationPanel { private JCheckBox myIncludeBaseRevisionTextCheckBox; private Consumer myOkEnabledListener; private final Project myProject; - private boolean myDvcsIsUsed; private List myChanges; private Collection myIncludedChanges; private SelectFilesToAddTextsToPatchPanel mySelectFilesToAddTextsToPatchPanel; @@ -173,8 +172,7 @@ public class CreatePatchConfigurationPanel { myPanelWithSelectedFiles.add(myHideableTitledPanel, BorderLayout.CENTER); } - public void showTextStoreOption(final boolean dvcsIsUsed) { - myDvcsIsUsed = dvcsIsUsed; + public void showTextStoreOption() { if (myChanges.size() > 0) { myIncludeBaseRevisionTextCheckBox.setVisible(true); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index d83564e213ed..759a97426dad 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -653,12 +653,13 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj return; } boolean isOK = true; - if (SessionDialog.createConfigurationUI(session, getIncludedChanges(), getCommitMessage())!= null) { + final JComponent configurationUI = SessionDialog.createConfigurationUI(session, getIncludedChanges(), getCommitMessage()); + if (configurationUI != null) { DialogWrapper sessionDialog = new SessionDialog(commitExecutor.getActionText(), getProject(), session, getIncludedChanges(), - getCommitMessage()); + getCommitMessage(), configurationUI); isOK = sessionDialog.showAndGet(); } if (isOK) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java index fccbcf69af90..42a336e80999 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java @@ -41,17 +41,24 @@ public class SessionDialog extends DialogWrapper { public SessionDialog(String title, Project project, CommitSession session, List changes, - String commitMessage) { + String commitMessage, @Nullable JComponent configurationComponent) { super(project, true); mySession = session; myChanges = changes; myCommitMessage = commitMessage; - myConfigurationComponent = createConfigurationUI(mySession, myChanges, myCommitMessage); + myConfigurationComponent = + configurationComponent == null ? createConfigurationUI(mySession, myChanges, myCommitMessage) : configurationComponent; setTitle(CommitChangeListDialog.trimEllipsis(title)); init(); updateButtons(); } + public SessionDialog(String title, Project project, + CommitSession session, List changes, + String commitMessage) { + this(title, project, session, changes, commitMessage, null); + } + public static JComponent createConfigurationUI(final CommitSession session, final List changes, final String commitMessage) { try { return session.getAdditionalConfigurationUI(changes, commitMessage); From 305f7ae78f841cd41f982597fe86ce72ddc27613 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Thu, 2 Jul 2015 08:12:32 +0300 Subject: [PATCH 53/68] fixed exec permission for binaries into unix jre bundled. --- build/scripts/dist.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 373b1e6512aa..dfe40cd92382 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -172,7 +172,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix]) if (p("jdk.bundled.linux") != "false") { - buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/bin/*"]) + buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}-jdk-bundled.tar", [paths.distAll, paths.distUnix, "${paths.sandbox}/bundled.linux.jdk"], ["jre/jre/bin/*"]) } return info } From 259830af4deb27d16f8fe86bf14bed205218a2f4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 2 Jul 2015 11:29:52 +0200 Subject: [PATCH 54/68] IDEA-140785 Replace check getFacets().size() > 0 with hasFacet() which stops on first match --- .../com/intellij/appengine/actions/UploadApplicationAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java index 2ee134dda4b7..028b155a4113 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java @@ -46,7 +46,7 @@ public class UploadApplicationAction extends AnAction { public void update(AnActionEvent e) { final Project project = e.getProject(); e.getPresentation().setEnabledAndVisible( - project != null && !ProjectFacetManager.getInstance(project).getFacets(AppEngineFacet.ID).isEmpty()); + project != null && ProjectFacetManager.getInstance(project).hasFacets(AppEngineFacet.ID)); if (project != null) { String text; From 5e9bd9e7df575d62c20adc7d4e6100f00e74c833 Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Thu, 2 Jul 2015 12:39:39 +0300 Subject: [PATCH 55/68] Cucumber JVM. Removed unnecessary bundling of cucumber-java.jar --- build/scripts/libLicenses.gant | 1 - 1 file changed, 1 deletion(-) diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index e301961d8804..783c833133bc 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -260,7 +260,6 @@ libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "htt libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Beta3", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Kryo", libraryName: "Kryo", version: "2.22", license: "New BSD License", url: "https://github.com/EsotericSoftware/kryo", licenseUrl: "https://github.com/EsotericSoftware/kryo/blob/master/license.txt") libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "0.3.1", license: "Apache 2.0", url: "https://github.com/dain/snappy", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") -libraryLicense(name: "Cucumber-Java", libraryName: "cucumber-java", version: "1.2.2", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "Cucumber-JVM", libraryName: "cucumber-jvm", version: "1.2.2", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "Cucumber-Groovy", libraryName: "cucumber-groovy", version: "1.2.2", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "XStream", libraryName: "XStream", version: "1.4.2", license: "BSD License", url: "https://github.com/cucumber/cucumber-jvm-deps/", licenseUrl: "http://xstream.codehaus.org/license.html") From 3e7cafec3c5f6c86e73c60b64aa9e8d8680030a3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 17:46:52 +0300 Subject: [PATCH 56/68] cleanup --- .../openapi/vfs/newvfs/impl/FileNameCache.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java index 7fee33451002..2c49ecd05d5f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java @@ -60,13 +60,13 @@ public class FileNameCache { private static int calcStripeIdFromNameId(int id) { int h = id; - h -= (h<<6); - h ^= (h>>17); - h -= (h<<9); - h ^= (h<<4); - h -= (h<<3); - h ^= (h<<10); - h ^= (h>>15); + h -= h<<6; + h ^= h>>17; + h -= h<<9; + h ^= h<<4; + h -= h<<3; + h ^= h<<10; + h ^= h>>15; return h % ourNameCache.length; } From 784d53709b3fb7ebdb741a429fa029c604b1a1f9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 20:00:21 +0300 Subject: [PATCH 57/68] notnull --- .../core-api/src/com/intellij/lang/PsiBuilder.java | 12 +++++++----- .../core-api/src/com/intellij/lang/PsiParser.java | 4 ++-- .../intellij/lang/WhitespacesAndCommentsBinder.java | 4 +++- .../src/com/intellij/lang/impl/DelegateMarker.java | 13 +++++++------ .../com/intellij/lang/impl/PsiBuilderAdapter.java | 1 + .../intellij/codeInsight/daemon/NavigateAction.java | 12 +++++++----- .../embedding/MasqueradingPsiBuilderAdapter.java | 5 +++-- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/platform/core-api/src/com/intellij/lang/PsiBuilder.java b/platform/core-api/src/com/intellij/lang/PsiBuilder.java index bc6d2eca1c4b..66b4abd44afd 100644 --- a/platform/core-api/src/com/intellij/lang/PsiBuilder.java +++ b/platform/core-api/src/com/intellij/lang/PsiBuilder.java @@ -140,6 +140,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @return the new marker instance. */ + @NotNull Marker precede(); /** @@ -160,7 +161,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @param type the type of the node in the AST tree. */ - void done(IElementType type); + void done(@NotNull IElementType type); /** * Like {@linkplain #done(IElementType)}, but collapses all tokens between start and end markers @@ -168,7 +169,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @param type the type of the node in the AST tree. */ - void collapse(IElementType type); + void collapse(@NotNull IElementType type); /** * Like {@linkplain #done(IElementType)}, but the marker is completed (end marker inserted) @@ -178,7 +179,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param type the type of the node in the AST tree. * @param before marker to complete this one before. */ - void doneBefore(IElementType type, Marker before); + void doneBefore(@NotNull IElementType type, @NotNull Marker before); /** * Like {@linkplain #doneBefore(IElementType, Marker)}, but in addition an error element with given text @@ -188,7 +189,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param before marker to complete this one before. * @param errorMessage for error element. */ - void doneBefore(IElementType type, Marker before, String errorMessage); + void doneBefore(@NotNull IElementType type, @NotNull Marker before, String errorMessage); /** * Completes this marker and labels it as error element with specified message. Before calling this method, @@ -204,7 +205,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * @param message for error element. * @param before marker to complete this one before. */ - void errorBefore(String message, Marker before); + void errorBefore(String message, @NotNull Marker before); /** * Allows to define custom edge token binders instead of default ones. If any of parameters is null @@ -222,6 +223,7 @@ public interface PsiBuilder extends UserDataHolder, UserDataHolderUnprotected { * * @return the new marker instance. */ + @NotNull Marker mark(); /** diff --git a/platform/core-api/src/com/intellij/lang/PsiParser.java b/platform/core-api/src/com/intellij/lang/PsiParser.java index 0d241bcb50f1..0962ed977ed4 100644 --- a/platform/core-api/src/com/intellij/lang/PsiParser.java +++ b/platform/core-api/src/com/intellij/lang/PsiParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -38,5 +38,5 @@ public interface PsiParser { * @return the root of the resulting AST tree. */ @NotNull - ASTNode parse(IElementType root, PsiBuilder builder); + ASTNode parse(@NotNull IElementType root, @NotNull PsiBuilder builder); } diff --git a/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java b/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java index 2c24103f954b..7c3eb4070d63 100644 --- a/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java +++ b/platform/core-api/src/com/intellij/lang/WhitespacesAndCommentsBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.lang; import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -31,6 +32,7 @@ public interface WhitespacesAndCommentsBinder { * Provides an ability for the processor to get a text of any of given tokens. */ interface TokenTextGetter { + @NotNull CharSequence get(int i); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java b/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java index c28af8b4860b..10b6ae5f9d7d 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java +++ b/platform/core-impl/src/com/intellij/lang/impl/DelegateMarker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -35,6 +35,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { return myDelegate; } + @NotNull @Override public PsiBuilder.Marker precede() { return myDelegate.precede(); @@ -51,22 +52,22 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { } @Override - public void done(IElementType type) { + public void done(@NotNull IElementType type) { myDelegate.done(type); } @Override - public void collapse(IElementType type) { + public void collapse(@NotNull IElementType type) { myDelegate.collapse(type); } @Override - public void doneBefore(IElementType type, PsiBuilder.Marker before) { + public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before) { myDelegate.doneBefore(type, before); } @Override - public void doneBefore(IElementType type, PsiBuilder.Marker before, String errorMessage) { + public void doneBefore(@NotNull IElementType type, @NotNull PsiBuilder.Marker before, String errorMessage) { myDelegate.doneBefore(type, before, errorMessage); } @@ -76,7 +77,7 @@ public abstract class DelegateMarker implements PsiBuilder.Marker { } @Override - public void errorBefore(String message, PsiBuilder.Marker before) { + public void errorBefore(String message, @NotNull PsiBuilder.Marker before) { myDelegate.errorBefore(message, before); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java index b66f8062d42e..9cd3540180b0 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderAdapter.java @@ -101,6 +101,7 @@ public class PsiBuilderAdapter implements PsiBuilder { return myDelegate.getCurrentOffset(); } + @NotNull @Override public Marker mark() { return myDelegate.mark(); diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java index 90ccfbffbf8b..bc3bb1de1bd5 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/NavigateAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.ShortcutSet; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.event.MouseEvent; @@ -28,10 +29,10 @@ import java.awt.event.MouseEvent; * @author Dmitry Avdeev */ public class NavigateAction extends AnAction { - private LineMarkerInfo myInfo; + private final LineMarkerInfo myInfo; - public NavigateAction(String text, - LineMarkerInfo info, + public NavigateAction(@NotNull String text, + @NotNull LineMarkerInfo info, @Nullable String originalActionId) { super(text); myInfo = info; @@ -41,7 +42,7 @@ public class NavigateAction extends AnAction { } } - public NavigateAction(LineMarkerInfo info) { + public NavigateAction(@NotNull LineMarkerInfo info) { myInfo = info; } @@ -56,7 +57,8 @@ public class NavigateAction extends AnAction { } } - public static LineMarkerInfo setNavigateAction(LineMarkerInfo info, String text, @Nullable String originalActionId) { + @NotNull + public static LineMarkerInfo setNavigateAction(@NotNull LineMarkerInfo info, @NotNull String text, @Nullable String originalActionId) { NavigateAction action = new NavigateAction(text, info, originalActionId); info.setNavigateAction(action); return info; diff --git a/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java b/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java index 2aef6155b8ef..4f3488517c7b 100644 --- a/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java +++ b/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java @@ -222,6 +222,7 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter { return true; } + @NotNull @Override public Marker mark() { // In the case of the topmost node all should be inserted @@ -344,12 +345,12 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter { } @Override - public void doneBefore(IElementType type, Marker before) { + public void doneBefore(@NotNull IElementType type, @NotNull Marker before) { super.doneBefore(type, getDelegateOrThis(before)); } @Override - public void doneBefore(IElementType type, Marker before, String errorMessage) { + public void doneBefore(@NotNull IElementType type, @NotNull Marker before, String errorMessage) { super.doneBefore(type, getDelegateOrThis(before), errorMessage); } From 863eeb189854e46b1bce926cacce1656406a52ac Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 20:21:49 +0300 Subject: [PATCH 58/68] IDEA-141330 Find Usages cannot find valid usage from abstract class --- .../daemon/impl/UnusedSymbolUtil.java | 18 +-- .../psi/impl/FindSuperElementsHelper.java | 125 ++++++++++++++++++ .../daemon/impl/JavaLineMarkerProvider.java | 122 +++++++++++------ .../codeInsight/daemon/impl/MarkerType.java | 46 ++++--- .../hint/actions/ShowSiblingsAction.java | 20 ++- .../navigation/JavaGotoSuperHandler.java | 38 +++--- .../ide/util/SuperMethodWarningUtil.java | 33 +++-- .../JavaAllOverridingMethodsSearcher.java | 4 +- .../psi/impl/FindSuperElementsHelper.java | 56 -------- .../gotosuper/SiblingInheritance.after.java | 11 ++ .../gotosuper/SiblingInheritance.java | 11 ++ .../impl}/JavaGotoSuperTest.java | 72 ++++++++-- ...odNotExposedInInterfaceInspectionBase.java | 14 +- .../NoopMethodInAbstractClassInspection.java | 5 + .../codeInsight/GroovyLineMarkerProvider.java | 23 ++-- 15 files changed, 402 insertions(+), 196 deletions(-) create mode 100644 java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java delete mode 100644 java/java-psi-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java create mode 100644 java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java create mode 100644 java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java rename java/java-tests/testSrc/com/intellij/codeInsight/{navigation => daemon/impl}/JavaGotoSuperTest.java (51%) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java index a200ebd04f89..b1c858b0d9bb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/UnusedSymbolUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.impl.source.PsiClassImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchHelper; @@ -135,14 +136,15 @@ public class UnusedSymbolUtil { } else { //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too - if (containingClass != null && method.isConstructor() + boolean isConstructor = method.isConstructor(); + if (containingClass != null && isConstructor && containingClass.getConstructors().length == 1 && isClassUsed(project, containingFile, containingClass, progress, helper)) { return true; } if (isImplicitUsage(project, method, progress)) return true; - if (method.findSuperMethods().length != 0) { + if (!isConstructor && FindSuperElementsHelper.findSuperElements(method).length != 0) { return true; } if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) { @@ -193,7 +195,7 @@ public class UnusedSymbolUtil { @NotNull PsiFile containingFile, @NotNull PsiMember member, @NotNull ProgressIndicator progress, - final PsiFile ignoreFile, + @Nullable PsiFile ignoreFile, @NotNull Processor usageInfoProcessor) { String name = member.getName(); if (name == null) { @@ -247,10 +249,8 @@ public class UnusedSymbolUtil { } else if (member instanceof PsiMethod) { PsiMethod method = (PsiMethod)member; - JavaMethodFindUsagesOptions o = new JavaMethodFindUsagesOptions(project); - //o.isIncludeOverloadUsages = true; - options = o; - options.isSearchForTextOccurrences = method.isConstructor();; + options = new JavaMethodFindUsagesOptions(project); + options.isSearchForTextOccurrences = method.isConstructor(); } else if (member instanceof PsiVariable) { options = new JavaVariableFindUsagesOptions(project); @@ -271,7 +271,7 @@ public class UnusedSymbolUtil { @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) { final PsiClass containingClass = member.getContainingClass(); - if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true; + if (!(containingClass instanceof PsiClassImpl)) return true; final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod(); return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper); } diff --git a/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java new file mode 100644 index 000000000000..f52bffd65b4c --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2015 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.impl; + +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.psi.util.PsiSuperMethodUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.Processor; +import com.intellij.util.containers.FactoryMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class FindSuperElementsHelper { + @NotNull + public static PsiElement[] findSuperElements(@NotNull PsiElement element) { + if (element instanceof PsiClass) { + PsiClass aClass = (PsiClass) element; + List allSupers = new ArrayList(Arrays.asList(aClass.getSupers())); + for (Iterator iterator = allSupers.iterator(); iterator.hasNext();) { + PsiClass superClass = iterator.next(); + if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove(); + } + return allSupers.toArray(new PsiClass[allSupers.size()]); + } + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod) element; + if (method.isConstructor()) { + PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method); + if (constructorInSuper != null) { + return new PsiMethod[]{constructorInSuper}; + } + } + else { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) { + PsiMethod superMethod = getSiblingInheritedViaSubClass(method); + if (superMethod != null) { + superMethods = new PsiMethod[]{superMethod}; + } + } + return superMethods; + } + } + return PsiElement.EMPTY_ARRAY; + } + + public static PsiMethod getSiblingInheritedViaSubClass(@NotNull PsiMethod method) { + return getSiblingInheritedViaSubClass(method, createSubClassCache()); + } + + public static PsiMethod getSiblingInheritedViaSubClass(@NotNull final PsiMethod method, + @NotNull Map subClassCache) { + if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null; + if (method.hasModifierProperty(PsiModifier.STATIC)) return null; + final PsiClass containingClass = method.getContainingClass(); + boolean hasSubClass = containingClass != null && !containingClass.isInterface() && subClassCache.get(containingClass) != null; + if (!hasSubClass) { + return null; + } + final Collection checkedInterfaces = new THashSet(); + final PsiMethod[] result = new PsiMethod[1]; + ClassInheritorsSearch.search(containingClass, true).forEach(new Processor() { + @Override + public boolean process(PsiClass inheritor) { + for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) { + PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics(); + PsiClass anInterface = resolved.getElement(); + if (anInterface == null || !checkedInterfaces.add(anInterface)) continue; + for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) { + PsiClass superInterface = superMethod.getContainingClass(); + if (superInterface == null) { + continue; + } + + // calculate substitutor of containingClass --> inheritor + PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, inheritor, PsiSubstitutor.EMPTY); + // calculate substitutor of inheritor --> superInterface + substitutor = TypeConversionUtil.getSuperClassSubstitutor(superInterface, inheritor, substitutor); + + final MethodSignature superSignature = superMethod.getSignature(substitutor); + final MethodSignature derivedSignature = method.getSignature(PsiSubstitutor.EMPTY); + boolean isOverridden = MethodSignatureUtil.isSubsignature(superSignature, derivedSignature); + + if (isOverridden) { + result[0] = superMethod; + return false; + } + } + } + return true; + } + }); + return result[0]; + } + + @NotNull + public static Map createSubClassCache() { + return new FactoryMap() { + @Nullable + @Override + protected PsiClass create(PsiClass aClass) { + return ClassInheritorsSearch.search(aClass, false).findFirst(); + } + }; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index 4c705206a0a1..a0a7a0352ba5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,8 +31,8 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.search.searches.AllOverridingMethodsSearch; -import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; @@ -48,12 +48,12 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; public class JavaLineMarkerProvider implements LineMarkerProvider { - - protected final DaemonCodeAnalyzerSettings myDaemonSettings; - protected final EditorColorsManager myColorsManager; + private final DaemonCodeAnalyzerSettings myDaemonSettings; + private final EditorColorsManager myColorsManager; public JavaLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) { myDaemonSettings = daemonSettings; @@ -72,19 +72,14 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { method.hasModifierProperty(PsiModifier.ABSTRACT) == superSignature.getMethod().hasModifierProperty(PsiModifier.ABSTRACT); final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod; - final MarkerType type = MarkerType.OVERRIDING_METHOD; - ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(element, icon, type); - return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod"); + return createSuperMethodLineMarkerInfo(element, icon, Pass.UPDATE_ALL); } } final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element); final PsiElement firstChild = element.getFirstChild(); if (interfaceMethod != null && firstChild != null) { - final Icon icon = AllIcons.Gutter.ImplementingMethod; - final MarkerType type = MarkerType.OVERRIDING_METHOD; - ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(firstChild, icon, type); - return NavigateAction.setNavigateAction(info, "Go to super method", "GotoSuperMethod"); + return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_ALL); } if (myDaemonSettings.SHOW_METHOD_SEPARATORS && firstChild == null) { @@ -128,6 +123,12 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { return null; } + @NotNull + private static LineMarkerInfo createSuperMethodLineMarkerInfo(@NotNull PsiElement name, @NotNull Icon icon, int passId) { + ArrowUpLineMarkerInfo info = new ArrowUpLineMarkerInfo(name, icon, MarkerType.OVERRIDING_METHOD, passId); + return NavigateAction.setNavigateAction(info, "Go to super method", IdeActions.ACTION_GOTO_SUPER); + } + private static int getCategory(@NotNull PsiElement element, @NotNull CharSequence documentChars) { if (element instanceof PsiField || element instanceof PsiTypeParameter) return 1; if (element instanceof PsiClass || element instanceof PsiClassInitializer) return 2; @@ -147,37 +148,92 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { @Override public void collectSlowLineMarkers(@NotNull final List elements, @NotNull final Collection result) { ApplicationManager.getApplication().assertReadAccessAllowed(); + Map subClassCache = FindSuperElementsHelper.createSubClassCache(); - Set methods = new HashSet(); + Collection methods = new THashSet(); //noinspection ForLoopReplaceableByForEach for (int i = 0; i < elements.size(); i++) { PsiElement element = elements.get(i); ProgressManager.checkCanceled(); - if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)element; + if (!(element instanceof PsiIdentifier)) continue; + PsiElement parent = element.getParent(); + if (parent instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)parent; if (PsiUtil.canBeOverriden(method)) { methods.add(method); } } - else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) { - collectInheritingClasses((PsiClass)element, result); + else if (parent instanceof PsiClass && !(parent instanceof PsiTypeParameter)) { + collectInheritingClasses((PsiClass)parent, result, subClassCache); } } if (!methods.isEmpty()) { - collectOverridingAccessors(methods, result); + collectOverridingMethods(methods, result); + collectSiblingInheritedMethods(methods, result, subClassCache); } } - public static void collectInheritingClasses(PsiClass aClass, Collection result) { + private static void collectSiblingInheritedMethods(@NotNull final Collection methods, + @NotNull Collection result, + @NotNull Map subClassCache) { + for (PsiMethod method : methods) { + ProgressManager.checkCanceled(); + PsiClass aClass = method.getContainingClass(); + if (aClass == null || aClass.hasModifierProperty(PsiModifier.FINAL) || aClass.isInterface()) continue; + + System.err.println("collectSiblingInheritedMethods for "+method+" in "+aClass.getQualifiedName()); + + boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE); + System.err.println("canHaveSiblingSuper = " + canHaveSiblingSuper); + if (!canHaveSiblingSuper) continue; + + PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache); + System.err.println("siblingInheritedViaSubClass = " + siblingInheritedViaSubClass); + if (siblingInheritedViaSubClass == null) { + continue; + } + PsiElement range = getMethodRange(method); + LineMarkerInfo info = createSuperMethodLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_OVERRIDEN_MARKERS); + result.add(info); + PsiClass sClass = siblingInheritedViaSubClass.getContainingClass(); + String sName = sClass == null ? null : sClass.getQualifiedName(); + System.err.println("Added sibling "+siblingInheritedViaSubClass+" in "+sName+" to results: "+result); + } + } + + @NotNull + private static PsiElement getMethodRange(@NotNull PsiMethod method) { + PsiElement range; + if (method.isPhysical()) { + range = method.getNameIdentifier(); + } + else { + final PsiElement navigationElement = method.getNavigationElement(); + range = navigationElement instanceof PsiNameIdentifierOwner + ? ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier() + : navigationElement; + } + if (range == null) { + range = method; + } + return range; + } + + public static void collectInheritingClasses(@NotNull PsiClass aClass, + @NotNull Collection result, + @NotNull Map subClassCache) { if (aClass.hasModifierProperty(PsiModifier.FINAL)) { return; } if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object. - if (ClassInheritorsSearch.search(aClass, false).findFirst() != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { + PsiClass subClass = subClassCache.get(aClass); + if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod; PsiElement range = aClass.getNameIdentifier(); - if (range == null) range = aClass; + if (range == null) { + range = aClass; + } MarkerType type = MarkerType.SUBCLASSED_CLASS; LineMarkerInfo info = new LineMarkerInfo(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(), @@ -188,7 +244,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { } } - private static void collectOverridingAccessors(final Set methods, Collection result) { + private static void collectOverridingMethods(@NotNull final Collection methods, @NotNull Collection result) { final Set overridden = new HashSet(); Set classes = new THashSet(); for (PsiMethod method : methods) { @@ -229,22 +285,9 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { ProgressManager.checkCanceled(); boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT); - final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; - PsiElement range; - if (method.isPhysical()) { - range = method.getNameIdentifier(); - } - else { - final PsiElement navigationElement = method.getNavigationElement(); - if (navigationElement instanceof PsiNameIdentifierOwner) { - range = ((PsiNameIdentifierOwner)navigationElement).getNameIdentifier(); - } - else { - range = navigationElement; - } - } - if (range == null) range = method; + PsiElement range = getMethodRange(method); final MarkerType type = MarkerType.OVERRIDDEN_METHOD; + final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; LineMarkerInfo info = new LineMarkerInfo(range, range.getTextRange(), icon, Pass.UPDATE_OVERRIDEN_MARKERS, type.getTooltip(), type.getNavigationHandler(), @@ -255,8 +298,8 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { } private static class ArrowUpLineMarkerInfo extends MergeableLineMarkerInfo { - private ArrowUpLineMarkerInfo(@NotNull PsiElement element, Icon icon, @NotNull MarkerType markerType) { - super(element, element.getTextRange(), icon, Pass.UPDATE_ALL, markerType.getTooltip(), + private ArrowUpLineMarkerInfo(@NotNull PsiElement element, @NotNull Icon icon, @NotNull MarkerType markerType, int passId) { + super(element, element.getTextRange(), icon, passId, markerType.getTooltip(), markerType.getNavigationHandler(), GutterIconRenderer.Alignment.LEFT); } @@ -274,6 +317,7 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { return myIcon; } + @NotNull @Override public Function getCommonTooltip(@NotNull List infos) { return new Function() { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index 89785c572d84..d956ddcc054d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -34,6 +34,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; import com.intellij.psi.search.SearchScope; @@ -45,6 +46,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.CommonProcessors; import com.intellij.util.Function; import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -105,9 +107,9 @@ public class MarkerType { }); @Nullable - public static String calculateOverridingMethodTooltip(PsiMethod method, boolean acceptSelf) { + private static String calculateOverridingMethodTooltip(@NotNull PsiMethod method, boolean acceptSelf) { PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf); - if (superMethods == null) return null; + if (superMethods.length == 0) return null; PsiMethod superMethod = superMethods[0]; boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); @@ -121,10 +123,11 @@ public class MarkerType { else{ key = sameSignature ? "method.overrides" : "method.overrides.in"; } - return composeText(superMethods, "", DaemonBundle.message(key), "GotoSuperMethod"); + return composeText(superMethods, "", DaemonBundle.message(key), IdeActions.ACTION_GOTO_SUPER); } - private static String composeText(PsiElement[] methods, String start, String pattern, String actionId) { + @NotNull + private static String composeText(@NotNull PsiElement[] methods, @NotNull String start, @NotNull String pattern, @NotNull String actionId) { Shortcut[] shortcuts = ActionManager.getInstance().getAction(actionId).getShortcutSet().getShortcuts(); Shortcut shortcut = ArrayUtil.getFirstElement(shortcuts); String postfix = "

Click"; @@ -133,9 +136,9 @@ public class MarkerType { return GutterIconTooltipHelper.composeText(Arrays.asList(methods), start, pattern, postfix); } - public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method, boolean acceptSelf) { + private static void navigateToOverridingMethod(MouseEvent e, @NotNull PsiMethod method, boolean acceptSelf) { PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf); - if (superMethods == null) return; + if (superMethods.length == 0) return; boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); PsiElementListNavigator.openTargets(e, superMethods, DaemonBundle.message("navigation.title.super.method", method.getName()), @@ -143,17 +146,23 @@ public class MarkerType { new MethodCellRenderer(showMethodNames)); } - @Nullable - private static PsiMethod[] composeSuperMethods(PsiMethod method, boolean acceptSelf) { - PsiMethod[] superMethods = method.findSuperMethods(false); + @NotNull + private static PsiMethod[] composeSuperMethods(@NotNull PsiMethod method, boolean acceptSelf) { + PsiElement[] superElements = FindSuperElementsHelper.findSuperElements(method); + + PsiMethod[] superMethods = ContainerUtil.map(superElements, new Function() { + @Override + public PsiMethod fun(PsiElement element) { + return (PsiMethod)element; + } + }, PsiMethod.EMPTY_ARRAY); if (acceptSelf) { superMethods = ArrayUtil.prepend(method, superMethods); } - if (superMethods.length == 0) return null; return superMethods; } - private static PsiElement getParentMethod(PsiElement element) { + private static PsiElement getParentMethod(@NotNull PsiElement element) { final PsiElement parent = element.getParent(); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(parent); return interfaceMethod != null ? interfaceMethod : parent; @@ -179,7 +188,7 @@ public class MarkerType { } }); - public static String getOverriddenMethodTooltip(final PsiMethod method) { + private static String getOverriddenMethodTooltip(@NotNull PsiMethod method) { PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); @@ -206,7 +215,7 @@ public class MarkerType { return composeText(overridings, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); } - public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) { + private static void navigateToOverriddenMethod(MouseEvent e, @NotNull final PsiMethod method) { if (DumbService.isDumb(method.getProject())) { DumbService.getInstance(method.getProject()).showDumbModeNotification( "Navigation to overriding classes is not possible during index update"); @@ -267,7 +276,7 @@ public class MarkerType { } }); - public static String getSubclassedClassTooltip(PsiClass aClass) { + private static String getSubclassedClassTooltip(@NotNull PsiClass aClass) { PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); @@ -298,7 +307,7 @@ public class MarkerType { return composeText(subclasses, start, pattern, IdeActions.ACTION_GOTO_IMPLEMENTATION); } - public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) { + private static void navigateToSubclassedClass(MouseEvent e, @NotNull final PsiClass aClass) { if (DumbService.isDumb(aClass.getProject())) { DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); return; @@ -331,7 +340,7 @@ public class MarkerType { private final PsiClass myClass; private final PsiClassOrFunctionalExpressionListCellRenderer myRenderer; - public SubclassUpdater(PsiClass aClass, PsiClassOrFunctionalExpressionListCellRenderer renderer) { + private SubclassUpdater(@NotNull PsiClass aClass, @NotNull PsiClassOrFunctionalExpressionListCellRenderer renderer) { super(aClass.getProject(), SEARCHING_FOR_OVERRIDDEN_METHODS); myClass = aClass; myRenderer = renderer; @@ -374,14 +383,13 @@ public class MarkerType { } }); } - } private static class OverridingMethodsUpdater extends ListBackgroundUpdaterTask { private final PsiMethod myMethod; private final PsiElementListCellRenderer myRenderer; - public OverridingMethodsUpdater(PsiMethod method, PsiElementListCellRenderer renderer) { + private OverridingMethodsUpdater(@NotNull PsiMethod method, @NotNull PsiElementListCellRenderer renderer) { super(method.getProject(), SEARCHING_FOR_OVERRIDING_METHODS); myMethod = method; myRenderer = renderer; diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java index 41aea6e9c181..11a101da3edd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/actions/ShowSiblingsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -29,15 +29,11 @@ import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; public class ShowSiblingsAction extends ShowImplementationsAction { - public ShowSiblingsAction() { - super(); - } - @Override - public void performForContext(DataContext dataContext, final boolean invokedByShortcut) { + public void performForContext(@NotNull DataContext dataContext, final boolean invokedByShortcut) { final Project project = CommonDataKeys.PROJECT.getData(dataContext); final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext); @@ -61,7 +57,7 @@ public class ShowSiblingsAction extends ShowImplementationsAction { } final NavigatablePsiElement[] superElements = (NavigatablePsiElement[])findSuperElements(element); - if (superElements == null || superElements.length == 0) return; + if (superElements.length == 0) return; final boolean isMethod = superElements[0] instanceof PsiMethod; final JBPopup popup = PsiElementListNavigator.navigateOrCreatePopup(superElements, "Choose super " + (isMethod ? "method" : "class or interface"), "Super " + (isMethod ? "methods" : "classes/interfaces"), @@ -81,11 +77,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction { } private void showSiblings(boolean invokedByShortcut, - Project project, + @NotNull Project project, Editor editor, PsiFile file, boolean invokedFromEditor, - PsiElement element) { + @NotNull PsiElement element) { final PsiElement[] impls = getSelfAndImplementations(editor, element, createImplementationsSearcher(), false); final String text = SymbolPresentationUtil.getSymbolPresentableText(element); showImplementations(impls, project, text, editor, file, element, invokedFromEditor, invokedByShortcut); @@ -96,11 +92,11 @@ public class ShowSiblingsAction extends ShowImplementationsAction { return false; } - @Nullable + @NotNull private static PsiElement[] findSuperElements(final PsiElement element) { PsiNameIdentifierOwner parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClass.class); if (parent == null) { - return null; + return PsiElement.EMPTY_ARRAY; } return FindSuperElementsHelper.findSuperElements(parent); diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java index 95668b59fa69..1663d31da4a8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class JavaGotoSuperHandler implements CodeInsightActionHandler { @Override @@ -41,7 +40,7 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { int offset = editor.getCaretModel().getOffset(); PsiElement[] superElements = findSuperElements(file, offset); - if (superElements == null || superElements.length == 0) return; + if (superElements.length == 0) return; if (superElements.length == 1) { PsiElement superElement = superElements[0].getNavigationElement(); final PsiFile containingFile = superElement.getContainingFile(); @@ -50,24 +49,25 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { if (virtualFile == null) return; OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile, superElement.getTextOffset()); FileEditorManager.getInstance(project).openTextEditor(descriptor, true); - } else { - if (superElements[0] instanceof PsiMethod) { - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements); - PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements, - CodeInsightBundle.message("goto.super.method.chooser.title"), - CodeInsightBundle.message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()), - new MethodCellRenderer(showMethodNames)); - } - else { - NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title")).showInBestPositionFor(editor); - } + } + else if (superElements[0] instanceof PsiMethod) { + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements); + PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements, + CodeInsightBundle.message("goto.super.method.chooser.title"), + CodeInsightBundle + .message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()), + new MethodCellRenderer(showMethodNames)); + } + else { + NavigationUtil.getPsiElementPopup(superElements, CodeInsightBundle.message("goto.super.class.chooser.title")) + .showInBestPositionFor(editor); } } - @Nullable - private PsiElement[] findSuperElements(PsiFile file, int offset) { + @NotNull + private PsiElement[] findSuperElements(@NotNull PsiFile file, int offset) { PsiElement element = getElement(file, offset); - if (element == null) return null; + if (element == null) return PsiElement.EMPTY_ARRAY; final PsiElement psiElement = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, PsiMember.class); if (psiElement instanceof PsiFunctionalExpression) { @@ -79,13 +79,13 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler { final PsiNameIdentifierOwner parent = PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class); if (parent == null) { - return null; + return PsiElement.EMPTY_ARRAY; } return FindSuperElementsHelper.findSuperElements(parent); } - protected PsiElement getElement(PsiFile file, int offset) { + protected PsiElement getElement(@NotNull PsiFile file, int offset) { return file.findElementAt(offset); } diff --git a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java index 5e3a2d10c36d..a1a22653a60e 100644 --- a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -26,6 +26,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; @@ -34,6 +35,7 @@ import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -41,20 +43,24 @@ public class SuperMethodWarningUtil { private SuperMethodWarningUtil() {} @NotNull - public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString) { - return checkSuperMethods(method, actionString, null); + public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString) { + return checkSuperMethods(method, actionString, Collections.emptyList()); } @NotNull - public static PsiMethod[] checkSuperMethods(final PsiMethod method, String actionString, Collection ignore) { + public static PsiMethod[] checkSuperMethods(@NotNull PsiMethod method, @NotNull String actionString, @NotNull Collection ignore) { PsiClass aClass = method.getContainingClass(); if (aClass == null) return new PsiMethod[]{method}; final Collection superMethods = DeepestSuperMethodsSearch.search(method).findAll(); - if (ignore != null) { - superMethods.removeAll(ignore); - } + superMethods.removeAll(ignore); + if (superMethods.isEmpty()) { + PsiMethod siblingSuperMethod = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method); + if (siblingSuperMethod != null) { + superMethods.add(siblingSuperMethod); + } + } if (superMethods.isEmpty()) return new PsiMethod[]{method}; @@ -85,7 +91,7 @@ public class SuperMethodWarningUtil { } - public static PsiMethod checkSuperMethod(final PsiMethod method, String actionString) { + public static PsiMethod checkSuperMethod(@NotNull PsiMethod method, @NotNull String actionString) { PsiClass aClass = method.getContainingClass(); if (aClass == null) return method; @@ -110,10 +116,10 @@ public class SuperMethodWarningUtil { return null; } - public static void checkSuperMethod(final PsiMethod method, - final String actionString, - final PsiElementProcessor processor, - final Editor editor) { + public static void checkSuperMethod(@NotNull PsiMethod method, + @NotNull String actionString, + @NotNull final PsiElementProcessor processor, + @NotNull Editor editor) { PsiClass aClass = method.getContainingClass(); if (aClass == null) { processor.execute(method); @@ -137,7 +143,7 @@ public class SuperMethodWarningUtil { return; } - final PsiMethod[] methods = new PsiMethod[]{superMethod, method}; + final PsiMethod[] methods = {superMethod, method}; final String renameBase = actionString + " base method"; final String renameCurrent = actionString + " only current method"; final JBList list = new JBList(renameBase, renameCurrent); @@ -148,6 +154,7 @@ public class SuperMethodWarningUtil { .setResizable(false) .setRequestFocus(true) .setItemChoosenCallback(new Runnable() { + @Override public void run() { final Object value = list.getSelectedValue(); if (value instanceof String) { diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java index a614854ba728..797a22e8d68a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -61,7 +61,7 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor allSupers = new ArrayList(Arrays.asList(aClass.getSupers())); - for (Iterator iterator = allSupers.iterator(); iterator.hasNext();) { - PsiClass superClass = iterator.next(); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) iterator.remove(); - } - return allSupers.toArray(new PsiClass[allSupers.size()]); - } else if (element instanceof PsiMethod) { - PsiMethod method = (PsiMethod) element; - if (method.isConstructor()) { - PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method); - if (constructorInSuper != null) { - return new PsiMethod[]{constructorInSuper}; - } - } else { - return method.findSuperMethods(false); - } - } - return null; - } - -} diff --git a/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java new file mode 100644 index 000000000000..8c4289162396 --- /dev/null +++ b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.after.java @@ -0,0 +1,11 @@ +package z; + +interface I { + void run(); +} +abstract class A { + public void run() {} +} + +class Foo extends A implements I { +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java new file mode 100644 index 000000000000..d8d3e2970a93 --- /dev/null +++ b/java/java-tests/testData/codeInsight/gotosuper/SiblingInheritance.java @@ -0,0 +1,11 @@ +package z; + +interface I { + void run(); +} +abstract class A { + public void run() {} +} + +class Foo extends A implements I { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java similarity index 51% rename from java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java rename to java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java index e666583564b0..1a04900bc371 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.navigation; +package com.intellij.codeInsight.daemon.impl; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.codeInsight.daemon.LineMarkerInfo; -import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; +import com.intellij.ide.DataManager; import com.intellij.lang.CodeInsightActions; import com.intellij.lang.java.JavaLanguage; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -38,7 +39,7 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { return JavaTestUtil.getJavaTestDataPath(); } - protected String getBasePath() { + private static String getBasePath() { return "/codeInsight/gotosuper/"; } @@ -46,6 +47,13 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { doTest(); } + private void doTest() { + configureByFile(getBasePath() + getTestName(false) + ".java"); + final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE); + handler.invoke(getProject(), getEditor(), getFile()); + checkResultByFile(getBasePath() + getTestName(false) + ".after.java"); + } + public void testLambdaMarker() throws Exception { configureByFile(getBasePath() + getTestName(false) + ".java"); int offset = myEditor.getCaretModel().getOffset(); @@ -67,10 +75,52 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { fail("Gutter expected"); } - private void doTest() throws Throwable { - configureByFile(getBasePath() + getTestName(false) + ".java"); - final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE); - handler.invoke(getProject(), getEditor(), getFile()); - checkResultByFile(getBasePath() + getTestName(false) + ".after.java"); + public void testSiblingInheritance() throws Throwable { + doTest(); } + + public void testSiblingInheritanceLineMarkers() throws Throwable { + configureByFile(getBasePath() + "SiblingInheritance.java"); + PsiJavaFile file = (PsiJavaFile)getFile(); + PsiClass i = JavaPsiFacade.getInstance(getProject()).findClass("z.I", GlobalSearchScope.fileScope(file)); + PsiClass a = JavaPsiFacade.getInstance(getProject()).findClass("z.A", GlobalSearchScope.fileScope(file)); + PsiMethod iRun = i.getMethods()[0]; + assertEquals("run", iRun.getName()); + PsiMethod aRun = a.getMethods()[0]; + assertEquals("run", aRun.getName()); + doHighlighting(); + Document document = getEditor().getDocument(); + List markers = DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject()); + assertTrue(markers.size() >= 2); + LineMarkerInfo iMarker = findMarkerWithElement(markers, iRun.getNameIdentifier()); + assertSame(MarkerType.OVERRIDDEN_METHOD.getNavigationHandler(), iMarker.getNavigationHandler()); + + LineMarkerInfo aMarker = findMarkerWithElement(markers, aRun.getNameIdentifier()); + assertSame(MarkerType.OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler()); + } + + private static LineMarkerInfo findMarkerWithElement(List markers, PsiElement psiMethod) { + LineMarkerInfo marker = ContainerUtil.find(markers, info -> { + return info.getElement().equals(psiMethod); + }); + assertNotNull(markers.toString(), marker); + return marker; + } + + public void testSiblingInheritanceGoDown() throws Throwable { + configureByFile(getBasePath() + "SiblingInheritance.after.java"); + AnAction action = ActionManager.getInstance().getAction(IdeActions.ACTION_GOTO_IMPLEMENTATION); + AnActionEvent event = new AnActionEvent( + null, + DataManager.getInstance().getDataContextFromFocus().getResultSync(), + "", + action.getTemplatePresentation(), + ActionManager.getInstance(), + 0); + action.update(event); + assertTrue(event.getPresentation().isEnabledAndVisible()); + action.actionPerformed(event); + checkResultByFile(getBasePath() + "SiblingInheritance.java"); + } + } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspectionBase.java index ca8ec8f0ea0d..d5c2cacee541 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/PublicMethodNotExposedInInterfaceInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,8 @@ package com.siyeh.ig.abstraction; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; +import com.intellij.util.ArrayUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -28,10 +30,10 @@ import com.siyeh.ig.ui.ExternalizableStringSet; import org.jetbrains.annotations.NotNull; public class PublicMethodNotExposedInInterfaceInspectionBase extends BaseInspection { - @SuppressWarnings({"PublicField"}) + @SuppressWarnings("PublicField") public final ExternalizableStringSet ignorableAnnotations = new ExternalizableStringSet(); - @SuppressWarnings({"PublicField"}) + @SuppressWarnings("PublicField") public boolean onlyWarnIfContainingClassImplementsAnInterface = false; @Override @@ -115,7 +117,11 @@ public class PublicMethodNotExposedInInterfaceInspectionBase extends BaseInspect } private boolean exposedInInterface(PsiMethod method) { - final PsiMethod[] superMethods = method.findSuperMethods(); + PsiMethod[] superMethods = method.findSuperMethods(); + PsiMethod siblingInherited = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method); + if (siblingInherited != null && !ArrayUtil.contains(siblingInherited, superMethods)) { + superMethods = ArrayUtil.append(superMethods, siblingInherited); + } for (final PsiMethod superMethod : superMethods) { final PsiClass superClass = superMethod.getContainingClass(); if (superClass == null) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java index 375807f13b3e..74ac21ee25cc 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java @@ -18,6 +18,7 @@ package com.siyeh.ig.classlayout; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -67,6 +68,10 @@ public class NoopMethodInAbstractClassInspection extends BaseInspection { if (!MethodUtils.isEmpty(method)) { return; } + if (FindSuperElementsHelper.getSiblingInheritedViaSubClass(method) != null) { + // it may be an explicit intention to have non-abstract method here in order to sibling-inherit the method in subclass + return; + } registerMethodError(method); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java index 17045deb6ff7..7bfc95d97102 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -33,6 +33,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.impl.FindSuperElementsHelper; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.search.searches.AllOverridingMethodsSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; @@ -60,18 +61,15 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import javax.swing.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author ilyas * Same logic as for Java LMP */ public class GroovyLineMarkerProvider implements LineMarkerProvider { - protected final DaemonCodeAnalyzerSettings myDaemonSettings; - protected final EditorColorsManager myColorsManager; + private final DaemonCodeAnalyzerSettings myDaemonSettings; + private final EditorColorsManager myColorsManager; public GroovyLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) { myDaemonSettings = daemonSettings; @@ -152,7 +150,7 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { return null; } - private static boolean hasSuperMethods(GrMethod method) { + private static boolean hasSuperMethods(@NotNull GrMethod method) { final GrReflectedMethod[] reflectedMethods = method.getReflectedMethods(); if (reflectedMethods.length > 0) { for (GrReflectedMethod reflectedMethod : reflectedMethods) { @@ -166,7 +164,7 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { } } - private static int getGroovyCategory(PsiElement element, CharSequence documentChars) { + private static int getGroovyCategory(@NotNull PsiElement element, @NotNull CharSequence documentChars) { if (element instanceof GrVariableDeclarationImpl) { GrVariable[] variables = ((GrVariableDeclarationImpl)element).getVariables(); if (variables.length == 1 && variables[0] instanceof GrField && variables[0].getInitializerGroovy() instanceof GrClosableBlock) { @@ -193,6 +191,7 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { @Override public void collectSlowLineMarkers(@NotNull final List elements, @NotNull final Collection result) { Set methods = new HashSet(); + Map subClassCache = FindSuperElementsHelper.createSubClassCache(); for (PsiElement element : elements) { ProgressManager.checkCanceled(); if (element instanceof GrField) { @@ -208,13 +207,13 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { } } else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) { - JavaLineMarkerProvider.collectInheritingClasses((PsiClass)element, result); + JavaLineMarkerProvider.collectInheritingClasses((PsiClass)element, result, subClassCache); } } collectOverridingMethods(methods, result); } - private static void collectOverridingMethods(final Set methods, Collection result) { + private static void collectOverridingMethods(@NotNull final Set methods, @NotNull Collection result) { final Set overridden = new HashSet(); Set classes = new THashSet(); @@ -264,7 +263,7 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { } } - private static boolean isCorrectTarget(PsiMethod method) { + private static boolean isCorrectTarget(@NotNull PsiMethod method) { if (method instanceof GrTraitMethod) return false; final PsiElement navigationElement = method.getNavigationElement(); From 41cb05a58e73dde5ec9b0170d05ab315b1960273 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 20:28:11 +0300 Subject: [PATCH 59/68] notnull --- .../com/intellij/spi/SPIGotoSuperHandler.java | 5 +- .../daemon/impl/PsiElementListNavigator.java | 7 +- .../actions/ShowImplementationsAction.java | 69 +++++++++++-------- .../navigation/BackgroundUpdaterTask.java | 6 +- 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java index 966a7a3422ea..4be83981446e 100644 --- a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java +++ b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,13 +20,14 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.spi.psi.SPIClassProviderReferenceElement; +import org.jetbrains.annotations.NotNull; /** * User: anna */ public class SPIGotoSuperHandler extends JavaGotoSuperHandler { @Override - protected PsiElement getElement(PsiFile file, int offset) { + protected PsiElement getElement(@NotNull PsiFile file, int offset) { final SPIClassProviderReferenceElement providerElement = PsiTreeUtil.getParentOfType(super.getElement(file, offset), SPIClassProviderReferenceElement.class); if (providerElement != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 57f65283fd2f..4eeca2b71704 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -37,6 +37,7 @@ import com.intellij.ui.popup.HintUpdateSupply; import com.intellij.usages.UsageView; import com.intellij.util.Consumer; import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -88,12 +89,12 @@ public class PsiElementListNavigator { } @Nullable - public static JBPopup navigateOrCreatePopup(final NavigatablePsiElement[] targets, + public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets, final String title, final String findUsagesTitle, final ListCellRenderer listRenderer, @Nullable final ListBackgroundUpdaterTask listUpdaterTask, - final Consumer consumer) { + @NotNull final Consumer consumer) { if (targets.length == 0) return null; if (targets.length == 1) { consumer.consume(targets); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 7c3a0ced14d7..c48ae61e93c6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -105,7 +105,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } - protected Editor getEditor(DataContext dataContext) { + protected static Editor getEditor(@NotNull DataContext dataContext) { Editor editor = CommonDataKeys.EDITOR.getData(dataContext); if (editor == null) { @@ -123,7 +123,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return editor; } - public void performForContext(DataContext dataContext, boolean invokedByShortcut) { + public void performForContext(@NotNull DataContext dataContext, boolean invokedByShortcut) { final Project project = CommonDataKeys.PROJECT.getData(dataContext); if (project == null) return; PsiDocumentManager.getInstance(project).commitAllDocuments(); @@ -185,7 +185,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { showImplementations(impls, project, text, editor, file, element, isInvokedFromEditor, invokedByShortcut); } - protected static PsiElement getElement(Project project, PsiFile file, Editor editor, PsiElement element) { + protected static PsiElement getElement(@NotNull Project project, PsiFile file, Editor editor, PsiElement element) { if (element == null && editor != null) { element = TargetElementUtil.findTargetElement(editor, TargetElementUtil.getInstance().getAllAccepted()); final PsiElement adjustedElement = @@ -200,6 +200,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return element; } + @NotNull protected static ImplementationSearcher createImplementationsSearcher() { if (ApplicationManager.getApplication().isUnitTestMode()) { return new ImplementationSearcher() { @@ -209,18 +210,16 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } }; } - else { - return new ImplementationSearcher.FirstImplementationsSearcher() { - @Override - protected PsiElement[] filterElements(PsiElement element, PsiElement[] targetElements, final int offset) { - return ShowImplementationsAction.filterElements(targetElements); - } - }; - } + return new ImplementationSearcher.FirstImplementationsSearcher() { + @Override + protected PsiElement[] filterElements(PsiElement element, PsiElement[] targetElements, final int offset) { + return ShowImplementationsAction.filterElements(targetElements); + } + }; } - protected void updateElementImplementations(final PsiElement element, final Editor editor, final Project project, final PsiFile file) { - PsiElement[] impls = null; + private void updateElementImplementations(final PsiElement element, final Editor editor, @NotNull Project project, final PsiFile file) { + PsiElement[] impls = {}; String text = ""; if (element != null) { // if (element instanceof PsiPackage) return; @@ -234,10 +233,15 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { showImplementations(impls, project, text, editor, file, element, false, false); } - protected void showImplementations(final PsiElement[] impls, final Project project, final String text, final Editor editor, final PsiFile file, + protected void showImplementations(@NotNull PsiElement[] impls, + @NotNull final Project project, + final String text, + final Editor editor, + final PsiFile file, final PsiElement element, - boolean invokedFromEditor, boolean invokedByShortcut) { - if (impls == null || impls.length == 0) return; + boolean invokedFromEditor, + boolean invokedByShortcut) { + if (impls.length == 0) return; FeatureUsageTracker.getInstance().triggerFeatureUsed(CODEASSISTS_QUICKDEFINITION_FEATURE); if (LookupManager.getInstance(project).getActiveLookup() != null) { @@ -317,7 +321,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } } - private static boolean cancelTask(ImplementationsUpdaterTask task) { + private static boolean cancelTask(@Nullable ImplementationsUpdaterTask task) { if (task != null) { ProgressIndicator indicator = task.myIndicator; if (indicator != null) { @@ -330,9 +334,10 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { private void updateInBackground(Editor editor, @Nullable PsiElement element, - ImplementationViewComponent component, + @NotNull ImplementationViewComponent component, String title, - AbstractPopup popup, Ref usageView) { + @NotNull AbstractPopup popup, + @NotNull Ref usageView) { final ImplementationsUpdaterTask updaterTask = SoftReference.dereference(myTaskRef); cancelTask(updaterTask); @@ -348,15 +353,17 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { return true; } + @NotNull private static PsiElement[] getSelfAndImplementations(Editor editor, - PsiElement element, - final ImplementationSearcher handler) { + @NotNull PsiElement element, + @NotNull ImplementationSearcher handler) { return getSelfAndImplementations(editor, element, handler, !(element instanceof PomTargetPsiElement)); } + @NotNull protected static PsiElement[] getSelfAndImplementations(Editor editor, - PsiElement element, - final ImplementationSearcher handler, + @NotNull PsiElement element, + @NotNull ImplementationSearcher handler, final boolean includeSelfAlways) { int offset = editor == null ? 0 : editor.getCaretModel().getOffset(); final PsiElement[] handlerImplementations = handler.searchImplementations(element, editor, offset, includeSelfAlways, true); @@ -367,17 +374,18 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { // Magically, it's null for ant property declarations. element = element.getNavigationElement(); psiFile = element.getContainingFile(); - if (psiFile == null) return PsiElement.EMPTY_ARRAY; + if (psiFile == null) { + return PsiElement.EMPTY_ARRAY; + } } if (psiFile.getVirtualFile() != null && (element.getTextRange() != null || element instanceof PsiFile)) { return new PsiElement[]{element}; } - else { - return PsiElement.EMPTY_ARRAY; - } + return PsiElement.EMPTY_ARRAY; } - private static PsiElement[] filterElements(final PsiElement[] targetElements) { + @NotNull + private static PsiElement[] filterElements(@NotNull final PsiElement[] targetElements) { final Set unique = new LinkedHashSet(Arrays.asList(targetElements)); for (final PsiElement elt : targetElements) { ApplicationManager.getApplication().runReadAction(new Runnable() { @@ -410,12 +418,13 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { private static class ImplementationsUpdaterTask extends BackgroundUpdaterTask { private final String myCaption; private final Editor myEditor; + @NotNull private final PsiElement myElement; private final boolean myIncludeSelf; private PsiElement[] myElements; private volatile ProgressIndicator myIndicator; - public ImplementationsUpdaterTask(final PsiElement element, final Editor editor, final String caption, boolean includeSelf) { + private ImplementationsUpdaterTask(@NotNull PsiElement element, final Editor editor, final String caption, boolean includeSelf) { super(element.getProject(), ImplementationSearcher.SEARCHING_FOR_IMPLEMENTATIONS); myCaption = caption; myEditor = editor; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java index 397889c8e1cf..85cd0952c0ad 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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,8 +21,6 @@ import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopupAdapter; -import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.ui.popup.AbstractPopup; @@ -69,7 +67,7 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { super(project, title, canBeCancelled, backgroundOption); } - public void init(@NotNull AbstractPopup popup, T component, Ref usageView) { + public void init(@NotNull AbstractPopup popup, @NotNull T component, @NotNull Ref usageView) { myPopup = popup; myComponent = component; myUsageView = usageView; From 551081321065599e323bab98a8882402ad21ea68 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 1 Jul 2015 20:34:19 +0300 Subject: [PATCH 60/68] optimisation --- .../src/com/intellij/psi/SingleRootFileViewProvider.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 9741110e23cf..28e62c06c0e4 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -179,13 +179,14 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi } boolean set = myPsiFile.compareAndSet(null, psiFile); if (!set) { + PsiFile alreadyCreated = myPsiFile.get(); + if (alreadyCreated == psiFile) { + LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); + } if (psiFile instanceof PsiFileImpl) { - if (myPsiFile.get() == psiFile) { - LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); - } ((PsiFileImpl)psiFile).markInvalidated(); } - psiFile = myPsiFile.get(); + psiFile = alreadyCreated; } } return psiFile == PsiUtilCore.NULL_PSI_FILE ? null : psiFile; From e5795c2533f0fd6db475aaad02839a28f93eeade Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 12:27:05 +0300 Subject: [PATCH 61/68] avoid invalidation of NULL_PSI_FILE --- .../src/com/intellij/psi/SingleRootFileViewProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 28e62c06c0e4..c2ef19131a90 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -178,7 +178,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi psiFile = PsiUtilCore.NULL_PSI_FILE; } boolean set = myPsiFile.compareAndSet(null, psiFile); - if (!set) { + if (!set && psiFile != PsiUtilCore.NULL_PSI_FILE) { PsiFile alreadyCreated = myPsiFile.get(); if (alreadyCreated == psiFile) { LOG.error(this + ".createFile() must create new file instance but got the same: " + psiFile); From bbb6fa6d0106faeeb572e50a1b277927bb2b944d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 12:31:51 +0300 Subject: [PATCH 62/68] removed diagnostic println --- .../codeInsight/daemon/impl/JavaLineMarkerProvider.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index a0a7a0352ba5..4faf4245b8ba 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -181,14 +181,10 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { PsiClass aClass = method.getContainingClass(); if (aClass == null || aClass.hasModifierProperty(PsiModifier.FINAL) || aClass.isInterface()) continue; - System.err.println("collectSiblingInheritedMethods for "+method+" in "+aClass.getQualifiedName()); - boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE); - System.err.println("canHaveSiblingSuper = " + canHaveSiblingSuper); if (!canHaveSiblingSuper) continue; PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache); - System.err.println("siblingInheritedViaSubClass = " + siblingInheritedViaSubClass); if (siblingInheritedViaSubClass == null) { continue; } @@ -197,7 +193,6 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { result.add(info); PsiClass sClass = siblingInheritedViaSubClass.getContainingClass(); String sName = sClass == null ? null : sClass.getQualifiedName(); - System.err.println("Added sibling "+siblingInheritedViaSubClass+" in "+sName+" to results: "+result); } } From afac0df426b33189617dace7ebfe60f877d3b030 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 12:33:07 +0300 Subject: [PATCH 63/68] speed optimisation: store computed hashCode --- .../util/text/ByteArrayCharSequence.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java b/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java index fcf7ea4f1dbf..c417c3628075 100644 --- a/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java +++ b/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java @@ -15,15 +15,36 @@ */ package com.intellij.util.text; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; public class ByteArrayCharSequence implements CharSequence { + private int hash; private final byte[] myChars; - public ByteArrayCharSequence(@NotNull byte... chars) { + private ByteArrayCharSequence(@NotNull byte[] chars) { myChars = chars; } + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + byte[] chars = myChars; + + for (byte aChar : chars) { + h = 31 * h + aChar; + } + hash = h; + } + return h; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof CharSequence && StringUtil.equals(this, (CharSequence)obj); + } + @Override public final int length() { return myChars.length; @@ -63,6 +84,7 @@ public class ByteArrayCharSequence implements CharSequence { //noinspection RedundantStringConstructorCall return new String(name.toString()); // So we don't hold whole char[] buffer of a lengthy path on JDK 6 } + bytes[i] = (byte)c; } return new ByteArrayCharSequence(bytes); From 8144b12a672da6628928b2e6816d80f35e4f1509 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 2 Jul 2015 11:53:35 +0200 Subject: [PATCH 64/68] prohibit cached values in vfs user data --- .../openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java | 11 +++++++++++ .../openapi/vfs/newvfs/impl/VirtualFileImpl.java | 1 + 2 files changed, 12 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 37b17c080549..a49df7b86027 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vfs.newvfs.impl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileAttributes; import com.intellij.openapi.util.io.FileUtilRt; @@ -32,6 +33,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; import com.intellij.openapi.vfs.newvfs.persistent.FSRecords; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl; +import com.intellij.psi.impl.PsiCachedValue; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.UriUtil; @@ -547,6 +549,15 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { @Override protected boolean changeUserMap(KeyFMap oldMap, KeyFMap newMap) { + checkLeaks(newMap); return myData.changeUserMap(oldMap, UserDataInterner.internUserData(newMap)); } + + static void checkLeaks(KeyFMap newMap) { + for (Key key : newMap.getKeys()) { + if (key != null && newMap.get(key) instanceof PsiCachedValue) { + throw new AssertionError("Don't store CachedValue in VFS user data, since it leads to memory leaks"); + } + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java index bea852bba7c5..c51a6e62d17d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java @@ -142,6 +142,7 @@ public class VirtualFileImpl extends VirtualFileSystemEntry { @Override protected boolean changeUserMap(KeyFMap oldMap, KeyFMap newMap) { + VirtualDirectoryImpl.checkLeaks(newMap); return mySegment.changeUserMap(Math.abs(getId()), oldMap, UserDataInterner.internUserData(newMap)); } From 6f7ff1646571048ae9e894b536949e19d190d7cc Mon Sep 17 00:00:00 2001 From: Manuel Stadelmann Date: Thu, 2 Jul 2015 12:55:49 +0300 Subject: [PATCH 65/68] RemoveUsageAction: Now selects a next item from the usage tree after removing one or several items. This makes the function easier to use with the keyboard. --- .../usages/actions/RemoveUsageAction.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/platform/usageView/src/com/intellij/usages/actions/RemoveUsageAction.java b/platform/usageView/src/com/intellij/usages/actions/RemoveUsageAction.java index 1d5b9e70cfb1..920575fa4cfc 100644 --- a/platform/usageView/src/com/intellij/usages/actions/RemoveUsageAction.java +++ b/platform/usageView/src/com/intellij/usages/actions/RemoveUsageAction.java @@ -18,14 +18,40 @@ package com.intellij.usages.actions; import com.intellij.usages.Usage; import com.intellij.usages.UsageView; +import java.util.List; + /** * @author Manuel Stadelmann */ public class RemoveUsageAction extends IncludeExcludeActionBase { + @Override protected void process(Usage[] usages, UsageView usageView) { + + Usage nextToSelect = null; + for (Usage usage : usages) { + Usage toSelect = getNextToSelect(usageView, usage); usageView.removeUsage(usage); + nextToSelect = toSelect; + } + + if (nextToSelect != null) { + usageView.selectUsages(new Usage[]{nextToSelect}); } } + + private Usage getNextToSelect(UsageView usageView, Usage toDelete) { + List sortedUsages = usageView.getSortedUsages(); + int curIndex = sortedUsages.indexOf(toDelete); + + int selectIndex = 0; + if (curIndex < sortedUsages.size() - 1) { + selectIndex = curIndex + 1; + } + else if (curIndex > 0) { + selectIndex = curIndex - 1; + } + return sortedUsages.get(selectIndex); + } } From d97756ee9fb4bfc9487aa3c69cf93bd8e4bc29f0 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 2 Jul 2015 13:08:18 +0300 Subject: [PATCH 66/68] IDEA-90072 Faux italics used for some fonts with true italics available --- .../impl/ComplementaryFontsRegistry.java | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index 48e8de5f769b..e1eab3ac56a9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -43,7 +43,13 @@ public class ComplementaryFontsRegistry { private static FontInfo ourSharedDefaultFont; private static final TIntHashSet ourUndisplayableChars = new TIntHashSet(); private static boolean ourOldUseAntialiasing; - + + // This matches style detection in JDK (class sun.font.Font2D) + private static final String[] BOLD_NAMES = {"bold", "demibold", "demi-bold", "demi bold", "negreta", "demi" }; + private static final String[] ITALIC_NAMES = {"italic", "cursiva", "oblique", "inclined"}; + private static final String[] BOLD_ITALIC_NAMES = {"bolditalic", "bold-italic", "bold italic", "boldoblique", "bold-oblique", + "bold oblique", "demibold italic", "negreta cursiva","demi oblique"}; + static { final UISettings settings = UISettings.getInstance(); ourOldUseAntialiasing = settings.ANTIALIASING_IN_EDITOR; @@ -121,35 +127,38 @@ public class ComplementaryFontsRegistry { Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for (Font font : allFonts) { String name = font.getName(); - int style; - if (name.endsWith("-Italic")) { - style = Font.ITALIC; - } - else if (name.endsWith("-Bold")) { - style = Font.BOLD; - } - else if (name.endsWith("-BoldItalic")) { - style = Font.BOLD | Font.ITALIC; - } - else { - style = Font.PLAIN; - } + int style = getFontStyle(name); if (style != Font.PLAIN) { - String baseName = name.substring(0, name.lastIndexOf('-')); - Pair[] entry = ourStyledFontMap.get(baseName); + String familyName = font.getFamily(); + Pair[] entry = ourStyledFontMap.get(familyName); if (entry == null) { //noinspection unchecked entry = new Pair[4]; for (int i = 1; i < 4; i++) { - entry[i] = Pair.create(baseName, i); + entry[i] = Pair.create(familyName, i); } - ourStyledFontMap.put(baseName, entry); + ourStyledFontMap.put(familyName, entry); } entry[style] = Pair.create(name, Font.PLAIN); } } } + @JdkConstants.FontStyle + private static int getFontStyle(String fontName) { + fontName = fontName.toLowerCase(Locale.getDefault()); + for (String name : BOLD_ITALIC_NAMES) { + if (fontName.contains(name)) return Font.BOLD | Font.ITALIC; + } + for (String name : ITALIC_NAMES) { + if (fontName.contains(name)) return Font.ITALIC; + } + for (String name : BOLD_NAMES) { + if (fontName.contains(name)) return Font.BOLD; + } + return Font.PLAIN; + } + private static Pair fontFamily(String familyName, int style) { if (SystemInfo.isMac && style > 0 && style < 4) { Pair[] replacement = ourStyledFontMap.get(familyName); From 957c648ee2d82bb4ca115be74280b838834d6596 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 2 Jul 2015 10:53:59 +0200 Subject: [PATCH 67/68] change emmet edit points shortcut for old OSX keymap too #WEB-16977 fixed --- platform/platform-resources/src/META-INF/XmlActions.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-resources/src/META-INF/XmlActions.xml b/platform/platform-resources/src/META-INF/XmlActions.xml index a7862132188f..8bbde4689a10 100644 --- a/platform/platform-resources/src/META-INF/XmlActions.xml +++ b/platform/platform-resources/src/META-INF/XmlActions.xml @@ -105,12 +105,14 @@ + + From f1306ccb3d044aaedc7c78ffd110d753a66a9a4f Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 2 Jul 2015 13:43:41 +0300 Subject: [PATCH 68/68] inline method to avoid potential garbage generation source (see IDEA-140802) --- .../impl/ComplementaryFontsRegistry.java | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index e1eab3ac56a9..eff05d5534f1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -159,17 +159,6 @@ public class ComplementaryFontsRegistry { return Font.PLAIN; } - private static Pair fontFamily(String familyName, int style) { - if (SystemInfo.isMac && style > 0 && style < 4) { - Pair[] replacement = ourStyledFontMap.get(familyName); - if (replacement != null) { - familyName = replacement[style].first; - style = replacement[style].second; - } - } - return Pair.create(familyName, style); - } - @NotNull public static FontInfo getFontAbleToDisplay(char c, @JdkConstants.FontStyle int style, @NotNull FontPreferences preferences) { boolean tryDefaultFont = true; @@ -209,11 +198,17 @@ public class ComplementaryFontsRegistry { @Nullable private static FontInfo doGetFontAbleToDisplay(char c, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) { synchronized (lock) { - Pair p = fontFamily(defaultFontFamily, style); + if (SystemInfo.isMac && style > 0 && style < 4) { + Pair[] replacement = ourStyledFontMap.get(defaultFontFamily); + if (replacement != null) { + defaultFontFamily = replacement[style].first; + style = replacement[style].second; + } + } if (ourSharedKeyInstance.mySize == size && - ourSharedKeyInstance.myStyle == p.getSecond() && + ourSharedKeyInstance.myStyle == style && ourSharedKeyInstance.myFamilyName != null && - ourSharedKeyInstance.myFamilyName.equals(p.getFirst()) && + ourSharedKeyInstance.myFamilyName.equals(defaultFontFamily) && ourSharedDefaultFont != null && ( c < 128 || ourSharedDefaultFont.canDisplay(c) @@ -222,13 +217,13 @@ public class ComplementaryFontsRegistry { return ourSharedDefaultFont; } - ourSharedKeyInstance.myFamilyName = p.getFirst(); + ourSharedKeyInstance.myFamilyName = defaultFontFamily; ourSharedKeyInstance.mySize = size; - ourSharedKeyInstance.myStyle = p.getSecond(); + ourSharedKeyInstance.myStyle = style; FontInfo defaultFont = ourUsedFonts.get(ourSharedKeyInstance); if (defaultFont == null) { - defaultFont = new FontInfo(p.getFirst(), size, p.getSecond()); + defaultFont = new FontInfo(defaultFontFamily, size, style); ourUsedFonts.put(ourSharedKeyInstance, defaultFont); ourSharedKeyInstance = new FontKey("", 0, 0); }