From 6098de11acf49a36c199d131d7260d5f02541a1d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 18 Jul 2016 11:32:10 +0200 Subject: [PATCH 01/27] failure to load date formats via JNA is not fatal, so we should log it using LOG.info, not LOG.error --- platform/util/src/com/intellij/util/text/DateFormatUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/text/DateFormatUtil.java b/platform/util/src/com/intellij/util/text/DateFormatUtil.java index 096de12833a2..c7a3a3f1ce81 100644 --- a/platform/util/src/com/intellij/util/text/DateFormatUtil.java +++ b/platform/util/src/com/intellij/util/text/DateFormatUtil.java @@ -338,7 +338,7 @@ public class DateFormatUtil { } } catch (Throwable t) { - LOG.error(t); + LOG.info(t); } if (!loaded) { From e6137f81ff5b833d077c7ed3a7b58bb89b3fe3d8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 13:49:10 +0300 Subject: [PATCH 02/27] diagnostics --- platform/configuration-store-impl/src/FileBasedStorage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/configuration-store-impl/src/FileBasedStorage.kt b/platform/configuration-store-impl/src/FileBasedStorage.kt index 84896cb99fde..c08fa660cbc2 100644 --- a/platform/configuration-store-impl/src/FileBasedStorage.kt +++ b/platform/configuration-store-impl/src/FileBasedStorage.kt @@ -262,4 +262,4 @@ fun deleteFile(requestor: Any, virtualFile: VirtualFile) { runWriteAction { virtualFile.delete(requestor) } } -internal class ReadOnlyModificationException(val file: VirtualFile, val session: StateStorage.SaveSession?) : RuntimeException() \ No newline at end of file +internal class ReadOnlyModificationException(val file: VirtualFile, val session: StateStorage.SaveSession?) : RuntimeException("File is read-only: "+file) \ No newline at end of file From 3ca51e434b17ed780e9807f95f1e52d80fc50b22 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 13:49:50 +0300 Subject: [PATCH 03/27] more checkCanceled --- .../folding/impl/JavaFoldingBuilderBase.java | 2 ++ .../codeInsight/daemon/impl/LineMarkersPass.java | 7 ++++--- .../codeInsight/daemon/impl/SlowLineMarkersPass.java | 2 ++ .../siyeh/ig/threading/VariableAccessVisitor.java | 12 ++++++++++-- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java index 8cf092e43176..0b06c9168b16 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java @@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; @@ -522,6 +523,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem PsiClass[] classes = file.getClasses(); for (PsiClass aClass : classes) { + ProgressManager.checkCanceled(); ProgressIndicatorProvider.checkCanceled(); addElementsToFold(descriptors, aClass, document, true, quick); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java index 762df47b9808..a6102236fcb4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java @@ -38,6 +38,7 @@ import com.intellij.openapi.editor.markup.SeparatorPlacement; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; @@ -163,12 +164,12 @@ public class LineMarkersPass extends TextEditorHighlightingPass implements LineM @NotNull ProgressIndicator progress) throws ProcessCanceledException { ApplicationManager.getApplication().assertReadAccessAllowed(); //noinspection ForLoopReplaceableByForEach - for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { + for (int i = 0; i < elements.size(); i++) { PsiElement element = elements.get(i); - progress.checkCanceled(); //noinspection ForLoopReplaceableByForEach - for (int j = 0, providersSize = providers.size(); j < providersSize; j++) { + for (int j = 0; j < providers.size(); j++) { + ProgressManager.checkCanceled(); LineMarkerProvider provider = providers.get(j); LineMarkerInfo info; try { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java index 0996b8b88a8f..bbcc5b8f6067 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java @@ -24,6 +24,7 @@ import com.intellij.lang.Language; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -75,6 +76,7 @@ class SlowLineMarkersPass extends TextEditorHighlightingPass implements LineMark @NotNull List result, @NotNull ProgressIndicator progress) throws ProcessCanceledException { for (LineMarkerProvider provider : providers) { + ProgressManager.checkCanceled(); provider.collectSlowLineMarkers(elements, result); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java index 20853a87e148..5002945f6035 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.threading; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.search.SearchScope; @@ -202,14 +203,16 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { new HashSet(usedMethods); boolean stabilized = false; while (!stabilized) { + ProgressManager.checkCanceled(); stabilized = true; final Set methodsDeterminedThisPass = new HashSet(); for (PsiMethod method : remainingMethods) { - final Collection references = - referenceMap.get(method); + ProgressManager.checkCanceled(); + final Collection references = referenceMap.get(method); boolean areAllReferencesSynchronized = true; for (PsiReference reference : references) { + ProgressManager.checkCanceled(); if (isKnownToBeUsed(reference)) { if (isInKnownUnsynchronizedContext(reference)) { methodsNotAlwaysSynchronized.add(method); @@ -242,13 +245,16 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { new HashSet(privateMethods); boolean stabilized = false; while (!stabilized) { + ProgressManager.checkCanceled(); stabilized = true; final Set methodsDeterminedThisPass = new HashSet(); for (PsiMethod method : remainingMethods) { + ProgressManager.checkCanceled(); final Collection references = referenceMap.get(method); for (PsiReference reference : references) { + ProgressManager.checkCanceled(); if (isKnownToBeUsed(reference)) { usedMethods.add(method); methodsDeterminedThisPass.add(method); @@ -266,6 +272,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { final HashMap> referenceMap = new HashMap>(); for (PsiMethod method : privateMethods) { + ProgressManager.checkCanceled(); final SearchScope scope = method.getUseScope(); final Collection references = ReferencesSearch.search(method, scope).findAll(); @@ -278,6 +285,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { final Set privateMethods = new HashSet(); final PsiMethod[] methods = aClass.getMethods(); for (PsiMethod method : methods) { + ProgressManager.checkCanceled(); if (method.hasModifierProperty(PsiModifier.PRIVATE)) { privateMethods.add(method); } From 8fbc6db3ecfc9a51bc7622f9191cde2c08af7679 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 14:17:13 +0300 Subject: [PATCH 04/27] cleanup --- .../application/impl/ApplicationImpl.java | 18 +++--- .../ig/threading/VariableAccessVisitor.java | 59 ++++++++----------- .../PyMagicLiteralReferenceSearcher.java | 22 +++---- 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 8c5255d63f3b..2080e83bd4e6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -1026,18 +1026,16 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App @Override public boolean tryRunReadAction(@NotNull Runnable action) { //if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction - boolean mustAcquire = !isReadAccessAllowed(); - - if (mustAcquire) { - assertNoPsiLock(); - if (!myLock.tryReadLock()) return false; - } - - try { + if (isReadAccessAllowed()) { action.run(); } - finally { - if (mustAcquire) { + else { + assertNoPsiLock(); + if (!myLock.tryReadLock()) return false; + try { + action.run(); + } + finally { endRead(); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java index 5002945f6035..ea828ce3822f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/VariableAccessVisitor.java @@ -34,20 +34,16 @@ import java.util.Stack; class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private final PsiClass aClass; - private final Set m_synchronizedAccesses = - new HashSet(2); - private final Set m_unsynchronizedAccesses = - new HashSet(2); - private final Set methodsAlwaysSynchronized = - new HashSet(); - private final Set methodsNotAlwaysSynchronized = - new HashSet(); - private final Set unusedMethods = new HashSet(); - private final Set usedMethods = new HashSet(); + private final Set m_synchronizedAccesses = new HashSet<>(2); + private final Set m_unsynchronizedAccesses = new HashSet<>(2); + private final Set methodsAlwaysSynchronized = new HashSet<>(); + private final Set methodsNotAlwaysSynchronized = new HashSet<>(); + private final Set unusedMethods = new HashSet<>(); + private final Set usedMethods = new HashSet<>(); private boolean m_inInitializer; private int m_inSynchronizedContextCount; - private final Stack contextStack = new Stack(); - private final Stack contextInitializerStack = new Stack(); + private final Stack contextStack = new Stack<>(); + private final Stack contextInitializerStack = new Stack<>(); private boolean privateMethodUsagesCalculated; private final boolean countGettersAndSetters; @@ -62,7 +58,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { if (!classToVisit.equals(aClass)) { contextStack.push(m_inSynchronizedContextCount); m_inSynchronizedContextCount = 0; - + contextInitializerStack.push(m_inInitializer); m_inInitializer = false; } @@ -73,7 +69,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { public void visitLambdaExpression(PsiLambdaExpression expression) { contextStack.push(m_inSynchronizedContextCount); m_inSynchronizedContextCount = 0; - + contextInitializerStack.push(m_inInitializer); m_inInitializer = false; super.visitLambdaExpression(expression); @@ -145,6 +141,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { } private static final Key CODE_BLOCK_CONTAINS_HOLDS_LOCK_CALL = Key.create("CODE_BLOCK_CONTAINS_HOLDS_LOCK_CALL"); + @Override public void visitAssertStatement(PsiAssertStatement statement) { final PsiExpression condition = statement.getAssertCondition(); @@ -199,14 +196,12 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private void determineUsageMap(HashMap> referenceMap) { - final Set remainingMethods = - new HashSet(usedMethods); + final Set remainingMethods = new HashSet<>(usedMethods); boolean stabilized = false; while (!stabilized) { ProgressManager.checkCanceled(); stabilized = true; - final Set methodsDeterminedThisPass = - new HashSet(); + final Set methodsDeterminedThisPass = new HashSet<>(); for (PsiMethod method : remainingMethods) { ProgressManager.checkCanceled(); final Collection references = referenceMap.get(method); @@ -241,14 +236,12 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private void determineUsedMethods( Set privateMethods, HashMap> referenceMap) { - final Set remainingMethods = - new HashSet(privateMethods); + final Set remainingMethods = new HashSet<>(privateMethods); boolean stabilized = false; while (!stabilized) { ProgressManager.checkCanceled(); stabilized = true; - final Set methodsDeterminedThisPass = - new HashSet(); + final Set methodsDeterminedThisPass = new HashSet<>(); for (PsiMethod method : remainingMethods) { ProgressManager.checkCanceled(); final Collection references = @@ -269,20 +262,18 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private static HashMap> buildReferenceMap(Set privateMethods) { - final HashMap> referenceMap = - new HashMap>(); + final HashMap> referenceMap = new HashMap<>(); for (PsiMethod method : privateMethods) { ProgressManager.checkCanceled(); final SearchScope scope = method.getUseScope(); - final Collection references = - ReferencesSearch.search(method, scope).findAll(); + final Collection references = ReferencesSearch.search(method, scope).findAll(); referenceMap.put(method, references); } return referenceMap; } private Set findPrivateMethods() { - final Set privateMethods = new HashSet(); + final Set privateMethods = new HashSet<>(); final PsiMethod[] methods = aClass.getMethods(); for (PsiMethod method : methods) { ProgressManager.checkCanceled(); @@ -309,8 +300,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private boolean isInKnownSynchronizedContext(PsiReference reference) { final PsiElement element = reference.getElement(); - if (PsiTreeUtil.getParentOfType(element, - PsiSynchronizedStatement.class) != null) { + if (PsiTreeUtil.getParentOfType(element, PsiSynchronizedStatement.class) != null) { return true; } final PsiMethod method = @@ -329,8 +319,7 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { private boolean isInKnownUnsynchronizedContext(PsiReference reference) { final PsiElement element = reference.getElement(); - if (PsiTreeUtil.getParentOfType(element, - PsiSynchronizedStatement.class) != null) { + if (PsiTreeUtil.getParentOfType(element, PsiSynchronizedStatement.class) != null) { return false; } final PsiMethod method = @@ -364,7 +353,9 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { @Override protected void elementFinished(@NotNull PsiElement element) { - if (element instanceof PsiField || element instanceof PsiClassInitializer || element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { + if (element instanceof PsiField || + element instanceof PsiClassInitializer || + element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { m_inInitializer = false; } if (element instanceof PsiClass && !element.equals(aClass) || element instanceof PsiLambdaExpression) { @@ -381,14 +372,14 @@ class VariableAccessVisitor extends JavaRecursiveElementWalkingVisitor { } } if (element.getUserData(CODE_BLOCK_CONTAINS_HOLDS_LOCK_CALL) != null) { - m_inSynchronizedContextCount --; + m_inSynchronizedContextCount--; element.putUserData(CODE_BLOCK_CONTAINS_HOLDS_LOCK_CALL, null); } } Set getInappropriatelyAccessedFields() { final Set out = - new HashSet(m_synchronizedAccesses); + new HashSet<>(m_synchronizedAccesses); out.retainAll(m_unsynchronizedAccesses); return out; } diff --git a/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralReferenceSearcher.java b/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralReferenceSearcher.java index 7889be4f8097..5bd9ad969f7d 100644 --- a/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralReferenceSearcher.java +++ b/python/src/com/jetbrains/python/magicLiteral/PyMagicLiteralReferenceSearcher.java @@ -15,9 +15,8 @@ */ package com.jetbrains.python.magicLiteral; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.QueryExecutorBase; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.application.Result; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; @@ -36,18 +35,15 @@ class PyMagicLiteralReferenceSearcher extends QueryExecutorBase consumer) { - new ReadAction() { - @Override - protected void run(@NotNull final Result result) throws Throwable { - final PsiElement refElement = queryParameters.getElementToSearch(); - if (PyMagicLiteralTools.isMagicLiteral(refElement)) { - final String refText = ((StringLiteralExpression)refElement).getStringValue(); - if (!StringUtil.isEmpty(refText)) { - final SearchScope searchScope = queryParameters.getEffectiveSearchScope(); - queryParameters.getOptimizer().searchWord(refText, searchScope, true, refElement); - } + ApplicationManager.getApplication().runReadAction(() -> { + final PsiElement refElement = queryParameters.getElementToSearch(); + if (PyMagicLiteralTools.isMagicLiteral(refElement)) { + final String refText = ((StringLiteralExpression)refElement).getStringValue(); + if (!StringUtil.isEmpty(refText)) { + final SearchScope searchScope = queryParameters.getEffectiveSearchScope(); + queryParameters.getOptimizer().searchWord(refText, searchScope, true, refElement); } } - }.execute(); + }); } } From 61b7847177e14d07189ce7ec5d22ddb800ba817d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 14:54:43 +0300 Subject: [PATCH 05/27] javadoc references fixed --- .../openapi/actionSystem/DataConstants.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/DataConstants.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/DataConstants.java index 7c8b01316138..5dcf68f05f52 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/DataConstants.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/DataConstants.java @@ -28,7 +28,7 @@ public interface DataConstants { /** * Returns {@link com.intellij.openapi.project.Project} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#PROJECT} instead + * @deprecated use {@link PlatformDataKeys#PROJECT} instead */ String PROJECT = CommonDataKeys.PROJECT.getName(); @@ -42,42 +42,42 @@ public interface DataConstants { /** * Returns {@link com.intellij.openapi.vfs.VirtualFile} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#VIRTUAL_FILE} instead + * @deprecated use {@link PlatformDataKeys#VIRTUAL_FILE} instead */ String VIRTUAL_FILE = CommonDataKeys.VIRTUAL_FILE.getName(); /** * Returns array of {@link com.intellij.openapi.vfs.VirtualFile} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#VIRTUAL_FILE_ARRAY} instead + * @deprecated use {@link PlatformDataKeys#VIRTUAL_FILE_ARRAY} instead */ String VIRTUAL_FILE_ARRAY = CommonDataKeys.VIRTUAL_FILE_ARRAY.getName(); /** * Returns {@link com.intellij.openapi.editor.Editor} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#EDITOR} instead + * @deprecated use {@link PlatformDataKeys#EDITOR} instead */ String EDITOR = CommonDataKeys.EDITOR.getName(); /** * Returns {@link com.intellij.openapi.fileEditor.FileEditor} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#FILE_EDITOR} instead + * @deprecated use {@link PlatformDataKeys#FILE_EDITOR} instead */ String FILE_EDITOR = PlatformDataKeys.FILE_EDITOR.getName(); /** * Returns {@link com.intellij.openapi.fileEditor.OpenFileDescriptor} * - * @deprecated {@link com.intellij.openapi.actionSystem.PlatformDataKeys#NAVIGATABLE} should be used instead + * @deprecated {@link PlatformDataKeys#NAVIGATABLE} should be used instead */ @NonNls String OPEN_FILE_DESCRIPTOR = "openFileDescriptor"; /** * Returns the text of currently selected file/file revision * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKey#FILE_TEXT} instead + * @deprecated use {@link PlatformDataKeys#FILE_TEXT} instead */ String FILE_TEXT = PlatformDataKeys.FILE_TEXT.getName(); @@ -86,35 +86,35 @@ public interface DataConstants { * Boolean.FALSE if action is executed not in modal context. If context * is unknown then the value of this data constant is null. * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#IS_MODAL_CONTEXT} instead + * @deprecated use {@link PlatformDataKeys#IS_MODAL_CONTEXT} instead */ String IS_MODAL_CONTEXT = PlatformDataKeys.IS_MODAL_CONTEXT.getName(); /** * Returns {@link com.intellij.openapi.diff.DiffViewer} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#DIFF_VIEWER} instead + * @deprecated use {@link PlatformDataKeys#DIFF_VIEWER} instead */ String DIFF_VIEWER = PlatformDataKeys.DIFF_VIEWER.getName(); /** * Returns help id (String) * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#HELP_ID} instead + * @deprecated use {@link PlatformDataKeys#HELP_ID} instead */ String HELP_ID = PlatformDataKeys.HELP_ID.getName(); /** * Returns project if project node is selected (in project view) * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#PROJECT_CONTEXT} instead + * @deprecated use {@link PlatformDataKeys#PROJECT_CONTEXT} instead */ String PROJECT_CONTEXT = PlatformDataKeys.PROJECT_CONTEXT.getName(); /** * Returns module if module node is selected (in module view) * - * @deprecated use {@link com.intellij.openapi.actionSystem.LangDataKeys.MODULE_CONTEXT} instead + * @deprecated use {@link com.intellij.openapi.actionSystem.LangDataKeys#MODULE_CONTEXT} instead */ @NonNls String MODULE_CONTEXT = "context.Module"; @@ -126,49 +126,49 @@ public interface DataConstants { /** * Returns {@link com.intellij.pom.Navigatable} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#NAVIGATABLE} instead + * @deprecated use {@link PlatformDataKeys#NAVIGATABLE} instead */ String NAVIGATABLE = CommonDataKeys.NAVIGATABLE.getName(); /** * Returns an array of {@link com.intellij.pom.Navigatable} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#NAVIGATABLE_ARRAY} instead + * @deprecated use {@link PlatformDataKeys#NAVIGATABLE_ARRAY} instead */ String NAVIGATABLE_ARRAY = CommonDataKeys.NAVIGATABLE_ARRAY.getName(); /** * Returns {@link com.intellij.ide.ExporterToTextFile} * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#EXPORTER_TO_TEXT_FILE} instead + * @deprecated use {@link PlatformDataKeys#EXPORTER_TO_TEXT_FILE} instead */ String EXPORTER_TO_TEXT_FILE = PlatformDataKeys.EXPORTER_TO_TEXT_FILE.getName(); /** * Returns {@link com.intellij.psi.PsiElement} * - * @deprecated use {@link com.intellij.openapi.actionSystem.LangDataKeys#PSI_ELEMENT} instead + * @deprecated use {@link CommonDataKeys#PSI_ELEMENT} instead */ @NonNls String PSI_ELEMENT = "psi.Element"; /** * Returns {@link com.intellij.psi.PsiFile} * - * @deprecated use {@link com.intellij.openapi.actionSystem.com.intellij.openapi.actionSystem.CommonDataKeys.PSI_FILE} instead + * @deprecated use {@link CommonDataKeys#PSI_FILE} instead */ @NonNls String PSI_FILE = "psi.File"; /** * Returns {@link com.intellij.lang.Language} * - * @deprecated use {@link com.intellij.openapi.actionSystem.LangDataKeys.LANGUAGE} instead + * @deprecated use {@link com.intellij.openapi.actionSystem.LangDataKeys#LANGUAGE} instead */ @NonNls String LANGUAGE = "Language"; /** * Returns java.awt.Component currently in focus, DataContext should be retrieved for * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#CONTEXT_COMPONENT} instead + * @deprecated use {@link PlatformDataKeys#CONTEXT_COMPONENT} instead */ String CONTEXT_COMPONENT = PlatformDataKeys.CONTEXT_COMPONENT.getName(); @@ -206,45 +206,45 @@ public interface DataConstants { /** * Returns com.intellij.ide.CopyProvider * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#COPY_PROVIDER} instead + * @deprecated use {@link PlatformDataKeys#COPY_PROVIDER} instead */ String COPY_PROVIDER = PlatformDataKeys.COPY_PROVIDER.getName(); /** * Returns com.intellij.ide.CutProvider * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#CUT_PROVIDER} instead + * @deprecated use {@link PlatformDataKeys#CUT_PROVIDER} instead */ String CUT_PROVIDER = PlatformDataKeys.CUT_PROVIDER.getName(); /** * Returns com.intellij.ide.PasteProvider * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#PASTE_PROVIDER} instead + * @deprecated use {@link PlatformDataKeys#PASTE_PROVIDER} instead */ String PASTE_PROVIDER = PlatformDataKeys.PASTE_PROVIDER.getName(); /** * Returns com.intellij.ide.DeleteProvider * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#DELETE_ELEMENT_PROVIDER} instead + * @deprecated use {@link PlatformDataKeys#DELETE_ELEMENT_PROVIDER} instead */ String DELETE_ELEMENT_PROVIDER = PlatformDataKeys.DELETE_ELEMENT_PROVIDER.getName(); /** * Returns com.intellij.openapi.editor.Editor even if focuses currently is in find bar * - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#EDITOR} instead + * @deprecated use {@link PlatformDataKeys#EDITOR} instead */ String EDITOR_EVEN_IF_INACTIVE = CommonDataKeys.EDITOR_EVEN_IF_INACTIVE.getName(); /** - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#SELECTED_ITEM} instead + * @deprecated use {@link PlatformDataKeys#SELECTED_ITEM} instead */ String SELECTED_ITEM = PlatformDataKeys.SELECTED_ITEM.getName(); /** - * @deprecated use {@link com.intellij.openapi.actionSystem.PlatformDataKeys#DOMINANT_HINT_AREA_RECTANGLE} instead + * @deprecated use {@link PlatformDataKeys#DOMINANT_HINT_AREA_RECTANGLE} instead */ String DOMINANT_HINT_AREA_RECTANGLE = PlatformDataKeys.DOMINANT_HINT_AREA_RECTANGLE.getName(); } From 06417af4b4492ee9c132a3e2c62303eec1e058f2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 16:09:23 +0300 Subject: [PATCH 06/27] do not lose information about write action caller --- .../src/com/intellij/openapi/project/DumbServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index f6abe730fb68..363d15bf8faf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -293,7 +293,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica private void queueUpdateFinished(boolean modal) { if (myUpdateFinishedQueued) return; myUpdateFinishedQueued = true; - TransactionGuard.submitTransaction(myProject, () -> WriteAction.run(() -> updateFinished(modal))); + TransactionGuard.submitTransaction(myProject, () -> ApplicationManager.getApplication().runWriteAction(() -> updateFinished(modal))); } private void updateFinished(boolean modal) { From 5cab61669f9c4484cd7046d2e6b09a44ce0ed8b8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 16:21:18 +0300 Subject: [PATCH 07/27] dump threads in case of missed PCE --- .../impl/DaemonRespondToChangesTest.java | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java index 3ef8541e46e4..d3842322fa7e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java @@ -58,10 +58,7 @@ import com.intellij.lang.annotation.ExternalAnnotator; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DataConstants; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; @@ -144,6 +141,7 @@ import java.util.concurrent.atomic.AtomicReference; /** * @author cdr */ +@SuppressWarnings("StringConcatenationInsideStringBufferAppend") @SkipSlowTestLocally public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/typing/"; @@ -677,7 +675,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { assertEquals("Variable 'e' is already defined in the scope", error.getDescription()); PsiElement element = getFile().findElementAt(getEditor().getCaretModel().getOffset()).getParent(); - DataContext dataContext = SimpleDataContext.getSimpleContext(DataConstants.PSI_ELEMENT, element, ((EditorEx)getEditor()).getDataContext()); + DataContext dataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.getName(), element, ((EditorEx)getEditor()).getDataContext()); new InlineRefactoringActionHandler().invoke(getProject(), getEditor(), getFile(), dataContext); Collection afterTyping = highlightErrors(); @@ -1608,22 +1606,13 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { } continue; } - long now = System.currentTimeMillis(); - if (now - start1 > 500) { + long elapsed = System.currentTimeMillis() - start1; + if (elapsed > 500) { // too long, see WTF - PerformanceWatcher.dumpThreadsToConsole("Too long interrupt: " + - (now - start1) + - "; Progress canceled=" + - progress.isCanceled() + - "\n----------------------------"); - System.err.println("----all threads---"); - for (Thread thread : Thread.getAllStackTraces().keySet()) { - boolean canceled = CoreProgressManager.isCanceledThread(thread); - if (canceled) { - System.err.println("Thread " + thread + " is canceled"); - } - } - System.err.println("----///////---"); + String message = "Too long interrupt: " + elapsed + + "; Progress: " + progress + + "\n----------------------------"; + dumpThreadsToConsole(message); break; } } @@ -1648,9 +1637,13 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { CodeInsightTestFixtureImpl.ensureIndexesUpToDate(project); TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + long hiStart = System.currentTimeMillis(); codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, ArrayUtil.EMPTY_INT_ARRAY, false, interrupt); + long hiEnd = System.currentTimeMillis(); DaemonProgressIndicator progress = codeAnalyzer.getUpdateProgress(); - throw new RuntimeException("should have been interrupted: "+progress); + String message = "Should have been interrupted: " + progress + "; Elapsed: " + (hiEnd - hiStart) + "ms; Thread dump:\n"; + dumpThreadsToConsole(message); + throw new RuntimeException(message); } catch (ProcessCanceledException ignored) { } @@ -1664,6 +1657,18 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { } } + private static void dumpThreadsToConsole(@NotNull String message) { + PerformanceWatcher.dumpThreadsToConsole(message); + System.err.println("----all threads---"); + for (Thread thread : Thread.getAllStackTraces().keySet()) { + boolean canceled = CoreProgressManager.isCanceledThread(thread); + if (canceled) { + System.err.println("Thread " + thread + " indicator is canceled"); + } + } + System.err.println("----///////---"); + } + public void testTypingLatencyPerformance() throws Throwable { @NonNls String filePath = "/psi/resolve/ThinletBig.java"; From c6798d330efa33b49232352cfd7589a1defc8373 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 18:18:50 +0300 Subject: [PATCH 08/27] made more inlinable --- platform/util/src/com/intellij/openapi/util/TextRange.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/TextRange.java b/platform/util/src/com/intellij/openapi/util/TextRange.java index e3cfceb31e35..e051f77ed66f 100644 --- a/platform/util/src/com/intellij/openapi/util/TextRange.java +++ b/platform/util/src/com/intellij/openapi/util/TextRange.java @@ -218,11 +218,8 @@ public class TextRange implements Segment, Serializable { } public static void assertProperRange(int startOffset, int endOffset, @NotNull Object message) { - if (startOffset > endOffset) { + if (startOffset > endOffset || startOffset < 0) { LOG.error("Invalid range specified: (" + startOffset + "," + endOffset + "); " + message); } - if (startOffset < 0) { - LOG.error("Negative start offset: (" + startOffset + "," + endOffset + "); " + message); - } } } From 78fc8599e6eff98bfd1b84d52980524fb32200bb Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 19:22:23 +0300 Subject: [PATCH 09/27] testonly --- .../codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index b2c2a9435881..9a5f9f01b017 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -416,6 +416,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers } } + @TestOnly private boolean waitInOtherThread(int millis, boolean canChangeDocument) throws Throwable { Disposable disposable = Disposer.newDisposable(); // last hope protection against PsiModificationTrackerImpl.incCounter() craziness (yes, Kotlin) @@ -461,6 +462,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers } } + @TestOnly void waitForTermination() { myPassExecutorService.cancelAll(true); } @@ -960,6 +962,7 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers return myEditorTracker.getActiveEditors(); } + @TestOnly private static void wrap(@NotNull ThrowableRunnable runnable) { try { runnable.run(); From 2ea1283a3299fa4c5aac2d375d66a57a91f6b12a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 12 Jul 2016 20:02:45 +0300 Subject: [PATCH 10/27] print thread dump on too long interrupt --- .../impl/DaemonRespondToChangesTest.java | 97 +++++++++---------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java index d3842322fa7e..bbfd0dee6e69 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/DaemonRespondToChangesTest.java @@ -1578,57 +1578,37 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { int N = Math.max(5, Timings.adjustAccordingToMySpeed(80, true)); System.out.println("N = " + N); final long[] interruptTimes = new long[N]; - List watchers = new ArrayList<>(); for (int i = 0; i < N; i++) { codeAnalyzer.restart(); final int finalI = i; final long start = System.currentTimeMillis(); - Runnable interrupt = () -> { - long now = System.currentTimeMillis(); - if (now - start < 100) { - // wait to engage all highlighting threads - return; - } - final AtomicLong typingStart = new AtomicLong(); - final DaemonProgressIndicator progress = codeAnalyzer.getUpdateProgress(); - Thread watcher = new Thread("reactivity watcher") { - @Override - public void run() { - while (true) { - final long start1 = typingStart.get(); - if (start1 == -1) break; - if (start1 == 0) { - try { - Thread.sleep(5); - } - catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - continue; + final AtomicLong typingStart = new AtomicLong(); + Thread watcher = new Thread("reactivity watcher") { + @Override + public void run() { + while (true) { + final long start1 = typingStart.get(); + if (start1 == -1) break; + if (start1 == 0) { + try { + Thread.sleep(5); } - long elapsed = System.currentTimeMillis() - start1; - if (elapsed > 500) { - // too long, see WTF - String message = "Too long interrupt: " + elapsed + - "; Progress: " + progress + - "\n----------------------------"; - dumpThreadsToConsole(message); - break; + catch (InterruptedException e1) { + throw new RuntimeException(e1); } + continue; + } + long elapsed = System.currentTimeMillis() - start1; + if (elapsed > 500) { + // too long, see WTF + String message = "Too long interrupt: " + elapsed + + "; Progress: " + codeAnalyzer.getUpdateProgress() + + "\n----------------------------"; + dumpThreadsToConsole(); + throw new RuntimeException(message); } } - }; - watcher.start(); - watchers.add(watcher); - typingStart.set(System.currentTimeMillis()); - type(' '); - typingStart.set(-1); - long end = System.currentTimeMillis(); - long interruptTime = end - now; - interruptTimes[finalI] = interruptTime; - assertNull(codeAnalyzer.getUpdateProgress()); - System.out.println(interruptTime); - throw new ProcessCanceledException(); + } }; try { PsiFile file = getFile(); @@ -1637,28 +1617,45 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase { CodeInsightTestFixtureImpl.ensureIndexesUpToDate(project); TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + watcher.start(); + Runnable interrupt = () -> { + long now = System.currentTimeMillis(); + if (now - start < 100) { + // wait to engage all highlighting threads + return; + } + typingStart.set(System.currentTimeMillis()); + type(' '); + long end = System.currentTimeMillis(); + long interruptTime = end - now; + interruptTimes[finalI] = interruptTime; + assertNull(codeAnalyzer.getUpdateProgress()); + System.out.println(interruptTime); + throw new ProcessCanceledException(); + }; long hiStart = System.currentTimeMillis(); codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, ArrayUtil.EMPTY_INT_ARRAY, false, interrupt); long hiEnd = System.currentTimeMillis(); DaemonProgressIndicator progress = codeAnalyzer.getUpdateProgress(); - String message = "Should have been interrupted: " + progress + "; Elapsed: " + (hiEnd - hiStart) + "ms; Thread dump:\n"; - dumpThreadsToConsole(message); + String message = "Should have been interrupted: " + progress + "; Elapsed: " + (hiEnd - hiStart) + "ms"; + dumpThreadsToConsole(); throw new RuntimeException(message); } catch (ProcessCanceledException ignored) { } + finally { + typingStart.set(-1); // cancel watcher + watcher.join(); + } } long ave = ArrayUtil.averageAmongMedians(interruptTimes, 3); System.out.println("Average among the N/3 median times: " + ave + "ms"); assertTrue(ave < 300); - for (Thread watcher : watchers) { - watcher.join(); - } } - private static void dumpThreadsToConsole(@NotNull String message) { - PerformanceWatcher.dumpThreadsToConsole(message); + private static void dumpThreadsToConsole() { + PerformanceWatcher.dumpThreadsToConsole(""); System.err.println("----all threads---"); for (Thread thread : Thread.getAllStackTraces().keySet()) { boolean canceled = CoreProgressManager.isCanceledThread(thread); From 8ab23b5813bdf635525b0ce5c239b4500e706dc3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 13:09:33 +0300 Subject: [PATCH 11/27] migrate to afterWriteActionFinished listener --- .../application/ApplicationAdapter.java | 1 + .../psi/impl/DocumentCommitThread.java | 25 +++---------------- .../openapi/vcs/ex/LineStatusTracker.java | 14 ++--------- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/application/ApplicationAdapter.java b/platform/core-api/src/com/intellij/openapi/application/ApplicationAdapter.java index 17fffb76466c..3497d6ec8c3e 100644 --- a/platform/core-api/src/com/intellij/openapi/application/ApplicationAdapter.java +++ b/platform/core-api/src/com/intellij/openapi/application/ApplicationAdapter.java @@ -39,6 +39,7 @@ public abstract class ApplicationAdapter implements ApplicationListener { public void writeActionFinished(@NotNull Object action) { } + @Override public void afterWriteActionFinished(@NotNull Object action) { } } \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 0a069a9ca0c8..f4a77ecc2759 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.impl; -import com.intellij.diagnostic.ThreadDumper; import com.intellij.lang.ASTNode; import com.intellij.lang.FileASTNode; import com.intellij.openapi.Disposable; @@ -86,7 +85,6 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi private volatile boolean isDisposed; private CommitTask currentTask; // guarded by lock private boolean myEnabled; // true if we can do commits. set to false temporarily during the write action. guarded by lock - private int runningWriteActions; // accessed in EDT only public static DocumentCommitThread getInstance() { return (DocumentCommitThread)ServiceManager.getService(DocumentCommitProcessor.class); @@ -97,33 +95,18 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi application.invokeLater(new Runnable() { @Override public void run() { - assert runningWriteActions == 0; if (application.isDisposed()) return; assert !application.isWriteAccessAllowed() || application.isUnitTestMode(); // crazy stuff happens in tests, e.g. UIUtil.dispatchInvocationEvents() inside write action application.addApplicationListener(new ApplicationAdapter() { @Override public void beforeWriteActionStart(@NotNull Object action) { - int writeActionsBefore = runningWriteActions++; - if (writeActionsBefore == 0) { - disable("Write action started: " + action); - } + disable("Write action started: " + action); } @Override - public void writeActionFinished(@NotNull Object action) { + public void afterWriteActionFinished(@NotNull Object action) { // crazy things happen when running tests, like starting write action in one thread but firing its end in the other - int writeActionsAfter = runningWriteActions = Math.max(0,runningWriteActions-1); - if (writeActionsAfter == 0) { - enable("Write action finished: " + action); - } - else { - if (writeActionsAfter < 0) { - System.err.println("mismatched listeners: " + writeActionsAfter + ";\n==== log==="+log+"\n====end log==="+ - ";\n=======threaddump====\n" + - ThreadDumper.dumpThreadsToString()+"\n=====END threaddump======="); - assert false; - } - } + enable("Write action finished: " + action); } }, DocumentCommitThread.this); @@ -685,7 +668,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi @Override public String toString() { - return "Document commit thread; application: "+myApplication+"; isDisposed: "+isDisposed+"; myEnabled: "+isEnabled()+"; runningWriteActions: "+runningWriteActions; + return "Document commit thread; application: "+myApplication+"; isDisposed: "+isDisposed+"; myEnabled: "+isEnabled(); } @TestOnly diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index d59a9fc01efe..5b3305efda8a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -401,19 +401,9 @@ public class LineStatusTracker { } private class MyApplicationListener extends ApplicationAdapter { - private int myWriteActionDepth = 0; - @Override - public void writeActionStarted(@NotNull Object action) { - myWriteActionDepth++; - } - - @Override - public void writeActionFinished(@NotNull Object action) { - myWriteActionDepth = Math.max(myWriteActionDepth - 1, 0); - if (myWriteActionDepth == 0) { - updateRanges(); - } + public void afterWriteActionFinished(@NotNull Object action) { + updateRanges(); } } From 071319f47a136e017327b7369c4b7863183218fe Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 13:10:31 +0300 Subject: [PATCH 12/27] performance when using rainbow highlighter --- .../codeInsight/daemon/impl/HighlightInfo.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index a4d074d00a0c..d7d0c2df34bd 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -183,21 +183,16 @@ public class HighlightInfo implements Segment { TextAttributes attributes = getAttributesByType(element, type, colorsScheme); if (element != null && RainbowHighlighter.isRainbowEnabled() && - !isByPass(element) && isLikeVariable(type.getAttributesKey())) { - String text = element.getContainingFile().getText(); - String name = text.substring(startOffset, endOffset); - attributes = new RainbowHighlighter(colorsScheme).getAttributes(name, attributes); + PsiFile containingFile = element.getContainingFile(); + if (!RainbowVisitor.existsPassSuitableForFile(containingFile)) { + CharSequence text = containingFile.getViewProvider().getContents().subSequence(startOffset, endOffset); + attributes = new RainbowHighlighter(colorsScheme).getAttributes(text.toString(), attributes); + } } return attributes; } - @Contract("null -> false") - public static boolean isByPass(@Nullable PsiElement element) { - return element != null - && RainbowVisitor.existsPassSuitableForFile(element.getContainingFile()); - } - @Contract("null -> false") private static boolean isLikeVariable(TextAttributesKey key) { if (key == null) return false; From 22b9b89f2b138b594cced165090c967fd8b7db12 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 13:16:09 +0300 Subject: [PATCH 13/27] less memory for action update/write action statistics --- .../openapi/actionSystem/ex/ActionUtil.java | 8 +- .../application/impl/ApplicationImpl.java | 2 +- .../testFramework/src/_LastInSuiteTest.java | 2 +- .../src/com/intellij/util/PausesStat.java | 55 +++-- .../containers/UnsignedShortArrayList.java | 226 ++++++++++++++++++ 5 files changed, 262 insertions(+), 31 deletions(-) create mode 100644 platform/util/src/com/intellij/util/containers/UnsignedShortArrayList.java diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java index c2029184e88e..b9c6d959b481 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java @@ -88,7 +88,6 @@ public class ActionUtil { + " not available while " + ApplicationNamesInfo.getInstance().getProductName() + " is updating indices"; } - public static final PausesStat ACTION_UPDATE_PAUSES = new PausesStat("AnAction.update()"); private static int insidePerformDumbAwareUpdate; /** * @param action action @@ -113,7 +112,7 @@ public class ActionUtil { final boolean notAllowed = dumbMode && !action.isDumbAware(); if (insidePerformDumbAwareUpdate++ == 0) { - ACTION_UPDATE_PAUSES.started(); + ActionPauses.STAT.started(); } try { if (beforeActionPerformed) { @@ -133,7 +132,7 @@ public class ActionUtil { } finally { if (--insidePerformDumbAwareUpdate == 0) { - ACTION_UPDATE_PAUSES.finished(presentation.getText()+" action update ("+action.getClass()+")"); + ActionPauses.STAT.finished(presentation.getText() + " action update (" + action.getClass() + ")"); } if (notAllowed) { if (wasEnabledBefore == null) { @@ -145,6 +144,9 @@ public class ActionUtil { return false; } + public static class ActionPauses { + public static final PausesStat STAT = new PausesStat("AnAction.update()"); + } /** * @return whether a dumb mode is in progress for the passed project or, if the argument is null, for any open project. diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 2080e83bd4e6..fd5dde976fce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -488,7 +488,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App if (gatherStatistics) { //noinspection TestOnlyProblems LOG.info(writeActionStatistics()); - LOG.info(ActionUtil.ACTION_UPDATE_PAUSES.statistics()); + LOG.info(ActionUtil.ActionPauses.STAT.statistics()); //noinspection TestOnlyProblems LOG.info(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics() + "; ProcessIOExecutorService threads: "+((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter() diff --git a/platform/testFramework/src/_LastInSuiteTest.java b/platform/testFramework/src/_LastInSuiteTest.java index 91c3726d5f8e..989bc325ccd4 100644 --- a/platform/testFramework/src/_LastInSuiteTest.java +++ b/platform/testFramework/src/_LastInSuiteTest.java @@ -54,7 +54,7 @@ public class _LastInSuiteTest extends TestCase { PlatformTestUtil.cleanupAllProjects(); ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication(); System.out.println(application.writeActionStatistics()); - System.out.println(ActionUtil.ACTION_UPDATE_PAUSES.statistics()); + System.out.println(ActionUtil.ActionPauses.STAT.statistics()); System.out.println(((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).statistics()); System.out.println("ProcessIOExecutorService threads created: "+((ProcessIOExecutorService)ProcessIOExecutorService.INSTANCE).getThreadCounter()); diff --git a/platform/util/src/com/intellij/util/PausesStat.java b/platform/util/src/com/intellij/util/PausesStat.java index 20ab5bfd86db..fbd15c980320 100644 --- a/platform/util/src/com/intellij/util/PausesStat.java +++ b/platform/util/src/com/intellij/util/PausesStat.java @@ -15,16 +15,19 @@ */ package com.intellij.util; -import gnu.trove.TIntArrayList; +import com.intellij.util.containers.UnsignedShortArrayList; import org.jetbrains.annotations.NotNull; +import java.awt.*; + public class PausesStat { - private static final int N_MAX = 200000; - // stores pairs of (timestamp of the event start), (timestamp of the event end). Timestamps are stored as diffs between System.currentTimeMillis() and epochStart. - private final TIntArrayList pauses = new TIntArrayList(); - private final long epochStart; + private static final int N_MAX = 100000; + // stores durations of the event: (timestamp of the event end) - (timestamp of the event start) in milliseconds. + private final UnsignedShortArrayList durations = new UnsignedShortArrayList(); @NotNull private final String myName; - private volatile boolean started; + private final Thread myEdtThread; + private boolean started; + private long startTimeStamp; private int maxDuration; private Object maxDurationDescription; private int totalNumberRecorded; @@ -32,51 +35,51 @@ public class PausesStat { public PausesStat(@NotNull String name) { myName = name; - epochStart = System.currentTimeMillis(); + assert EventQueue.isDispatchThread() : Thread.currentThread(); + myEdtThread = Thread.currentThread(); } - private int register() { - int stamp = (int)(System.currentTimeMillis() - epochStart); - if (pauses.size()/2 == N_MAX) { - pauses.set(indexToOverwrite, stamp); + private int register(int duration) { + if (durations.size() == N_MAX) { + durations.set(indexToOverwrite, duration); indexToOverwrite = (indexToOverwrite + 1) % N_MAX; } else { - pauses.add(stamp); + durations.add(duration); } - return stamp; + return duration; } public void started() { + assertEdt(); assert !started; - register(); started = true; + startTimeStamp = System.currentTimeMillis(); + } + + private void assertEdt() { + assert Thread.currentThread() == myEdtThread : Thread.currentThread(); } public void finished(@NotNull String description) { + assertEdt(); assert started; - int startStamp = pauses.get(pauses.size()/2 == N_MAX ? indexToOverwrite-1 : pauses.size() - 1); - int finishStamp = register(); - int duration = finishStamp - startStamp; + long finishStamp = System.currentTimeMillis(); + int duration = (int)(finishStamp - startTimeStamp); started = false; + duration = Math.min(duration, (1 << 16) - 1); if (duration > maxDuration) { maxDuration = duration; maxDurationDescription = description; } totalNumberRecorded++; + register(duration); } public String statistics() { int total = 0; - int number = pauses.size() / 2; - int[] duration = new int[number]; - for (int i = 0; i < number*2; i+=2) { - int start = pauses.get(i); - int finish = pauses.get(i+1); - int thisDuration = finish - start; - total += thisDuration; - duration[i / 2] = thisDuration; - } + int number = durations.size(); + int[] duration = durations.toArray(); return myName + " Statistics" + (totalNumberRecorded == number ? "" : " ("+totalNumberRecorded+" events was recorded in total, but only last "+number+" are reported here)")+":"+ "\nEvent number: " + number + diff --git a/platform/util/src/com/intellij/util/containers/UnsignedShortArrayList.java b/platform/util/src/com/intellij/util/containers/UnsignedShortArrayList.java new file mode 100644 index 000000000000..df67fb86d92c --- /dev/null +++ b/platform/util/src/com/intellij/util/containers/UnsignedShortArrayList.java @@ -0,0 +1,226 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.containers; + +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; + +public class UnsignedShortArrayList implements Cloneable { + private char[] myData; // use char as an unsigned short + private int mySize; + + public UnsignedShortArrayList(int initialCapacity) { + myData = new char[initialCapacity]; + } + + public UnsignedShortArrayList() { + this(10); + } + + public void trimToSize() { + if (mySize < myData.length){ + myData = ArrayUtil.realloc(myData, mySize); + } + } + + public void ensureCapacity(int minCapacity) { + int oldCapacity = myData.length; + if (minCapacity > oldCapacity){ + char[] oldData = myData; + int newCapacity = oldCapacity * 3 / 2 + 1; + if (newCapacity < minCapacity){ + newCapacity = minCapacity; + } + myData = new char[newCapacity]; + System.arraycopy(oldData, 0, myData, 0, mySize); + } + } + + public void fill(int fromIndex, int toIndex, int value) { + assertShort(value); + if (toIndex > mySize) { + ensureCapacity(toIndex); + mySize = toIndex; + } + Arrays.fill(myData, fromIndex, toIndex, (char)value); + } + + public int size() { + return mySize; + } + + public boolean isEmpty() { + return mySize == 0; + } + + public boolean contains(int element) { + assertShort(element); + return indexOf(element) >= 0; + } + + public int indexOf(int element) { + assertShort(element); + return indexOf(element, 0, mySize); + } + + public int indexOf(int element, int startIndex, int endIndex) { + assertShort(element); + + if (startIndex < 0 || endIndex < startIndex || endIndex > mySize) { + throw new IndexOutOfBoundsException("startIndex: "+startIndex+"; endIndex: "+endIndex+"; mySize: "+mySize); + } + for(int i = startIndex; i < endIndex; i++){ + if (element == myData[i]) return i; + } + return -1; + } + + public int lastIndexOf(int element) { + assertShort(element); + for(int i = mySize - 1; i >= 0; i--){ + if (element == myData[i]) return i; + } + return -1; + } + + @Override + public Object clone() { + try{ + UnsignedShortArrayList v = (UnsignedShortArrayList)super.clone(); + v.myData = myData.clone(); + return v; + } + catch(CloneNotSupportedException e){ + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + @NotNull + public int[] toArray() { + return toArray(0,mySize); + } + + @NotNull + public int[] toArray(@NotNull int[] a) { + if (a.length < mySize){ + a = new int[mySize]; + } + for (int i = 0; i < mySize; i++) { + char c = myData[i]; + a[i] = c; + } + + return a; + } + + @NotNull + public int[] toArray(int startIndex, int length) { + int[] result = new int[length]; + for (int i = startIndex; i < length; i++) { + char c = myData[i]; + result[i-startIndex] = c; + } + return result; + } + + public int get(int index) { + checkRange(index); + return myData[index]; + } + + public int getQuick(int index) { + return myData[index]; + } + + public int set(int index, int element) { + checkRange(index); + + int oldValue = myData[index]; + setQuick(index, element); + return oldValue; + } + public void setQuick(int index, int element) { + assertShort(element); + + myData[index] = (char)element; + } + + private static void assertShort(int element) { + assert element >= 0 && element < 1<<16 : element; + } + + public void add(int element) { + ensureCapacity(mySize + 1); + setQuick(mySize++, element); + } + + public void add(int index, int element) { + if (index > mySize || index < 0){ + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize); + } + + ensureCapacity(mySize + 1); + System.arraycopy(myData, index, myData, index + 1, mySize - index); + setQuick(index, element); + mySize++; + } + + public int remove(int index) { + checkRange(index); + + int oldValue = myData[index]; + + int numMoved = mySize - index - 1; + if (numMoved > 0){ + System.arraycopy(myData, index + 1, myData, index,numMoved); + } + mySize--; + + return oldValue; + } + + public void clear() { + mySize = 0; + } + + public void removeRange(int fromIndex, int toIndex) { + int numMoved = mySize - toIndex; + System.arraycopy(myData, toIndex, myData, fromIndex, numMoved); + mySize -= toIndex - fromIndex; + } + + public void copyRange(int fromIndex, int length, int toIndex) { + if (length < 0 || fromIndex < 0 || fromIndex + length > mySize || toIndex < 0 || toIndex + length > mySize) { + throw new IndexOutOfBoundsException("fromIndex: "+fromIndex+"; length: "+length+"; toIndex: "+toIndex+"; mySize: "+mySize); + } + System.arraycopy(myData, fromIndex, myData, toIndex, length); + } + + private void checkRange(int index) { + if (index >= mySize || index < 0){ + //noinspection HardCodedStringLiteral + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize); + } + } + + @Override + public String toString() { + return Arrays.toString(toArray()); + } +} From 5660a61c70c90737ee87f093d3ffc860b65c830a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 15:09:26 +0300 Subject: [PATCH 14/27] cleanup --- .../testFramework/src/com/intellij/TestAll.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/testFramework/src/com/intellij/TestAll.java b/platform/testFramework/src/com/intellij/TestAll.java index 18a93116e578..9e1d45db93dc 100644 --- a/platform/testFramework/src/com/intellij/TestAll.java +++ b/platform/testFramework/src/com/intellij/TestAll.java @@ -61,7 +61,7 @@ public class TestAll implements Test { private static final int CHECK_MEMORY = 8; private static final int FILTER_CLASSES = 16; - public static int ourMode = SAVE_MEMORY_SNAPSHOT /*| START_GUARD | RUN_GC | CHECK_MEMORY*/ | FILTER_CLASSES; + private static final int ourMode = SAVE_MEMORY_SNAPSHOT /*| START_GUARD | RUN_GC | CHECK_MEMORY*/ | FILTER_CLASSES; private static final boolean PERFORMANCE_TESTS_ONLY = System.getProperty(TestCaseLoader.PERFORMANCE_TESTS_ONLY_FLAG) != null; private static final boolean INCLUDE_PERFORMANCE_TESTS = System.getProperty(TestCaseLoader.INCLUDE_PERFORMANCE_TESTS_FLAG) != null; @@ -106,7 +106,7 @@ public class TestAll implements Test { private int myLastTestTestMethodCount; private TestRecorder myTestRecorder; - private static List outClassLoadingProblems = new ArrayList(); + private static final List outClassLoadingProblems = new ArrayList<>(); public TestAll(String packageRoot) throws Throwable { this(packageRoot, getClassRoots()); @@ -176,7 +176,7 @@ public class TestAll implements Test { } private static Set normalizePaths(String[] array) { - Set answer = new LinkedHashSet(array.length); + Set answer = new LinkedHashSet<>(array.length); for (String path : array) { answer.add(path.replace('\\', '/')); } @@ -326,7 +326,7 @@ public class TestAll implements Test { tryGc(10); } - private TestListener loadDiscoveryListener() { + private static TestListener loadDiscoveryListener() { final String discoveryListener = System.getProperty("test.discovery.listener"); if (discoveryListener != null) { try { @@ -434,7 +434,7 @@ public class TestAll implements Test { private static boolean possibleOutOfMemory(int neededMemory) { Runtime runtime = Runtime.getRuntime(); long maxMemory = runtime.maxMemory(); - long realFreeMemory = runtime.freeMemory() + (maxMemory - runtime.totalMemory()); + long realFreeMemory = runtime.freeMemory() + maxMemory - runtime.totalMemory(); long meg = 1024 * 1024; long needed = neededMemory * meg; return realFreeMemory < needed; @@ -466,7 +466,7 @@ public class TestAll implements Test { if (TestRunnerUtil.isJUnit4TestClass(testCaseClass)) { JUnit4TestAdapter adapter = new JUnit4TestAdapter(testCaseClass); - boolean runEverything = isIncludingPerformanceTestsRun() || (isPerformanceTest(testCaseClass) && isPerformanceTestsRun()); + boolean runEverything = isIncludingPerformanceTestsRun() || isPerformanceTest(testCaseClass) && isPerformanceTestsRun(); if (!runEverything) { try { adapter.filter(isPerformanceTestsRun() ? PERFORMANCE_ONLY : NO_PERFORMANCE); @@ -573,7 +573,7 @@ public class TestAll implements Test { private static class ExplodedBomb extends TestCase { private final Bombed myBombed; - public ExplodedBomb(String testName, Bombed bombed) { + public ExplodedBomb(@NotNull String testName, @NotNull Bombed bombed) { super(testName); myBombed = bombed; } From fc111bcb1d6e853e966b4f659662663d8b887ea4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 15:10:00 +0300 Subject: [PATCH 15/27] clear parameter name --- .../LightPlatformCodeInsightTestCase.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index 72c0f7a4e44c..f336446a5be5 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -283,20 +283,20 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest /** * Validates that content of the editor as well as caret and selection matches one specified in data file that * should be formed with the same format as one used in configureByFile - * @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/ + * @param expectedFilePath - relative path from %IDEA_INSTALLATION_HOME%/testData/ */ - protected void checkResultByFile(@TestDataFile @NonNls @NotNull String filePath) { - checkResultByFile(null, filePath, false); + protected void checkResultByFile(@TestDataFile @NonNls @NotNull String expectedFilePath) { + checkResultByFile(null, expectedFilePath, false); } /** * Validates that content of the editor as well as caret and selection matches one specified in data file that * should be formed with the same format as one used in configureByFile * @param message - this check specific message. Added to text, caret position, selection checking. May be null - * @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/ + * @param expectedFilePath - relative path from %IDEA_INSTALLATION_HOME%/testData/ * @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing. */ - protected void checkResultByFile(@Nullable String message, @TestDataFile @NotNull String filePath, final boolean ignoreTrailingSpaces) { + protected void checkResultByFile(@Nullable String message, @TestDataFile @NotNull String expectedFilePath, final boolean ignoreTrailingSpaces) { bringRealEditorBack(); getProject().getComponent(PostprocessReformattingAspect.class).doPostponedFormatting(); @@ -308,26 +308,27 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); - String fullPath = getTestDataPath() + filePath; + String fullPath = getTestDataPath() + expectedFilePath; File ioFile = new File(fullPath); assertTrue(getMessage("Cannot find file " + fullPath, message), ioFile.exists()); - String fileText = null; + String fileText; try { fileText = FileUtil.loadFile(ioFile, CharsetToolkit.UTF8_CHARSET); } catch (IOException e) { LOG.error(e); + throw new RuntimeException(e); } - checkResultByText(message, StringUtil.convertLineSeparators(fileText), ignoreTrailingSpaces, getTestDataPath() + "/" + filePath); + checkResultByText(message, StringUtil.convertLineSeparators(fileText), ignoreTrailingSpaces, getTestDataPath() + "/" + expectedFilePath); } /** * Same as checkResultByFile but text is provided directly. */ - protected void checkResultByText(@NonNls @NotNull String fileText) { - checkResultByText(null, fileText, false, null); + protected void checkResultByText(@NonNls @NotNull String expectedFileText) { + checkResultByText(null, expectedFileText, false, null); } /** @@ -335,8 +336,8 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest * @param message - this check specific message. Added to text, caret position, selection checking. May be null * @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing. */ - protected void checkResultByText(final String message, @NotNull String fileText, final boolean ignoreTrailingSpaces) { - checkResultByText(message, fileText, ignoreTrailingSpaces, null); + protected void checkResultByText(final String message, @NotNull String expectedFileText, final boolean ignoreTrailingSpaces) { + checkResultByText(message, expectedFileText, ignoreTrailingSpaces, null); } /** @@ -344,11 +345,11 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest * @param message - this check specific message. Added to text, caret position, selection checking. May be null * @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing. */ - protected void checkResultByText(final String message, @NotNull final String fileText, final boolean ignoreTrailingSpaces, final String filePath) { + protected void checkResultByText(final String message, @NotNull String expectedFileText, final boolean ignoreTrailingSpaces, final String filePath) { bringRealEditorBack(); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); ApplicationManager.getApplication().runWriteAction(() -> { - final Document document = EditorFactory.getInstance().createDocument(fileText); + final Document document = EditorFactory.getInstance().createDocument(expectedFileText); if (ignoreTrailingSpaces) { ((DocumentImpl)document).stripTrailingSpaces(getProject()); From 2d07a9c5a266aab54c3e2d09779fd55695398820 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 15:47:49 +0300 Subject: [PATCH 16/27] typo --- platform/util/src/com/intellij/util/PausesStat.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/PausesStat.java b/platform/util/src/com/intellij/util/PausesStat.java index fbd15c980320..06070fa8d402 100644 --- a/platform/util/src/com/intellij/util/PausesStat.java +++ b/platform/util/src/com/intellij/util/PausesStat.java @@ -77,15 +77,18 @@ public class PausesStat { } public String statistics() { - int total = 0; int number = durations.size(); int[] duration = durations.toArray(); + int total = 0; + for (int d : duration) { + total += d; + } return myName + " Statistics" + (totalNumberRecorded == number ? "" : " ("+totalNumberRecorded+" events was recorded in total, but only last "+number+" are reported here)")+":"+ "\nEvent number: " + number + "\nTotal time spent: " + total + "ms" + "\nAverage duration: " + (number == 0 ? 0 : total / number) + "ms" + "\nMedian duration: " + ArrayUtil.averageAmongMedians(duration, 3) + "ms" + - "\nMax duration: " + maxDuration + "ms (it was '"+maxDurationDescription+"')"; + "\nMax duration: " + (maxDuration == 65535 ? ">" : "") + maxDuration+ "ms (it was '"+maxDurationDescription+"')"; } } From ec318f7f17a1e6f6fd412e2fd560f5da8c033fd5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Jul 2016 15:48:35 +0300 Subject: [PATCH 17/27] cleanup --- .../codeInsight/GenerateEquals15Test.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java index be02e9c483c4..6cff93155fd6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateEquals15Test.java @@ -17,7 +17,7 @@ package com.intellij.codeInsight; import com.intellij.codeInsight.generation.EqualsHashCodeTemplatesManager; import com.intellij.psi.PsiField; -import com.intellij.util.Function; +import com.intellij.util.Functions; /** * @author dsl @@ -28,32 +28,32 @@ public class GenerateEquals15Test extends GenerateEqualsTestCase { } public void testDifferentTypes() throws Exception { - doTest(Function.ID, Function.ID, fields -> PsiField.EMPTY_ARRAY, true + doTest(Functions.id(), Functions.id(), fields -> PsiField.EMPTY_ARRAY, true ); } public void testDifferentTypesGetters() throws Exception { - doTest(Function.ID, Function.ID, fields -> PsiField.EMPTY_ARRAY, true, true); + doTest(Functions.id(), Functions.id(), fields -> PsiField.EMPTY_ARRAY, true, true); } public void testDifferentTypesAllNotNull() throws Exception { - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } public void testDifferentTypesSuperEqualsAndHashCode() throws Exception { - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } public void testDifferentTypesNoDouble() throws Exception { - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } public void testNameConflicts() throws Exception { - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } public void testClassWithTypeParams() throws Exception { - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } public void testDifferentTypesSuperEqualsAndHashCodeApache3() throws Exception { @@ -71,7 +71,7 @@ public class GenerateEquals15Test extends GenerateEqualsTestCase { private void doTestWithTemplate(String templateName) throws Exception { try { EqualsHashCodeTemplatesManager.getInstance().setDefaultTemplate(templateName); - doTest(Function.ID, Function.ID, Function.ID, true); + doTest(Functions.id(), Functions.id(), Functions.id(), true); } finally { EqualsHashCodeTemplatesManager.getInstance().setDefaultTemplate(EqualsHashCodeTemplatesManager.INTELLI_J_DEFAULT); From 98df80b4b38ddb10c0c80ddc8f39947981f8d452 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jul 2016 12:49:15 +0300 Subject: [PATCH 18/27] notnull --- .../junit/FileComparisonFailure.java | 10 +++--- .../openapi/editor/EditorPaintingTest.java | 2 +- .../testFramework/EditorTestUtil.java | 10 +++--- .../impl/CodeInsightTestFixtureImpl.java | 1 + .../intellij/openapi/util/io/StreamUtil.java | 35 +++++++++++-------- 5 files changed, 35 insertions(+), 23 deletions(-) diff --git a/java/java-runtime/src/com/intellij/rt/execution/junit/FileComparisonFailure.java b/java/java-runtime/src/com/intellij/rt/execution/junit/FileComparisonFailure.java index b6b728192713..a540eceacad8 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/junit/FileComparisonFailure.java +++ b/java/java-runtime/src/com/intellij/rt/execution/junit/FileComparisonFailure.java @@ -25,12 +25,14 @@ public class FileComparisonFailure extends ComparisonFailure implements KnownExc private final String myFilePath; private final String myActualFilePath; - public FileComparisonFailure(String message, String expected, String actual, String filePath) { - this(message, expected, actual, filePath, null); + public FileComparisonFailure(String message, /*@NotNull */String expected, /*@NotNull */String actual, String expectedFilePath) { + this(message, expected, actual, expectedFilePath, null); } - public FileComparisonFailure(String message, String expected, String actual, String expectedFilePath, String actualFilePath) { + public FileComparisonFailure(String message, /*@NotNull */String expected, /*@NotNull */String actual, String expectedFilePath, String actualFilePath) { super(message, expected, actual); + if (expected == null) throw new NullPointerException("'expected' must not be null"); + if (actual == null) throw new NullPointerException("'actual' must not be null"); myExpected = expected; myActual = actual; myFilePath = expectedFilePath; @@ -60,7 +62,7 @@ public class FileComparisonFailure extends ComparisonFailure implements KnownExc private static class MyPacketFactory extends ComparisonDetailsExtractor { private final String myFilePath; - public MyPacketFactory(ComparisonFailure assertion, String expected, String actual, String filePath) { + MyPacketFactory(ComparisonFailure assertion, String expected, String actual, String filePath) { super(assertion, expected, actual); myFilePath = filePath; } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java index 72bcca058e93..5e4173fbb4a2 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorPaintingTest.java @@ -198,7 +198,7 @@ public class EditorPaintingTest extends AbstractEditorTest { } } - private void fail(String message, File expectedResultsFile, BufferedImage actualImage) throws IOException { + private void fail(@NotNull String message, @NotNull File expectedResultsFile, BufferedImage actualImage) throws IOException { File savedImage = FileUtil.createTempFile(getName(), ".png", false); addTmpFileToKeep(savedImage); ImageIO.write(actualImage, "png", savedImage); diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java index 33dd5fbb1aa5..5d72a50f04be 100644 --- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java @@ -251,7 +251,8 @@ public class EditorTestUtil { * * @see #extractCaretAndSelectionMarkers(Document, boolean) */ - public static CaretAndSelectionState extractCaretAndSelectionMarkers(Document document) { + @NotNull + public static CaretAndSelectionState extractCaretAndSelectionMarkers(@NotNull Document document) { return extractCaretAndSelectionMarkers(document, true); } @@ -261,7 +262,8 @@ public class EditorTestUtil { * * @param processBlockSelection if true, <block> and </block> tags describing a block selection state will also be extracted. */ - public static CaretAndSelectionState extractCaretAndSelectionMarkers(final Document document, final boolean processBlockSelection) { + @NotNull + public static CaretAndSelectionState extractCaretAndSelectionMarkers(@NotNull Document document, final boolean processBlockSelection) { return new WriteCommandAction(null) { @Override public void run(@NotNull Result actionResult) { @@ -271,9 +273,8 @@ public class EditorTestUtil { } @NotNull - public static CaretAndSelectionState extractCaretAndSelectionMarkersImpl(Document document, boolean processBlockSelection) { + public static CaretAndSelectionState extractCaretAndSelectionMarkersImpl(@NotNull Document document, boolean processBlockSelection) { List carets = ContainerUtil.newArrayList(); - TextRange blockSelection = null; String fileText = document.getText(); RangeMarker blockSelectionStartMarker = null; @@ -354,6 +355,7 @@ public class EditorTestUtil { if (carets.isEmpty()) { carets.add(new CaretInfo(null, null)); } + TextRange blockSelection = null; if (blockSelectionStartMarker != null) { blockSelection = new TextRange(blockSelectionStartMarker.getStartOffset(), blockSelectionEndMarker.getStartOffset()); } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index e96aee74fb41..4423c4b3bdc8 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -1891,6 +1891,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig private static class SelectionAndCaretMarkupLoader { private final String filePath; + @NotNull private final String newFileText; private final EditorTestUtil.CaretAndSelectionState caretState; diff --git a/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java b/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java index 319191e523dd..83b31097be7f 100644 --- a/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java @@ -25,6 +25,8 @@ import java.io.*; import java.nio.charset.Charset; public class StreamUtil { + private static final Logger LOG = Logger.getInstance(StreamUtil.class); + private StreamUtil() { } @@ -34,9 +36,8 @@ public class StreamUtil { * @param inputStream source stream * @param outputStream destination stream * @return bytes copied - * @throws IOException */ - public static int copyStreamContent(InputStream inputStream, OutputStream outputStream) throws IOException { + public static int copyStreamContent(@NotNull InputStream inputStream, @NotNull OutputStream outputStream) throws IOException { final byte[] buffer = new byte[10 * 1024]; int count; int total = 0; @@ -47,7 +48,8 @@ public class StreamUtil { return total; } - public static byte[] loadFromStream(InputStream inputStream) throws IOException { + @NotNull + public static byte[] loadFromStream(@NotNull InputStream inputStream) throws IOException { final UnsyncByteArrayOutputStream outputStream = new UnsyncByteArrayOutputStream(); try { copyStreamContent(inputStream, outputStream); @@ -61,31 +63,37 @@ public class StreamUtil { /** * @deprecated depends on the default encoding, use StreamUtil#readText(java.io.InputStream, String) instead */ - public static String readText(InputStream inputStream) throws IOException { + @NotNull + public static String readText(@NotNull InputStream inputStream) throws IOException { final byte[] data = loadFromStream(inputStream); return new String(data); } - public static String readText(InputStream inputStream, @NotNull String encoding) throws IOException { + @NotNull + public static String readText(@NotNull InputStream inputStream, @NotNull String encoding) throws IOException { final byte[] data = loadFromStream(inputStream); return new String(data, encoding); } - public static String readText(InputStream inputStream, @NotNull Charset encoding) throws IOException { + @NotNull + public static String readText(@NotNull InputStream inputStream, @NotNull Charset encoding) throws IOException { final byte[] data = loadFromStream(inputStream); return new String(data, encoding); } - public static String convertSeparators(String s) { + @NotNull + public static String convertSeparators(@NotNull String s) { return StringFactory.createShared(convertSeparators(s.toCharArray())); } - public static char[] readTextAndConvertSeparators(Reader reader) throws IOException { + @NotNull + public static char[] readTextAndConvertSeparators(@NotNull Reader reader) throws IOException { char[] buffer = readText(reader); return convertSeparators(buffer); } - private static char[] convertSeparators(char[] buffer) { + @NotNull + private static char[] convertSeparators(@NotNull char[] buffer) { int dst = 0; char prev = ' '; for (char c : buffer) { @@ -113,11 +121,13 @@ public class StreamUtil { return result; } - public static String readTextFrom(Reader reader) throws IOException { + @NotNull + public static String readTextFrom(@NotNull Reader reader) throws IOException { return StringFactory.createShared(readText(reader)); } - private static char[] readText(Reader reader) throws IOException { + @NotNull + private static char[] readText(@NotNull Reader reader) throws IOException { CharArrayWriter writer = new CharArrayWriter(); char[] buffer = new char[2048]; @@ -140,7 +150,4 @@ public class StreamUtil { } } } - - private static final Logger LOG = Logger.getInstance(StreamUtil.class); - } From 355a1253df6e2a220eccd9ccf958ec00c3722596 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jul 2016 12:52:45 +0300 Subject: [PATCH 19/27] unnecessary concurrent set --- .../openapi/progress/impl/CoreProgressManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java index a902109fe94a..5b384707cdcd 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.SmartHashSet; import com.intellij.util.io.storage.HeavyProcessLatch; import gnu.trove.THashMap; +import gnu.trove.THashSet; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,7 +63,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable { // the active indicator for the thread id private static final ConcurrentLongObjectMap currentIndicators = ContainerUtil.createConcurrentLongObjectMap(); // threads which are running under canceled indicator - static final Set threadsUnderCanceledIndicator = ContainerUtil.newConcurrentSet(); + static final Set threadsUnderCanceledIndicator = new THashSet(); // guarded by threadsUnderIndicator private static volatile boolean shouldCheckCanceled; /** active (i.e. which have {@link #executeProcessUnderProgress(Runnable, ProgressIndicator)} method running) indicators @@ -639,7 +640,9 @@ public class CoreProgressManager extends ProgressManager implements Disposable { @TestOnly public static boolean isCanceledThread(@NotNull Thread thread) { - return threadsUnderCanceledIndicator.contains(thread); + synchronized (threadsUnderIndicator) { + return threadsUnderCanceledIndicator.contains(thread); + } } @NotNull From 1bb6b56ebaed704aa9f16c3a2dba70c94cbe8073 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Jul 2016 12:53:15 +0300 Subject: [PATCH 20/27] performance --- .../com/intellij/codeHighlighting/RainbowHighlighter.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java index f31fd8494c6d..2ba41926c5b8 100644 --- a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java +++ b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java @@ -36,15 +36,10 @@ import java.util.List; import java.util.stream.Collectors; public class RainbowHighlighter { - private final float[] myFloats; @NotNull private final TextAttributesScheme myColorsScheme; public RainbowHighlighter(@Nullable TextAttributesScheme colorsScheme) { myColorsScheme = colorsScheme != null ? colorsScheme : EditorColorsManager.getInstance().getGlobalScheme(); - TextAttributes attributes = myColorsScheme.getAttributes(DefaultLanguageHighlighterColors.CONSTANT); - Color foregroundColor = attributes.getForegroundColor(); - float[] components = foregroundColor.getRGBColorComponents(null); - myFloats = Color.RGBtoHSB((int)(255 * components[0]), (int)(255 * components[0]), (int)(255 * components[0]), null); } public static final HighlightInfoType RAINBOW_ELEMENT = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT); @@ -72,7 +67,7 @@ public class RainbowHighlighter { final float colors = 36.0f; final float v = Math.round(Math.abs(colors * hash) / Integer.MAX_VALUE) / colors; - return Color.getHSBColor(v, 0.7f, myFloats[2] + .3f); + return Color.getHSBColor(v, 0.7f, .3f); } public HighlightInfo getInfo(@Nullable String nameKey, @Nullable PsiElement id, @Nullable TextAttributesKey colorKey) { From 11018ab6a93f75f75816560a7a85869926d0d4d7 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 18 Jul 2016 13:22:58 +0300 Subject: [PATCH 21/27] Revert "IDEA-157915 resolve Git symbolic-ref in HEAD" This reverts commit f57c1c02efef6ea702ce200070f93af44abe5a4c. It broke the case when ref is packed. The updated version will follow. --- .../src/git4idea/repo/GitRepositoryFiles.java | 5 ---- .../git4idea/repo/GitRepositoryReader.java | 23 +++---------------- .../repo/symbolic-refs/current-branch.txt | 2 +- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java index f77525642ffc..017d47c2889c 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java @@ -316,9 +316,4 @@ public class GitRepositoryFiles { Collection getRootDirs() { return ContainerUtil.newHashSet(myMainDir, myWorktreeDir); } - - @NotNull - File getBranchFile(@NotNull String fullBranchName) { - return file(myMainDir.getPath() + slash(fullBranchName)); - } } diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java index 236f71e4857c..d646eb7609ea 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java @@ -23,7 +23,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.LineTokenizer; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.Function; import com.intellij.util.Processor; @@ -321,14 +320,9 @@ class GitRepositoryReader { @NotNull private HeadInfo readHead() { - return readHeadInternal(myHeadFile, new ArrayList<>()); - } - - @NotNull - private HeadInfo readHeadInternal(@NotNull File headFile, @NotNull List alreadyVisited) { String headContent; try { - headContent = DvcsUtil.tryLoadFile(headFile, CharsetToolkit.UTF8); + headContent = DvcsUtil.tryLoadFile(myHeadFile, CharsetToolkit.UTF8); } catch (RepoStateException e) { LOG.error(e); @@ -337,22 +331,11 @@ class GitRepositoryReader { Hash hash = parseHash(headContent); if (hash != null) { - if (alreadyVisited.isEmpty()) { - return new HeadInfo(false, headContent); - } else { - return new HeadInfo(true, ContainerUtil.getLastItem(alreadyVisited)); - } + return new HeadInfo(false, headContent); } String target = getTarget(headContent); if (target != null) { - if (alreadyVisited.contains(target)) { - alreadyVisited.add(target); - LOG.error(new RepoStateException("Cyclic symbolic ref in HEAD: [" + StringUtil.join(alreadyVisited, " -> ") + "]")); - return new HeadInfo(false, null); - } else { - alreadyVisited.add(target); - return readHeadInternal(myGitFiles.getBranchFile(target), alreadyVisited); - } + return new HeadInfo(true, target); } LOG.error(new RepoStateException("Invalid format of the .git/HEAD file: [" + headContent + "]")); // including "refs/tags/v1" return new HeadInfo(false, null); diff --git a/plugins/git4idea/testData/repo/symbolic-refs/current-branch.txt b/plugins/git4idea/testData/repo/symbolic-refs/current-branch.txt index c9d930435819..30e2c01a2f94 100644 --- a/plugins/git4idea/testData/repo/symbolic-refs/current-branch.txt +++ b/plugins/git4idea/testData/repo/symbolic-refs/current-branch.txt @@ -1 +1 @@ -0e1d130689bc52f140c5c374aa9cc2b8916c0ad7 master +0e1d130689bc52f140c5c374aa9cc2b8916c0ad7 master-link \ No newline at end of file From 727fdc413c86f544bef9f7ee8220ce4556885668 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 15 Jul 2016 19:01:14 +0300 Subject: [PATCH 22/27] build scripts: corrected error message about not specified library license --- .../intellij/build/impl/LibraryLicensesListGenerator.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/groovy/org/jetbrains/intellij/build/impl/LibraryLicensesListGenerator.groovy b/build/groovy/org/jetbrains/intellij/build/impl/LibraryLicensesListGenerator.groovy index a7b3073da7db..bc625a824b11 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/LibraryLicensesListGenerator.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/LibraryLicensesListGenerator.groovy @@ -133,7 +133,7 @@ class LibraryLicensesListGenerator { errorMessage << "Licenses aren't specified for ${withoutLicenses.size()} libraries:" withoutLicenses.sort(true, String.CASE_INSENSITIVE_ORDER) withoutLicenses.each { errorMessage << it } - errorMessage << "If a library is packaged into IDEA installation information about its license must be added to libLicenses.gant file" + errorMessage << "If a library is packaged into IDEA installation information about its license must be added into one of *LibraryLicenses.groovy files" errorMessage << "If a library is used in tests only change its scope to 'Test'" errorMessage << "If a library is used for compilation only change its scope to 'Provided'" projectBuilder.error(errorMessage.join("\n")) From 831e338de16357a2b30aa4ff52b32002122f2fc9 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 18 Jul 2016 13:43:59 +0300 Subject: [PATCH 23/27] xdebugger: method WatchesRootNode::getAllChildren restored to fix API compatibility --- .../xdebugger/impl/ui/tree/nodes/WatchesRootNode.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java index 17795670efba..70faf4f78617 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java @@ -88,6 +88,14 @@ public class WatchesRootNode extends XValueContainerNode { return ContainerUtil.concat(myChildren, children); } + /** + * @deprecated use {@link #getWatchChildren()} instead + */ + @NotNull + public List getAllChildren() { + return getWatchChildren(); + } + @NotNull public List getWatchChildren() { return myChildren; From b39787a164a7b6c8e99b0f2062d0db13f34c0051 Mon Sep 17 00:00:00 2001 From: Philipp Smorygo Date: Mon, 18 Jul 2016 13:20:17 +0300 Subject: [PATCH 24/27] New words in jb dictionary --- spellchecker/src/com/intellij/spellchecker/jetbrains.dic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 1813d9d8166a..22cc4d5c6aa2 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -589,6 +589,8 @@ subexpression subexpressions sublicense sublist +submodule +submodules subpackage subpackages subpartition From 127db3831eb0db0a12b7257092aa3fe445376e9d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 18 Jul 2016 14:12:26 +0200 Subject: [PATCH 25/27] fix AIOOB --- .../src/com/intellij/codeHighlighting/RainbowHighlighter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java index f31fd8494c6d..ca9a91e523a5 100644 --- a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java +++ b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java @@ -66,7 +66,7 @@ public class RainbowHighlighter { if (!registryColors.isEmpty()) { final List colors = registryColors.stream().map((s -> ColorUtil.fromHex(s.trim()))).collect(Collectors.toList()); if (!colors.isEmpty()) { - return colors.get(hash % colors.size()); + return colors.get(Math.abs(hash) % colors.size()); } } From e69b8fe9a1b3580cff33423c874fa21f59db65d9 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 18 Jul 2016 15:06:52 +0300 Subject: [PATCH 26/27] diff: move trivial implementation inside interface --- .../iterables/ChangeDiffIterableBase.java | 6 +-- .../comparison/iterables/DiffIterable.java | 8 +++- .../iterables/DiffIterableBase.java | 42 ------------------- .../iterables/FairDiffIterableWrapper.java | 2 +- .../InvertedDiffIterableWrapper.java | 2 +- 5 files changed, 11 insertions(+), 49 deletions(-) delete mode 100644 platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableBase.java diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/ChangeDiffIterableBase.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/ChangeDiffIterableBase.java index c21bbea0c563..5cb9899fbcaa 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/ChangeDiffIterableBase.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/ChangeDiffIterableBase.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; -abstract class ChangeDiffIterableBase extends DiffIterableBase { +abstract class ChangeDiffIterableBase implements DiffIterable { private final int myLength1; private final int myLength2; @@ -42,7 +42,7 @@ abstract class ChangeDiffIterableBase extends DiffIterableBase { @NotNull @Override public Iterator changes() { - return new MyIterator() { + return new Iterator() { @NotNull private final ChangeIterable myIterable = createChangeIterable(); @Override @@ -62,7 +62,7 @@ abstract class ChangeDiffIterableBase extends DiffIterableBase { @NotNull @Override public Iterator unchanged() { - return new MyIterator() { + return new Iterator() { @NotNull private final ChangeIterable myIterable = createChangeIterable(); int lastIndex1 = 0; diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterable.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterable.java index ee429e6ff60b..28f27a729b9b 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterable.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterable.java @@ -36,8 +36,12 @@ public interface DiffIterable { Iterator unchanged(); @NotNull - Iterable iterateChanges(); + default Iterable iterateChanges() { + return this::changes; + } @NotNull - Iterable iterateUnchanged(); + default Iterable iterateUnchanged() { + return this::unchanged; + } } diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableBase.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableBase.java deleted file mode 100644 index a0f882d7455a..000000000000 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableBase.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.diff.comparison.iterables; - -import com.intellij.diff.util.Range; -import org.jetbrains.annotations.NotNull; - -import java.util.Iterator; - -abstract class DiffIterableBase implements DiffIterable { - @NotNull - @Override - public Iterable iterateUnchanged() { - return this::unchanged; - } - - @NotNull - @Override - public Iterable iterateChanges() { - return this::changes; - } - - protected static abstract class MyIterator implements Iterator { - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/FairDiffIterableWrapper.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/FairDiffIterableWrapper.java index 541dd258a680..ec4c8032085f 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/FairDiffIterableWrapper.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/FairDiffIterableWrapper.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; -class FairDiffIterableWrapper extends DiffIterableBase implements FairDiffIterable { +class FairDiffIterableWrapper implements FairDiffIterable { @NotNull private final DiffIterable myIterable; public FairDiffIterableWrapper(@NotNull DiffIterable iterable) { diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/InvertedDiffIterableWrapper.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/InvertedDiffIterableWrapper.java index eb90d653ddb7..c1f5c7d2bb46 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/InvertedDiffIterableWrapper.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/InvertedDiffIterableWrapper.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; -class InvertedDiffIterableWrapper extends DiffIterableBase { +class InvertedDiffIterableWrapper implements DiffIterable { @NotNull private final DiffIterable myIterable; public InvertedDiffIterableWrapper(@NotNull DiffIterable iterable) { From 294941ab2ed0d1d3f3ee54a8d51d3130fa51d239 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Mon, 18 Jul 2016 15:11:43 +0300 Subject: [PATCH 27/27] Java inspection: Improved descriptions and messages for "Add Braces" and "Remove Braces" inspections. Test data updated. (IDEA-157727) --- .../siyeh/InspectionGadgetsBundle.properties | 4 +-- .../ControlFlowStatementWithoutBraces.html | 4 +-- .../SingleStatementInBlock.html | 1 + .../style/single_statement_block/expected.xml | 28 +++++++++---------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 86b92f43163e..d8ce66c56396 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2203,7 +2203,7 @@ replace.equality.with.equals.name=Replace Equality with Equals replace.equality.with.equals.descriptor=Replace ''{0}'' with ''{1}equals()'' replace.equality.with.safe.equals.name=Replace Equality with Safe Equals replace.equality.with.safe.equals.descriptor=Replace ''{0}'' with safe ''{1}equals()'' -single.statement.in.block.name=Code Block Contains Single Statement +single.statement.in.block.name=Code block contains single statement single.statement.in.block.descriptor=''{0}'' contains single statement single.statement.in.block.quickfix=Remove braces from ''{0}'' statement -single.statement.in.block.family.quickfix=Remove Braces From Statement \ No newline at end of file +single.statement.in.block.family.quickfix=Remove braces from statement \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ControlFlowStatementWithoutBraces.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ControlFlowStatementWithoutBraces.html index dd8eb8837735..5afff14a47b8 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/ControlFlowStatementWithoutBraces.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ControlFlowStatementWithoutBraces.html @@ -4,8 +4,6 @@ Reports any if, while or for statements without braces. Braces make the code easier to read and help prevent errors when modifying the code. - -

- +

The quick fix for the inspection wraps the statement body with braces. \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SingleStatementInBlock.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SingleStatementInBlock.html index 7ee68dfec244..4a4132a7d46f 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/SingleStatementInBlock.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SingleStatementInBlock.html @@ -2,5 +2,6 @@ This inspection reports control flow statements with only a single statement in their code block. +

The quick fix for the inspection removes braces from the statement body. diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/single_statement_block/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/single_statement_block/expected.xml index d049f6bf366a..9d1103579b2d 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/single_statement_block/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/single_statement_block/expected.xml @@ -4,98 +4,98 @@ SingleStatement.java 4 - Code Block Contains Single Statement + Code block contains single statement 'for' contains single statement SingleStatement.java 8 - Code Block Contains Single Statement + Code block contains single statement 'if' contains single statement SingleStatement.java 10 - Code Block Contains Single Statement + Code block contains single statement 'else' contains single statement SingleStatement.java 14 - Code Block Contains Single Statement + Code block contains single statement 'if' contains single statement SingleStatement.java 19 - Code Block Contains Single Statement + Code block contains single statement 'else' contains single statement SingleStatement.java 23 - Code Block Contains Single Statement + Code block contains single statement 'for' contains single statement SingleStatement.java 28 - Code Block Contains Single Statement + Code block contains single statement 'do' contains single statement SingleStatement.java 34 - Code Block Contains Single Statement + Code block contains single statement 'while' contains single statement SingleStatement.java 40 - Code Block Contains Single Statement + Code block contains single statement 'if' contains single statement SingleStatement.java 41 - Code Block Contains Single Statement + Code block contains single statement 'for' contains single statement SingleStatement.java 42 - Code Block Contains Single Statement + Code block contains single statement 'if' contains single statement SingleStatement.java 43 - Code Block Contains Single Statement + Code block contains single statement 'for' contains single statement SingleStatement.java 46 - Code Block Contains Single Statement + Code block contains single statement 'else' contains single statement SingleStatement.java 50 - Code Block Contains Single Statement + Code block contains single statement 'else' contains single statement