From 4be8892a3cf1933aee0927cf66f7681a4c88e58f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 6 Sep 2017 14:51:27 +0300 Subject: [PATCH 01/25] clear lists after dispose to conserve memory in case of leaks --- .../openapi/vfs/impl/VirtualFilePointerContainerImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java index d4315050916c..ea324d64073f 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java @@ -259,14 +259,17 @@ class VirtualFilePointerContainerImpl extends TraceableDisposable implements Vir return myList.hashCode(); } + @NotNull protected VirtualFilePointer create(@NotNull VirtualFile file) { return myVirtualFilePointerManager.create(file, myParent, myListener); } + @NotNull protected VirtualFilePointer create(@NotNull String url) { return myVirtualFilePointerManager.create(url, myParent, myListener); } + @NotNull protected VirtualFilePointer duplicate(@NotNull VirtualFilePointer virtualFilePointer) { return myVirtualFilePointerManager.duplicate(virtualFilePointer, myParent, myListener); } @@ -300,5 +303,6 @@ class VirtualFilePointerContainerImpl extends TraceableDisposable implements Vir assert !myDisposed; myDisposed = true; kill(null); + clear(); } } From da7965e5bc8847a50689443936cd1a41deb46963 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Sep 2017 13:01:04 +0300 Subject: [PATCH 02/25] changed wording to make clear index/size operations are bad --- .../util/src/com/intellij/util/containers/UnsafeWeakList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java index 385274ff1b41..0fea8964ba97 100644 --- a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java +++ b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java @@ -303,6 +303,6 @@ public class UnsafeWeakList extends AbstractList { } private T throwNotRandomAccess() { - throw new IncorrectOperationException("UnsafeWeakList is not RandomAccess, use list.iterator() instead."); + throw new IncorrectOperationException("index/size-based operations in UnsafeWeakList are not supported because they don't make sense in the presence of weak references. Use list.iterator() (which retains elements to avoid sudden GC) instead."); } } From f7d66216e73f3dc63ade3f49bb4783fa2e7494b2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Sep 2017 13:03:03 +0300 Subject: [PATCH 03/25] cleanup --- .../usages/impl/UsageViewTreeTest.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTreeTest.java b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTreeTest.java index fa1839c2f9ca..2416f18b16e1 100644 --- a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTreeTest.java +++ b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTreeTest.java @@ -46,15 +46,12 @@ public class UsageViewTreeTest extends UsefulTestCase { super.setUp(); myFixtureBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder("moduleGroups"); myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(myFixtureBuilder.getFixture()); - myDisposable = new Disposable() { - @Override - public void dispose() { - try { - myFixture.tearDown(); - } - catch (Exception e) { - throw new RuntimeException(e); - } + myDisposable = () -> { + try { + myFixture.tearDown(); + } + catch (Exception e) { + throw new RuntimeException(e); } }; myFixture.setUp(); @@ -72,7 +69,7 @@ public class UsageViewTreeTest extends UsefulTestCase { public void testSimpleModule() throws Exception { addModule("main"); PsiFile file = myFixture.addFileToProject("main/A.txt", "hello"); - Usage[] usages = new Usage[] {new UsageInfo2UsageAdapter(new UsageInfo(file))}; + Usage[] usages = {new UsageInfo2UsageAdapter(new UsageInfo(file))}; assertUsageViewStructureEquals(usages, "Usage (1 usage)\n" + " Non-code usages (1 usage)\n" + " main (1 usage)\n" + @@ -83,7 +80,7 @@ public class UsageViewTreeTest extends UsefulTestCase { public void testModuleWithQualifiedName() throws Exception { addModule("xxx.main"); PsiFile file = myFixture.addFileToProject("xxx.main/A.txt", "hello"); - Usage[] usages = new Usage[] {new UsageInfo2UsageAdapter(new UsageInfo(file))}; + Usage[] usages = {new UsageInfo2UsageAdapter(new UsageInfo(file))}; UsageViewSettings.getInstance().FLATTEN_MODULES = false; ModuleGroupTestsKt.runWithQualifiedModuleNamesEnabled(() -> { assertUsageViewStructureEquals(usages, "Usage (1 usage)\n" + From 1ce2d766586dfc34b2cc8258cde1cd2ada955d85 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Sep 2017 14:04:22 +0300 Subject: [PATCH 04/25] memory leaks in fixtures: remove added sdk after test finishes --- .../FileEditorManagerTestCase.java | 9 +++--- .../intellij/testFramework/PsiTestUtil.java | 30 +++++++++++++++---- .../java/decompiler/IdeaDecompilerTest.kt | 10 +++++++ .../python/pyi/PyiInspectionsTest.java | 16 +++++++++- .../com/jetbrains/python/pyi/PyiTypeTest.java | 22 ++++++++++++-- 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/FileEditorManagerTestCase.java b/platform/testFramework/src/com/intellij/testFramework/FileEditorManagerTestCase.java index c890cfc486d7..c194b71ac749 100644 --- a/platform/testFramework/src/com/intellij/testFramework/FileEditorManagerTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/FileEditorManagerTestCase.java @@ -20,6 +20,7 @@ import com.intellij.openapi.components.ExpandMacroToPathMap; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager; +import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.fileEditor.impl.FileEditorProviderManagerImpl; import com.intellij.openapi.util.Disposer; @@ -73,6 +74,9 @@ public abstract class FileEditorManagerTestCase extends LightPlatformCodeInsight myOldDockContainers = null; ((ComponentManagerImpl)getProject()).registerComponentInstance(FileEditorManager.class, myOldManager); myManager.closeAllFiles(); + for (VirtualFile file : EditorHistoryManager.getInstance(getProject()).getFiles()) { + EditorHistoryManager.getInstance(getProject()).removeFile(file); + } ((FileEditorProviderManagerImpl)FileEditorProviderManager.getInstance()).clearSelectedProviders(); } finally { @@ -82,11 +86,6 @@ public abstract class FileEditorManagerTestCase extends LightPlatformCodeInsight } } - @Override - protected boolean isWriteActionRequired() { - return false; - } - protected VirtualFile getFile(String path) { String fullPath = getTestDataPath() + path; VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(fullPath); diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java index 457b231d5737..c4d2b6f71ef4 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.testFramework; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.RunResult; @@ -34,6 +35,7 @@ import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -247,6 +249,20 @@ public class PsiTestUtil { public static void addLibrary(Module module, String libName, String libPath, String... jarArr) { ModuleRootModificationUtil.updateModel(module, model -> addLibrary(module, model, libName, libPath, jarArr)); } + public static void addLibrary(@NotNull Disposable parent, Module module, String libName, String libPath, String... jarArr) { + Ref ref = new Ref<>(); + ModuleRootModificationUtil.updateModel(module, model -> ref.set(addLibrary(module, model, libName, libPath, jarArr))); + Disposer.register(parent, () -> { + Library library = ref.get(); + ModuleRootModificationUtil.updateModel(module, model -> model.removeOrderEntry(model.findLibraryOrderEntry(library))); + WriteCommandAction.runWriteCommandAction(null, ()-> { + LibraryTable table = ProjectLibraryTable.getInstance(module.getProject()); + LibraryTable.ModifiableModel model = table.getModifiableModel(); + model.removeLibrary(library); + model.commit(); + }); + }); + } public static void addProjectLibrary(Module module, String libName, List classesRootPaths) { List roots = ContainerUtil.map(classesRootPaths, path -> VirtualFileManager.getInstance().refreshAndFindFileByUrl(VfsUtil.getUrlForLibraryRoot(new File(path)))); @@ -263,6 +279,7 @@ public class PsiTestUtil { return result.get(); } + @NotNull private static Library addProjectLibrary(Module module, ModifiableRootModel model, String libName, @@ -302,11 +319,12 @@ public class PsiTestUtil { return result.getResultObject(); } - public static void addLibrary(Module module, - ModifiableRootModel model, - String libName, - String libPath, - String... jarArr) { + @NotNull + public static Library addLibrary(Module module, + ModifiableRootModel model, + String libName, + String libPath, + String... jarArr) { List classesRoots = new ArrayList<>(); for (String jar : jarArr) { if (!libPath.endsWith("/") && !jar.startsWith("/")) { @@ -323,7 +341,7 @@ public class PsiTestUtil { assert root != null : "Library root folder not found: " + path + "!/"; classesRoots.add(root); } - addProjectLibrary(module, model, libName, classesRoots, Collections.emptyList()); + return addProjectLibrary(module, model, libName, classesRoots, Collections.emptyList()); } public static void addLibrary(Module module, diff --git a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.kt b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.kt index c44752e292d2..cf605238dd38 100644 --- a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.kt +++ b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.kt @@ -26,6 +26,8 @@ import com.intellij.ide.structureView.newStructureView.StructureViewComponent import com.intellij.ide.util.treeView.AbstractTreeNode import com.intellij.openapi.application.PluginPathManager import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx +import com.intellij.openapi.fileEditor.impl.EditorHistoryManager import com.intellij.openapi.fileTypes.StdFileTypes import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil @@ -45,6 +47,14 @@ class IdeaDecompilerTest : LightCodeInsightFixtureTestCase() { myFixture.testDataPath = "${PluginPathManager.getPluginHomePath("java-decompiler")}/plugin/testData" } + override fun tearDown() { + FileEditorManagerEx.getInstanceEx(project).closeAllFiles() + for (file in EditorHistoryManager.getInstance(project).files) { + EditorHistoryManager.getInstance(project).removeFile(file) + } + super.tearDown() + } + fun testSimple() { val file = getTestFile("${PlatformTestUtil.getRtJarPath()}!/java/lang/String.class") val decompiled = IdeaDecompiler().getText(file).toString() diff --git a/python/testSrc/com/jetbrains/python/pyi/PyiInspectionsTest.java b/python/testSrc/com/jetbrains/python/pyi/PyiInspectionsTest.java index 5b330270b4d0..99d444c0be78 100644 --- a/python/testSrc/com/jetbrains/python/pyi/PyiInspectionsTest.java +++ b/python/testSrc/com/jetbrains/python/pyi/PyiInspectionsTest.java @@ -16,6 +16,8 @@ package com.jetbrains.python.pyi; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.jetbrains.python.fixtures.PyTestCase; @@ -27,6 +29,18 @@ import org.jetbrains.annotations.NotNull; * @author vlan */ public class PyiInspectionsTest extends PyTestCase { + + private Disposable myRootsDisposable; + + @Override + protected void tearDown() throws Exception { + if (myRootsDisposable != null) { + Disposer.dispose(myRootsDisposable); + myRootsDisposable = null; + } + super.tearDown(); + } + private void doTestByExtension(@NotNull Class inspectionClass, @NotNull String extension) { doTestByFileName(inspectionClass, getTestName(false) + extension); } @@ -106,7 +120,7 @@ public class PyiInspectionsTest extends PyTestCase { } public void testPyiRelativeImports() { - PyiTypeTest.addPyiStubsToContentRoot(myFixture); + myRootsDisposable = PyiTypeTest.addPyiStubsToContentRoot(myFixture); doTestByFileName(PyUnresolvedReferencesInspection.class, "package_with_stub_in_path/a.pyi"); } } diff --git a/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java b/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java index ce6e92eb9cc9..6a8b81cc6dc7 100644 --- a/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java +++ b/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java @@ -15,8 +15,11 @@ */ package com.jetbrains.python.pyi; +import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; @@ -35,12 +38,23 @@ import org.jetbrains.annotations.Nullable; * @author vlan */ public class PyiTypeTest extends PyTestCase { - public static void addPyiStubsToContentRoot(CodeInsightTestFixture fixture) { + + private Disposable myDisposable; + + // return Disposable which undoes configuration + public static Disposable addPyiStubsToContentRoot(CodeInsightTestFixture fixture) { final String path = fixture.getTestDataPath() + "/pyi/pyiStubs"; final VirtualFile file = StandardFileSystems.local().refreshAndFindFileByPath(path); assertNotNull(file); file.refresh(false, true); ModuleRootModificationUtil.addContentRoot(fixture.getModule(), path); + return ()->ModuleRootModificationUtil.updateModel(fixture.getModule(), model -> { + for (ContentEntry entry : model.getContentEntries()) { + if (file.equals(entry.getFile())) { + model.removeContentEntry(entry); + } + } + }); } @Nullable @@ -57,6 +71,10 @@ public class PyiTypeTest extends PyTestCase { @Override public void tearDown() throws Exception { + if (myDisposable != null) { + Disposer.dispose(myDisposable); + myDisposable = null; + } setLanguageLevel(null); super.tearDown(); } @@ -97,7 +115,7 @@ public class PyiTypeTest extends PyTestCase { } public void testPyiOnPythonPath() { - addPyiStubsToContentRoot(myFixture); + myDisposable = addPyiStubsToContentRoot(myFixture); doTest("int"); } From 02fc99880c779b601a4b8c8daab55475117fbfe0 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Wed, 13 Sep 2017 14:19:37 +0300 Subject: [PATCH 05/25] build scripts: prepare dmg artifact using unique path to image. --- .../tools/mac/scripts/makedmg.pl | 5 +++-- .../tools/mac/scripts/makedmg.sh | 21 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/platform/build-scripts/tools/mac/scripts/makedmg.pl b/platform/build-scripts/tools/mac/scripts/makedmg.pl index 8a7076715ace..4c4f1c34f7c0 100644 --- a/platform/build-scripts/tools/mac/scripts/makedmg.pl +++ b/platform/build-scripts/tools/mac/scripts/makedmg.pl @@ -6,15 +6,16 @@ use Mac::Files qw( NewAliasMinimal ); $name = $ARGV[0]; $bg_pic = $ARGV[1]; +$mountName = $ARGV[2]; -&writeDSDBEntries("/Volumes/$name/.DS_Store", +&writeDSDBEntries("/Volumes/$mountName/.DS_Store", &makeEntries(".background", Iloc_xy => [ 560, 170 ]), &makeEntries(".DS_Store", Iloc_xy => [ 610, 170 ]), &makeEntries(".fseventsd", Iloc_xy => [ 660, 170 ]), &makeEntries(".Trashes", Iloc_xy => [ 710, 170 ]), &makeEntries(" ", Iloc_xy => [ 335, 120 ]), &makeEntries(".", - BKGD_alias => NewAliasMinimal("/Volumes/$name/.background/$bg_pic"), + BKGD_alias => NewAliasMinimal("/Volumes/$mountName/.background/$bg_pic"), ICVO => 1, fwi0_flds => [ 100, 400, 396, 855, "icnv", 0, 0 ], fwsw => 170, diff --git a/platform/build-scripts/tools/mac/scripts/makedmg.sh b/platform/build-scripts/tools/mac/scripts/makedmg.sh index 22ab16318398..3b91e1811aa0 100644 --- a/platform/build-scripts/tools/mac/scripts/makedmg.sh +++ b/platform/build-scripts/tools/mac/scripts/makedmg.sh @@ -37,17 +37,17 @@ echo "Creating unpacked r/w disk image ${VOLNAME}..." hdiutil create -srcfolder ./${EXPLODED} -volname "$VOLNAME" -anyowners -nospotlight -quiet -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW $2.temp.dmg # check if the image already mounted -if [ -d "/Volumes/$VOLNAME" ]; then +if [ -d "/Volumes/$1" ]; then attempt=1 limit=5 while [ $attempt -le $limit ] do - echo "/Volumes/$VOLNAME - the image is already mounted. This build will wait for unmount for 1 min (up to 5 times)." + echo "/Volumes/$1 - the image is already mounted. This build will wait for unmount for 1 min (up to 5 times)." sleep 60; let "attempt += 1" - if [ -d "/Volumes/$VOLNAME" ]; then - if [ $attempt -eq $limit ]; then - echo "/Volumes/$VOLNAME - the image is still mounted. By the reason the build will be stopped." + if [ -d "/Volumes/$1" ]; then + if [ $attempt -ge $limit ]; then + echo "/Volumes/$1 - the image is still mounted. By the reason the build will be stopped." rm -rf ${EXPLODED} rm -f $2.temp.dmg exit 1 @@ -58,16 +58,17 @@ fi # mount this image echo "Mounting unpacked r/w disk image..." -device=$(hdiutil attach -readwrite -noverify -noautoopen $2.temp.dmg | egrep '^/dev/' | sed 1q | awk '{print $1.dmg}') +device=$(hdiutil attach -readwrite -noverify -mountpoint /Volumes/"$1" -noautoopen $2.temp.dmg | egrep '^/dev/' | sed 1q | awk '{print $1.dmg}') echo "Mounted as ${device}." sleep 10 -find /Volumes/"$VOLNAME" -maxdepth 1 +find /Volumes/"$1" -maxdepth 1 # set properties echo "Updating $VOLNAME disk image styles..." -stat /Volumes/"$VOLNAME"/DSStorePlaceHolder || true -rm /Volumes/"$VOLNAME"/DSStorePlaceHolder -perl makedmg.pl "$VOLNAME" ${BG_PIC} +stat /Volumes/"$1"/DSStorePlaceHolder || true +rm /Volumes/"$1"/DSStorePlaceHolder +perl makedmg.pl "$VOLNAME" ${BG_PIC} "$1" + sync;sync;sync hdiutil detach ${device} From 4134e3af63c3f170cb2e00f7b85a510d0233efe8 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 13 Sep 2017 14:37:05 +0300 Subject: [PATCH 06/25] IDEA-175378 "Open Task" makes the whole IDE freeze when selecting a task too quickly --- .../tasks/generic/RegExResponseHandler.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java index c1147bba89e2..4f0bfaa48308 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java @@ -15,15 +15,11 @@ */ package com.intellij.tasks.generic; -import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.XmlElementFactory; -import com.intellij.psi.xml.XmlTag; import com.intellij.tasks.Task; import com.intellij.ui.EditorTextField; import com.intellij.ui.LanguageTextField; @@ -31,7 +27,6 @@ import com.intellij.ui.components.JBScrollPane; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.FormBuilder; import com.intellij.util.xmlb.annotations.Tag; -import com.intellij.xml.util.XmlUtil; import org.intellij.lang.regexp.RegExpLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -117,14 +112,6 @@ public final class RegExResponseHandler extends ResponseHandler { for (int i = 0; i < max && matcher.find(); i++) { String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1); String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1); - // temporary workaround to make AssemblaIntegrationTestPass - final String finalSummary = summary; - summary = ReadAction.compute(() -> { - XmlElementFactory factory = XmlElementFactory.getInstance(ProjectManager.getInstance().getDefaultProject()); - XmlTag text = factory.createTagFromText("" + finalSummary + ""); - String trimmedText = text.getValue().getTrimmedText(); - return XmlUtil.decode(trimmedText); - }); tasks.add(new GenericTask(id, summary, myRepository)); } return tasks.toArray(new Task[tasks.size()]); From 2de14ad5f9cf79bbfda63beb2aec8bbf41e2a6bd Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Wed, 13 Sep 2017 13:48:27 +0200 Subject: [PATCH 07/25] [groovy] extract type calculator for 'new Xxx()' expression --- .../expressions/GrNewExpressionImpl.java | 38 ++------------ .../DefaultNewExpressionTypeCalculator.kt | 52 +++++++++++++++++++ plugins/groovy/src/META-INF/plugin.xml | 2 + 3 files changed, 57 insertions(+), 35 deletions(-) create mode 100644 plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultNewExpressionTypeCalculator.kt diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java index 5a7a0a919822..b23789355b81 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -18,14 +18,11 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; -import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.util.InheritanceUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,18 +35,16 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrArrayD import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrBuiltInTypeElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnonymousClassType; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrClassReferenceType; import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrCallExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.util.GrInnerClassConstructorUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; +import org.jetbrains.plugins.groovy.lang.typing.GrTypeCalculator; import java.util.ArrayList; import java.util.List; @@ -59,33 +54,6 @@ import java.util.List; */ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewExpression { - private static final Function MY_TYPE_CALCULATOR = - (NullableFunction)newExpression -> { - final GrAnonymousClassDefinition anonymous = newExpression.getAnonymousClassDefinition(); - if (anonymous != null) { - return new GrAnonymousClassType(LanguageLevel.JDK_1_5, anonymous.getResolveScope(), - JavaPsiFacade.getInstance(newExpression.getProject()), anonymous); - } - PsiType type = null; - GrCodeReferenceElement refElement = newExpression.getReferenceElement(); - if (refElement != null) { - type = new GrClassReferenceType(refElement); - } - else { - GrBuiltInTypeElement builtin = newExpression.findChildByClass(GrBuiltInTypeElement.class); - if (builtin != null) type = builtin.getType(); - } - - if (type != null) { - for (int i = 0; i < newExpression.getArrayCount(); i++) { - type = type.createArrayType(); - } - return type; - } - - return null; - }; - private static final ResolveCache.PolyVariantResolver RESOLVER = new ResolveCache.PolyVariantResolver() { @NotNull @Override @@ -111,7 +79,7 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx @Override public PsiType getType() { - return TypeInferenceHelper.getCurrentContext().getExpressionType(this, MY_TYPE_CALCULATOR); + return TypeInferenceHelper.getCurrentContext().getExpressionType(this, GrTypeCalculator::getTypeFromCalculators); } @Override diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultNewExpressionTypeCalculator.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultNewExpressionTypeCalculator.kt new file mode 100644 index 000000000000..8d308117e97d --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultNewExpressionTypeCalculator.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2017 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 org.jetbrains.plugins.groovy.lang.typing + +import com.intellij.pom.java.LanguageLevel +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiType +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrBuiltInTypeElement +import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnonymousClassType +import org.jetbrains.plugins.groovy.lang.psi.impl.GrClassReferenceType + +class DefaultNewExpressionTypeCalculator : GrTypeCalculator { + + override fun getType(expression: GrNewExpression): PsiType? { + return getAnonymousType(expression) ?: + getRegularType(expression) + } + + private fun getAnonymousType(expression: GrNewExpression): PsiType? { + val anonymous = expression.anonymousClassDefinition ?: return null + return GrAnonymousClassType( + LanguageLevel.JDK_1_5, + anonymous.resolveScope, + JavaPsiFacade.getInstance(expression.project), + anonymous + ) + } + + private fun getRegularType(expression: GrNewExpression): PsiType? { + var type: PsiType = expression.referenceElement?.let { GrClassReferenceType(it) } ?: + (expression.typeElement as? GrBuiltInTypeElement)?.type ?: + return null + repeat(expression.arrayCount) { + type = type.createArrayType() + } + return type + } +} \ No newline at end of file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 174979088681..2afc47c51a00 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -170,6 +170,8 @@ + Date: Wed, 13 Sep 2017 15:14:16 +0300 Subject: [PATCH 08/25] EA-107282 - TDDE: TraceableDisposable.throwDisposalError --- .../codeInsight/highlighting/BraceHighlightingHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index 496b3817abe7..c92b102d3158 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -529,7 +529,7 @@ public class BraceHighlightingHandler { myAlarm.addRequest(() -> { if (myProject.isDisposed()) return; PsiDocumentManager.getInstance(myProject).performLaterWhenAllCommitted(() -> { - if (!myEditor.getComponent().isShowing()) return; + if (myEditor.isDisposed() || !myEditor.getComponent().isShowing()) return; Rectangle viewRect = myEditor.getScrollingModel().getVisibleArea(); if (y < viewRect.y) { int start = lbraceStart; From d0318503154cbf8a1321ecbc8be311bcd3c69020 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Sep 2017 13:26:46 +0300 Subject: [PATCH 09/25] delegate: don't copy override as it would be added explicitly (IDEA-178893) --- .../generation/GenerateDelegateHandler.java | 3 ++- .../afterEnsureCorrectOverride.java | 17 +++++++++++++++++ .../beforeEnsureCorrectOverride.java | 14 ++++++++++++++ .../java/codeInsight/DelegateMethodsTest.java | 1 + 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/delegateMethods/afterEnsureCorrectOverride.java create mode 100644 java/java-tests/testData/codeInsight/delegateMethods/beforeEnsureCorrectOverride.java diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java index ff95b6c02bcc..c83cd6b59b67 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java @@ -163,7 +163,8 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler stmt = (PsiStatement)CodeStyleManager.getInstance(psiManager.getProject()).reformat(stmt); method.getBody().add(stmt); - GenerateMembersUtil.copyAnnotations(methodCandidate.getElement().getModifierList(), method.getModifierList(), SuppressWarnings.class.getName()); + GenerateMembersUtil.copyAnnotations(methodCandidate.getElement().getModifierList(), method.getModifierList(), + SuppressWarnings.class.getName(), Override.class.getName()); if (isMethodStatic || modifierList != null && modifierList.hasModifierProperty(PsiModifier.STATIC)) { PsiUtil.setModifierProperty(method, PsiModifier.STATIC, true); diff --git a/java/java-tests/testData/codeInsight/delegateMethods/afterEnsureCorrectOverride.java b/java/java-tests/testData/codeInsight/delegateMethods/afterEnsureCorrectOverride.java new file mode 100644 index 000000000000..aaf6f267b571 --- /dev/null +++ b/java/java-tests/testData/codeInsight/delegateMethods/afterEnsureCorrectOverride.java @@ -0,0 +1,17 @@ +interface I { + void foo(); +} +class A implements I { + @Override + public void foo() { + + } +} + +class B { + A a; + + public void foo() { + a.foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/delegateMethods/beforeEnsureCorrectOverride.java b/java/java-tests/testData/codeInsight/delegateMethods/beforeEnsureCorrectOverride.java new file mode 100644 index 000000000000..5cb936e92b07 --- /dev/null +++ b/java/java-tests/testData/codeInsight/delegateMethods/beforeEnsureCorrectOverride.java @@ -0,0 +1,14 @@ +interface I { + void foo(); +} +class A implements I { + @Override + public void foo() { + + } +} + +class B { + A a; + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/DelegateMethodsTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/DelegateMethodsTest.java index f68980165c96..f087829c9a19 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/DelegateMethodsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/DelegateMethodsTest.java @@ -58,6 +58,7 @@ public class DelegateMethodsTest extends LightCodeInsightTestCase { public void testMultipleOverrideAnnotations() { doTest(); } public void testStripSuppressWarningsAnnotation() { doTest(); } public void testDoNotOverrideFinal() { doTest(); } + public void testEnsureCorrectOverride() { doTest(); } public void testAllowDelegateToFinal() { doTest(); } public void testDelegateWithSubstitutionOverrides() { doTest(); } public void testDelegateWithSubstitutionNoOverrides() { doTest(); } From 06dc99b6361447819e1bd92f8482360586e6af5a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Sep 2017 15:26:18 +0300 Subject: [PATCH 10/25] don't initialize all inspections in tests by default (IDEA-178905) --- .../SingleInspectionProfilePanelTest.kt | 31 ++++++++++--------- .../daemon/impl/ExternalToolPass.java | 5 +-- .../com/intellij/testFramework/inspections.kt | 30 +++++++++--------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/SingleInspectionProfilePanelTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/SingleInspectionProfilePanelTest.kt index 0e34161e0e42..9df2acbac466 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/SingleInspectionProfilePanelTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/SingleInspectionProfilePanelTest.kt @@ -25,6 +25,7 @@ import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel import com.intellij.testFramework.LightIdeaTestCase import com.intellij.testFramework.configureInspections import com.intellij.testFramework.createProfile +import com.intellij.testFramework.runInInitMode import junit.framework.TestCase import org.assertj.core.api.Assertions.assertThat @@ -33,23 +34,25 @@ class SingleInspectionProfilePanelTest : LightIdeaTestCase() { // see IDEA-85700 fun testSettingsModification() { - val project = ProjectManager.getInstance().defaultProject - val profile = configureInspections(arrayOf(myInspection), project, testRootDisposable) + runInInitMode { + val project = ProjectManager.getInstance().defaultProject + val profile = configureInspections(arrayOf(myInspection), project, testRootDisposable) - val model = profile.modifiableModel - val panel = SingleInspectionProfilePanel(ProjectInspectionProfileManager.getInstance(project), model) - panel.isVisible = true - panel.reset() + val model = profile.modifiableModel + val panel = SingleInspectionProfilePanel(ProjectInspectionProfileManager.getInstance(project), model) + panel.isVisible = true + panel.reset() - val tool = getInspection(model) - assertEquals("", tool.myAdditionalJavadocTags) - tool.myAdditionalJavadocTags = "foo" - model.setModified(true) - panel.apply() - assertThat(InspectionProfileTest.countInitializedTools(model)).isEqualTo(1) + val tool = getInspection(model) + assertEquals("", tool.myAdditionalJavadocTags) + tool.myAdditionalJavadocTags = "foo" + model.setModified(true) + panel.apply() + assertThat(InspectionProfileTest.countInitializedTools(model)).isEqualTo(1) - assertThat(getInspection(profile).myAdditionalJavadocTags).isEqualTo("foo") - panel.disposeUI() + assertThat(getInspection(profile).myAdditionalJavadocTags).isEqualTo("foo") + panel.disposeUI() + } } fun testModifyInstantiatedTool() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java index 3cb83e976bae..cd4ae0f05f3c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java @@ -112,8 +112,9 @@ public class ExternalToolPass extends ProgressableTextEditorHighlightingPass { String shortName = annotator.getPairedBatchInspectionShortName(); if (shortName != null) { HighlightDisplayKey key = HighlightDisplayKey.find(shortName); - LOG.assertTrue(key != null, "Paired tool '" + shortName + "' not found for external annotator: " + annotator); - if (!profile.isToolEnabled(key, myFile)) continue; + LOG.assertTrue(key != null || ApplicationManager.getApplication().isUnitTestMode(), + "Paired tool '" + shortName + "' not found for external annotator: " + annotator); + if (key == null || !profile.isToolEnabled(key, myFile)) continue; //test should register corresponding paired tool for annotator to run } Object collectedInfo = editor != null ? annotator.collectInformation(psiRoot, editor, errorFound) : annotator.collectInformation(psiRoot); diff --git a/platform/testFramework/src/com/intellij/testFramework/inspections.kt b/platform/testFramework/src/com/intellij/testFramework/inspections.kt index ae3530e07273..0a9a360c706d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/inspections.kt +++ b/platform/testFramework/src/com/intellij/testFramework/inspections.kt @@ -23,6 +23,8 @@ import com.intellij.codeInspection.ex.* import com.intellij.openapi.Disposable import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer +import com.intellij.profile.codeInspection.BaseInspectionProfileManager +import com.intellij.profile.codeInspection.InspectionProfileManager import com.intellij.profile.codeInspection.InspectionProjectProfileManager import com.intellij.profile.codeInspection.ProjectInspectionProfileManager import com.intellij.testFramework.fixtures.impl.GlobalInspectionContextForTests @@ -35,21 +37,21 @@ import java.util.* fun configureInspections(tools: Array, project: Project, parentDisposable: Disposable): InspectionProfileImpl { - runInInitMode { - val profile = createSimple(UUID.randomUUID().toString(), project, tools.mapSmart { InspectionToolRegistrar.wrapTool(it) }) - val profileManager = ProjectInspectionProfileManager.getInstance(project) - // we don't restore old project profile because in tests it must be in any case null - app default profile - Disposer.register(parentDisposable, Disposable { - profileManager.deleteProfile(profile) - profileManager.setCurrentProfile(null) - clearAllToolsIn(BASE_PROFILE) - }) + val profile = InspectionProfileImpl(UUID.randomUUID().toString(), + { tools.mapSmart { InspectionToolRegistrar.wrapTool(it) } }, + InspectionProfileManager.getInstance() as BaseInspectionProfileManager) + val profileManager = ProjectInspectionProfileManager.getInstance(project) + // we don't restore old project profile because in tests it must be in any case null - app default profile + Disposer.register(parentDisposable, Disposable { + profileManager.deleteProfile(profile) + profileManager.setCurrentProfile(null) + clearAllToolsIn(BASE_PROFILE) + }) - profileManager.addProfile(profile) - profile.initInspectionTools(project) - profileManager.setCurrentProfile(profile) - return profile - } + profileManager.addProfile(profile) + profileManager.setCurrentProfile(profile) + enableInspectionTools(project, parentDisposable, *tools) + return profile } @JvmOverloads From b9e2c4130d55211c728e7d05c9cbe8a5905b4628 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Sep 2017 15:31:00 +0300 Subject: [PATCH 11/25] inference: allow capture during intersection type construction (IDEA-173900) --- .../intellij/psi/PsiCapturedWildcardType.java | 7 +++++-- .../com/intellij/psi/PsiIntersectionType.java | 2 +- ...idIntersectionTypeWithCapturedBounds1.java | 21 +++++++++++++++++++ .../GraphInferenceHighlightingTest.java | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ValidIntersectionTypeWithCapturedBounds1.java diff --git a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java index bf3b6a65e519..e3416e934584 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java @@ -16,7 +16,6 @@ package com.intellij.psi; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.RecursionGuard; import com.intellij.openapi.util.RecursionManager; import com.intellij.psi.search.GlobalSearchScope; @@ -83,13 +82,17 @@ public class PsiCapturedWildcardType extends PsiType.Stub { glb = substitutedBoundType; } else { - glb = GenericsUtil.getGreatestLowerBound(glb, substitutedBoundType); + glb = getGreatestLowerBound(glb, substitutedBoundType, wildcardType); } } return glb; } + private static PsiType getGreatestLowerBound(PsiType glb, PsiType bound, Object guardObject) { + return guard.doPreventingRecursion(guardObject, true, () -> GenericsUtil.getGreatestLowerBound(glb, bound)); + } + @Override public boolean equals(Object o) { if (!(o instanceof PsiCapturedWildcardType)) { diff --git a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java index 4bd643b13974..331063c585dd 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java @@ -60,7 +60,7 @@ public class PsiIntersectionType extends PsiType.Stub { @NotNull private static PsiType[] flattenAndRemoveDuplicates(@NotNull PsiType[] conjuncts) { try { - final Set flattenConjuncts = PsiCapturedWildcardType.guard.doPreventingRecursion(conjuncts, true, () -> flatten(conjuncts, ContainerUtil.newLinkedHashSet())); + final Set flattenConjuncts = flatten(conjuncts, ContainerUtil.newLinkedHashSet()); if (flattenConjuncts == null) { return conjuncts; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ValidIntersectionTypeWithCapturedBounds1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ValidIntersectionTypeWithCapturedBounds1.java new file mode 100644 index 000000000000..bba01422feca --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ValidIntersectionTypeWithCapturedBounds1.java @@ -0,0 +1,21 @@ + +abstract class Bug { + void m1(){ + D jobHandler = m(); + } + + abstract > J m(); +} + +interface B { +} + +abstract class C { + +} + +abstract class D extends C { + +} + +abstract class E implements B { } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 2aad6e703571..fd044c5a5e0e 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -116,6 +116,7 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase public void testIDEA149774() { doTest(); } public void testDisjunctionTypes() { doTest(); } public void testValidIntersectionTypeWithCapturedBounds() { doTest(); } + public void testValidIntersectionTypeWithCapturedBounds1() { doTest(); } public void testPushErasedStateToArguments() { doTest(); } public void testStopAtStandaloneConditional() { doTest(); } public void testTransitiveInferenceVariableDependencies() { doTest(); } From f330b845a3d938f99e6bdd821349a5f8e7345aa4 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 13 Sep 2017 15:56:12 +0300 Subject: [PATCH 12/25] EA-85207 - TDDE: TraceableDisposable.throwDisposalError --- .../openapi/fileEditor/impl/IdeDocumentHistoryImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java index 15793c351689..0dde9268c9d6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java @@ -464,6 +464,8 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec } private PlaceInfo createPlaceInfo(@NotNull final FileEditor fileEditor, final FileEditorProvider fileProvider) { + if (!fileEditor.isValid()) return null; + final VirtualFile file = myEditorManager.getFile(fileEditor); LOG.assertTrue(file != null); From 4c89642304c67101cb53386db346a5176c4bfe13 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 13 Sep 2017 15:37:54 +0300 Subject: [PATCH 13/25] [file-history] proper keymap groups for revision history and annotate actions --- platform/platform-resources/src/idea/VcsActions.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml index 977adafa24cb..1abad6d5bf64 100644 --- a/platform/platform-resources/src/idea/VcsActions.xml +++ b/platform/platform-resources/src/idea/VcsActions.xml @@ -325,6 +325,7 @@ + @@ -339,6 +340,7 @@ + From 9215b7996363f2260c0364608397d62043a27c5a Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 13 Sep 2017 15:53:30 +0300 Subject: [PATCH 14/25] [file-history] no need to include show history for selection in the second keymap group --- platform/platform-resources/src/idea/VcsActions.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml index 1abad6d5bf64..1dad5b71986d 100644 --- a/platform/platform-resources/src/idea/VcsActions.xml +++ b/platform/platform-resources/src/idea/VcsActions.xml @@ -323,7 +323,6 @@ - From 17caf3238c17fda85e0c7d3fcbf27771f67315f4 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 13 Sep 2017 15:58:40 +0300 Subject: [PATCH 15/25] PY-25962 The documentation window in Scientific mode can take up all the editor space move documentation manager used in edu to the python --- .../resources/META-INF/plugin.xml | 2 -- python/src/META-INF/python-core-common.xml | 3 +++ .../python/PyDocumentationManager.java} | 12 +++++++----- .../python/actions/PySciViewAction.java | 17 ++++------------- 4 files changed, 14 insertions(+), 20 deletions(-) rename python/{educational-core/src/com/jetbrains/edu/learning/StudyDocumentationManager.java => src/com/jetbrains/python/PyDocumentationManager.java} (75%) diff --git a/python/educational-core/resources/META-INF/plugin.xml b/python/educational-core/resources/META-INF/plugin.xml index 83ddbb6ed724..6b169c7829c8 100644 --- a/python/educational-core/resources/META-INF/plugin.xml +++ b/python/educational-core/resources/META-INF/plugin.xml @@ -157,8 +157,6 @@ - diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index cb744f18e557..2b48df70978a 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -105,6 +105,9 @@ + + Date: Wed, 13 Sep 2017 14:57:31 +0200 Subject: [PATCH 16/25] [groovy] prefer empty vararg over implicit null (IDEA-178858) --- .../lang/resolve/GrDefaultMethodComparator.java | 5 +++++ .../groovy/lang/resolve/ResolveMethodTest.groovy | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GrDefaultMethodComparator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GrDefaultMethodComparator.java index 138f10ea9b10..ba676a2b1bb3 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GrDefaultMethodComparator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/GrDefaultMethodComparator.java @@ -69,6 +69,11 @@ public class GrDefaultMethodComparator extends GrMethodComparator { PsiParameter[] params1 = method1.getParameterList().getParameters(); PsiParameter[] params2 = method2.getParameterList().getParameters(); + + if (argTypes != null && argTypes.length == 0) { + if (params2.length == 1 && params2[0].getType() instanceof PsiArrayType) return true; + } + if (argTypes == null && params1.length != params2.length) return false; if (params1.length < params2.length) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy index d3489f52e201..296b65190619 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy @@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.lang.resolve import com.intellij.psi.* import com.intellij.psi.util.PropertyUtil import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression @@ -2292,4 +2293,19 @@ new SomeClass().size() ''', GrMethodImpl } + + void 'test prefer varargs in no-arg call'() { + def file = fixture.configureByText('_.groovy', '''\ +class A { + A(String... a) { println "varargs" } + A(A a) { println "single" } +} + +new A() +''') as GroovyFile + def expression = file.statements.last() as GrNewExpression + def resolved = expression.resolveMethod() + assert resolved instanceof GrMethod + assert resolved.isVarArgs() + } } From b3d29e57497653001461c80ffd563ff42aa6a366 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 13 Sep 2017 15:19:26 +0200 Subject: [PATCH 17/25] IDEA-178141 Case sensitive completion: First Letter - doesn't work correctly if class starts with special symbol check first letter after the underscore --- .../DispreferUnderscoredCaseMatch.java | 5 +++++ .../NormalCompletionOrderingTest.groovy | 4 ++++ .../completion/impl/CamelHumpMatcher.java | 16 ++++++++++++++-- .../jetbrains/python/PythonCompletionTest.java | 5 +++-- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normalSorting/DispreferUnderscoredCaseMatch.java diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferUnderscoredCaseMatch.java b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferUnderscoredCaseMatch.java new file mode 100644 index 000000000000..21ba4e5aa742 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferUnderscoredCaseMatch.java @@ -0,0 +1,5 @@ +class Zoo { + void zoo(String fooBar, String __foo_bar) { + foo + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy index 46257504acf2..f44f25fd1adf 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -443,6 +443,10 @@ interface TxANotAnno {} checkPreferredItems(0, 'fooBar', '_fooBar', 'FooBar') } + void testDispreferUnderscoredCaseMatch() { + checkPreferredItems(0, 'fooBar', '__foo_bar') + } + void testStatisticsMattersOnNextCompletion() { configureByFile(getTestName(false) + ".java") myFixture.completeBasic() diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java index 73923b6e395c..9fc55743281d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java @@ -63,14 +63,26 @@ public class CamelHumpMatcher extends PrefixMatcher { @Override public boolean prefixMatches(@NotNull final String name) { if (name.startsWith("_") && - myPrefix.length() > 0 && Character.isLetter(myPrefix.charAt(0)) && - CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE == CodeInsightSettings.FIRST_LETTER) { + CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE == CodeInsightSettings.FIRST_LETTER && + firstLetterCaseDiffers(name)) { return false; } return myMatcher.matches(name); } + private boolean firstLetterCaseDiffers(String name) { + int nameFirst = skipUnderscores(name); + int prefixFirst = skipUnderscores(myPrefix); + return nameFirst < name.length() && + prefixFirst < myPrefix.length() && + caseDiffers(name.charAt(nameFirst), myPrefix.charAt(prefixFirst)); + } + + private static boolean caseDiffers(char c1, char c2) { + return Character.isLowerCase(c1) != Character.isLowerCase(c2) || Character.isUpperCase(c1) != Character.isUpperCase(c2); + } + @Override public boolean prefixMatches(@NotNull final LookupElement element) { return prefixMatchersInternal(element, !element.isCaseSensitive()); diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index b99354a514ba..39f3698a7e89 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -23,6 +23,7 @@ import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.testFramework.PsiTestUtil; +import com.jetbrains.python.documentation.PyDocumentationSettings; import com.jetbrains.python.documentation.docstrings.DocStringFormat; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.LanguageLevel; @@ -1067,7 +1068,7 @@ public class PythonCompletionTest extends PyTestCase { "@six.add_metaclass(M)\n" + "class C(object):\n" + " def foo(self):\n" + - " C.bax()"); + " C.ba()"); assertNotNull(suggested); assertContainsElements(suggested, "baz"); @@ -1081,7 +1082,7 @@ public class PythonCompletionTest extends PyTestCase { "@a_m(M)\n" + "class C(object):\n" + " def foo(self):\n" + - " C.bax()"); + " C.ba()"); assertNotNull(suggested); assertContainsElements(suggested, "baz"); From 13615c5b3d5c0e233879821b6fd9df410d71bdf3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Sep 2017 15:44:34 +0300 Subject: [PATCH 18/25] read action (IDEA-178910) --- .../impl/src/com/intellij/execution/junit/JUnitUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java index 556e342110d2..a5ee8935ba5e 100644 --- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java +++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java @@ -21,6 +21,7 @@ import com.intellij.codeInsight.TestFrameworks; import com.intellij.execution.*; import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.execution.testframework.SourceScope; +import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.progress.ProgressManager; @@ -278,7 +279,7 @@ public class JUnitUtil { return aPackage != null && aPackage.getDirectories(scope).length > 0; }; - return foundCondition.value(TEST5_PACKAGE_FQN); + return ReadAction.compute(() -> foundCondition.value(TEST5_PACKAGE_FQN)); } public static boolean isTestAnnotated(final PsiMethod method) { From 224bf4f33bfd52e931ecd1f12dc9708ea52b3205 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 13 Sep 2017 16:46:02 +0300 Subject: [PATCH 19/25] coverage: setting to ignore trivial constructors --- .../coverage/CoverageDataManagerImpl.java | 1 - plugins/coverage/src/META-INF/plugin.xml | 2 + .../intellij/coverage/JavaCoverageEngine.java | 7 +- .../coverage/JavaCoverageOptions.java | 84 +++++++++++++++++++ .../coverage/JavaCoverageOptionsProvider.java | 60 +++++++++++++ .../intellij/coverage/PackageAnnotator.java | 16 ++-- .../coverage/SourceLineCounterUtil.java | 32 ++++--- 7 files changed, 180 insertions(+), 22 deletions(-) create mode 100644 plugins/coverage/src/com/intellij/coverage/JavaCoverageOptions.java create mode 100644 plugins/coverage/src/com/intellij/coverage/JavaCoverageOptionsProvider.java diff --git a/plugins/coverage-common/src/com/intellij/coverage/CoverageDataManagerImpl.java b/plugins/coverage-common/src/com/intellij/coverage/CoverageDataManagerImpl.java index 7c96cd7de1e8..a84bfe67f691 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/CoverageDataManagerImpl.java +++ b/plugins/coverage-common/src/com/intellij/coverage/CoverageDataManagerImpl.java @@ -137,7 +137,6 @@ public class CoverageDataManagerImpl extends CoverageDataManager { @Override public void readExternal(Element element) throws InvalidDataException { - //noinspection unchecked for (Element suiteElement : element.getChildren(SUITE)) { final CoverageRunner coverageRunner = BaseCoverageSuite.readRunnerAttribute(suiteElement); // skip unknown runners diff --git a/plugins/coverage/src/META-INF/plugin.xml b/plugins/coverage/src/META-INF/plugin.xml index 6b9f5961d53e..97c83b556bf5 100644 --- a/plugins/coverage/src/META-INF/plugin.xml +++ b/plugins/coverage/src/META-INF/plugin.xml @@ -26,6 +26,8 @@ + + diff --git a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java index 49be86c13f47..b36f7847dc83 100644 --- a/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java +++ b/plugins/coverage/src/com/intellij/coverage/JavaCoverageEngine.java @@ -654,8 +654,11 @@ public class JavaCoverageEngine extends CoverageEngine { @Override public boolean isGeneratedCode(Project project, String qualifiedName, Object lineData) { - PsiClass psiClass = ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName)); - return PackageAnnotator.isGeneratedDefaultConstructor(psiClass, ((LineData)lineData).getMethodSignature()); + if (JavaCoverageOptionsProvider.getInstance(project).ignoreEmptyPrivateConstructors()) { + PsiClass psiClass = ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName)); + return PackageAnnotator.isGeneratedDefaultConstructor(psiClass, ((LineData)lineData).getMethodSignature()); + } + return super.isGeneratedCode(project, qualifiedName, lineData); } @Override diff --git a/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptions.java b/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptions.java new file mode 100644 index 000000000000..2af4314e3c82 --- /dev/null +++ b/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptions.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2017 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.coverage; + +import com.intellij.ui.IdeBorderFactory; + +import javax.swing.*; +import java.awt.*; + +public class JavaCoverageOptions extends CoverageOptions { + + private final JavaCoverageOptionsProvider myCoverageOptionsProvider; + private JavaCoverageOptionsEditor myEditor; + + public JavaCoverageOptions(JavaCoverageOptionsProvider coverageOptionsProvider) { + myCoverageOptionsProvider = coverageOptionsProvider; + } + + @Override + public JComponent getComponent() { + myEditor = new JavaCoverageOptionsEditor(); + return myEditor.getComponent(); + } + + @Override + public boolean isModified() { + return myEditor.isModified(myCoverageOptionsProvider); + } + + @Override + public void apply() { + myEditor.apply(myCoverageOptionsProvider); + } + + @Override + public void reset() { + myEditor.reset(myCoverageOptionsProvider); + } + + @Override + public void disposeUIResources() { + myEditor = null; + } + + private static class JavaCoverageOptionsEditor { + + private JPanel myPanel = new JPanel(new BorderLayout(0, 10)); + private JCheckBox myCheckBox = new JCheckBox("Ignore empty private and implicit constructors", true); + + public JavaCoverageOptionsEditor() { + myPanel.setBorder(IdeBorderFactory.createTitledBorder("Java coverage")); + myPanel.add(myCheckBox, BorderLayout.NORTH); + } + + public JPanel getComponent() { + return myPanel; + } + + public boolean isModified(JavaCoverageOptionsProvider provider) { + return myCheckBox.isSelected() != provider.ignoreEmptyPrivateConstructors(); + } + + public void apply(JavaCoverageOptionsProvider provider) { + provider.setIgnoreEmptyPrivateConstructors(myCheckBox.isSelected()); + } + + public void reset(JavaCoverageOptionsProvider provider) { + myCheckBox.setSelected(provider.ignoreEmptyPrivateConstructors()); + } + } +} diff --git a/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptionsProvider.java b/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptionsProvider.java new file mode 100644 index 000000000000..22fb29900059 --- /dev/null +++ b/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptionsProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2017 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.coverage; + +import com.intellij.openapi.components.*; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.Nullable; + +@State( + name = "JavaCoverageOptionsProvider", + storages = { + @Storage(StoragePathMacros.WORKSPACE_FILE) + } +) +public class JavaCoverageOptionsProvider implements PersistentStateComponent { + private State myState = new State(); + + public static JavaCoverageOptionsProvider getInstance(Project project) { + return ServiceManager.getService(project, JavaCoverageOptionsProvider.class); + } + + + public void setIgnoreEmptyPrivateConstructors(boolean state) { + myState.myIgnoreEmptyPrivateConstructors = state; + } + + public boolean ignoreEmptyPrivateConstructors() { + return myState.myIgnoreEmptyPrivateConstructors; + } + + @Nullable + @Override + public JavaCoverageOptionsProvider.State getState() { + return myState; + } + + @Override + public void loadState(JavaCoverageOptionsProvider.State state) { + myState.myIgnoreEmptyPrivateConstructors = state.myIgnoreEmptyPrivateConstructors; + } + + + public static class State { + public boolean myIgnoreEmptyPrivateConstructors = true; + } + +} diff --git a/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java b/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java index 2f90f21a4db0..4f450db59e0d 100644 --- a/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java +++ b/plugins/coverage/src/com/intellij/coverage/PackageAnnotator.java @@ -23,6 +23,7 @@ import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -37,6 +38,7 @@ import com.intellij.rt.coverage.data.LineData; import com.intellij.rt.coverage.data.ProjectData; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.SmartHashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import org.jetbrains.jps.model.java.JavaSourceRootType; @@ -57,12 +59,14 @@ public class PackageAnnotator { private final Project myProject; private final PsiManager myManager; private final CoverageDataManager myCoverageManager; + private final boolean myIgnoreEmptyPrivateConstructors; public PackageAnnotator(final PsiPackage aPackage) { myPackage = aPackage; myProject = myPackage.getProject(); myManager = PsiManager.getInstance(myProject); myCoverageManager = CoverageDataManager.getInstance(myProject); + myIgnoreEmptyPrivateConstructors = JavaCoverageOptionsProvider.getInstance(myProject).ignoreEmptyPrivateConstructors(); } public interface Annotator { @@ -455,7 +459,7 @@ public class PackageAnnotator { touchedClass = true; } - if (isGeneratedDefaultConstructor(psiClass, (String)nameAndSig)) { + if (myIgnoreEmptyPrivateConstructors && isGeneratedDefaultConstructor(psiClass, (String)nameAndSig)) { continue; } @@ -505,16 +509,16 @@ public class PackageAnnotator { * in the bytecode, so we need to look at the PSI to see if the class defines such a constructor. */ public static boolean isGeneratedDefaultConstructor(@Nullable final PsiClass aClass, String nameAndSig) { + if (aClass == null) { + return false; + } if (DEFAULT_CONSTRUCTOR_NAME_SIGNATURE.equals(nameAndSig)) { return hasGeneratedOrEmptyPrivateConstructor(aClass); } return false; } - private static boolean hasGeneratedOrEmptyPrivateConstructor(@Nullable final PsiClass aClass) { - if (aClass == null) { - return false; - } + private static boolean hasGeneratedOrEmptyPrivateConstructor(@NotNull final PsiClass aClass) { return ReadAction.compute(() -> { PsiMethod[] constructors = aClass.getConstructors(); if (constructors.length == 1 && constructors[0].hasModifierProperty(PsiModifier.PRIVATE)) { @@ -563,6 +567,6 @@ public class PackageAnnotator { if (coverageSuite == null) return false; return SourceLineCounterUtil .collectNonCoveredClassInfo(classCoverageInfo, packageCoverageInfo, content, coverageSuite.isTracingEnabled(), - psiClass); + myIgnoreEmptyPrivateConstructors ? description -> !isGeneratedDefaultConstructor(psiClass, description) : Condition.TRUE); } } diff --git a/plugins/coverage/src/com/intellij/coverage/SourceLineCounterUtil.java b/plugins/coverage/src/com/intellij/coverage/SourceLineCounterUtil.java index e5e8851fbae7..b3be240bcdaf 100644 --- a/plugins/coverage/src/com/intellij/coverage/SourceLineCounterUtil.java +++ b/plugins/coverage/src/com/intellij/coverage/SourceLineCounterUtil.java @@ -17,6 +17,7 @@ package com.intellij.coverage; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiManager; import com.intellij.psi.util.ClassUtil; @@ -29,11 +30,10 @@ import java.util.List; import java.util.Set; public class SourceLineCounterUtil { - public static boolean collectNonCoveredClassInfo(final PackageAnnotator.ClassCoverageInfo classCoverageInfo, - final PackageAnnotator.PackageCoverageInfo packageCoverageInfo, - byte[] content, + public static boolean collectNonCoveredClassInfo(final PackageAnnotator.ClassCoverageInfo classCoverageInfo, + final PackageAnnotator.PackageCoverageInfo packageCoverageInfo, byte[] content, final boolean excludeLines, - final PsiClass psiClass) { + final Condition includeDescriptionCondition) { if (content == null) return false; ClassReader reader = new ClassReader(content, 0, content.length); @@ -42,13 +42,13 @@ public class SourceLineCounterUtil { Set descriptions = new HashSet<>(); TIntObjectHashMap lines = counter.getSourceLines(); lines.forEachEntry((line, description) -> { - if (!PackageAnnotator.isGeneratedDefaultConstructor(psiClass, (String)description)) { - classCoverageInfo.totalLineCount ++; - packageCoverageInfo.totalLineCount ++; - descriptions.add(description); - } - return true; - }); + if (includeDescriptionCondition.value((String)description)) { + classCoverageInfo.totalLineCount++; + packageCoverageInfo.totalLineCount++; + descriptions.add(description); + } + return true; + }); classCoverageInfo.totalMethodCount += descriptions.size(); packageCoverageInfo.totalMethodCount += descriptions.size(); @@ -68,10 +68,16 @@ public class SourceLineCounterUtil { reader.accept(collector, 0); String qualifiedName = reader.getClassName(); - PsiClass psiClass = ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName)); + boolean ignoreEmptyPrivateConstructors = JavaCoverageOptionsProvider.getInstance(project).ignoreEmptyPrivateConstructors(); + PsiClass psiClass = ignoreEmptyPrivateConstructors + ? ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName)) + : null; + Condition includeDescriptionCondition = ignoreEmptyPrivateConstructors + ? description -> !PackageAnnotator.isGeneratedDefaultConstructor(psiClass, description) + : Condition.TRUE; TIntObjectHashMap lines = collector.getSourceLines(); lines.forEachEntry((line, description) -> { - if (!PackageAnnotator.isGeneratedDefaultConstructor(psiClass, (String)description)) { + if (includeDescriptionCondition.value((String)description)) { line--; uncoveredLines.add(line); } From e119300628bbd8ed03ec578eac547a35f458fba3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Sep 2017 15:11:10 +0300 Subject: [PATCH 20/25] javadoc --- .../lang/injection/MultiHostInjector.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java b/platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java index 4172eaf05570..d76b7edf4380 100644 --- a/platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java +++ b/platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java @@ -24,12 +24,64 @@ import java.util.List; /** * @see com.intellij.psi.PsiLanguageInjectionHost + * @see MultiHostRegistrar */ public interface MultiHostInjector { ExtensionPointName MULTIHOST_INJECTOR_EP_NAME = ExtensionPointName.create("com.intellij.multiHostInjector"); + /** + * Provides list of places to inject a language to.
+ * + * For example, to inject "RegExp" language to java string literal, you can override this method with something like this: + *
+   * class MyRegExpToJavaInjector implements MultiHostInjector {
+   *   void getLanguagesToInject(MultiHostRegistrar registrar, PsiElement context) {
+   *     if (context instanceof PsiLiteralExpression && looksLikeAGoodPlaceToInject(context)) {
+   *       registrar.startInjecting(REGEXP_LANG).addPlace(null,null,context,innerRangeStrippingQuotes(context));
+   *     }
+   *   }
+   * }
+   * 
+ * + * Also, we may need to inject into several fragments at once. For example, if we have this really bizarre XML-based DSL: + *
+   * {@code
+   *
+   * 
+   *   
+   *     foo
+   *     System.out.println(42);
+   *   
+   * 
+   * }
+   * 
+ * + * which should be converted to Java: + *
class MyDsl { void foo() { System.out.println(42);} }
+ * + * Then we can inject Java into several places at once - method name and its body: + *
+   * class MyBizarreDSLInjector implements MultiHostInjector {
+   *   void getLanguagesToInject(MultiHostRegistrar registrar, PsiElement context) {
+   *     if (isMethodTag(context)) {
+   *       registrar.startInjecting(JavaLanguage.INSTANCE);
+   *       // construct class header, method header, inject method name, append code block start
+   *       registrar.addPlace("class MyDsl { void ", "() {", context, rangeForMethodName(context));
+   *       // inject method body, append closing braces to form a valid Java class structure
+   *       registrar.addPlace(null, "}}", context, rangeForBody(context));
+   *       registrar.doneInjecting();
+   *     }
+   *   }
+   * }
+   * 
+ * + * Now, then we look at this XML in the editor, "foo" will feel like a method name + * and "System.out.println(42);" will look and feel like a method body - with highlighting, completion, goto definitions etc. + * + */ void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context); + @NotNull List> elementsToInjectIn(); } \ No newline at end of file From b04aae06c0f79fef9a32705a9d80326192a7e5a0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 13 Sep 2017 15:59:45 +0300 Subject: [PATCH 21/25] diagnostics --- .../testSrc/com/intellij/util/AlarmTest.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.java b/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.java index 83f423317f7c..c026c3ef1afe 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/AlarmTest.java @@ -16,21 +16,19 @@ package com.intellij.util; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.impl.LaterInvocator; -import com.intellij.testFramework.PlatformTestCase; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.NotNull; + import com.intellij.openapi.application.ModalityState; + import com.intellij.openapi.application.impl.LaterInvocator; + import com.intellij.testFramework.PlatformTestCase; + import com.intellij.util.ui.UIUtil; + import org.jetbrains.annotations.NotNull; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; + import java.util.*; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.Future; + import java.util.concurrent.TimeUnit; + import java.util.concurrent.TimeoutException; + import java.util.concurrent.atomic.AtomicInteger; + import java.util.stream.Collectors; public class AlarmTest extends PlatformTestCase { public void testTwoAddsWithZeroDelayMustExecuteSequentially() throws Exception { @@ -93,7 +91,12 @@ public class AlarmTest extends PlatformTestCase { UIUtil.dispatchAllInvocationEvents(); } Map after = Thread.getAllStackTraces(); - assertTrue("before: "+before.size()+"; after: "+after.size(), after.size() - before.size() < 10); + Map> diff = new HashMap<>(); + after.forEach((key, value) -> diff.put(key, Arrays.asList(value))); + before.keySet().forEach(diff::remove); + if (!(after.size() - before.size() < 10)) { + fail("before: "+before.size()+"; after: "+after.size()+"Diff:\n"+diff); + } } public void testManyAlarmsDoNotStartTooManyThreads() { From 11e95c565d32bc9f990587ce800834bc54473d40 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 13 Sep 2017 17:01:42 +0300 Subject: [PATCH 22/25] condaenv icon --- .../com/jetbrains/python/condaenv@2x_dark.png | Bin 294 -> 423 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/python/resources/icons/com/jetbrains/python/condaenv@2x_dark.png b/python/resources/icons/com/jetbrains/python/condaenv@2x_dark.png index 5ed486884ef0ed2e73bc95ba5d984f6a086d66d8..d3d7529470124c6d3059b426cd15e08bf88f63b5 100644 GIT binary patch literal 423 zcmV;Y0a*TtP)I7{~7m95_2UbrTAi+_H#Mp=+r_ry{s08C)~h!PQRJL2h(8oE$O>2lr9@2=#d& zkr40YNiOLv9{jkWCI4Suo~LP+{XfKq9~uGFM8uTghHXp%Gw2M+0Ywl{DFkv&MOlRu z0*V@*O2CVl0<4F40)eN!ljB#$fZ9O>Q}Gdy)LEqx;3LDNE=Oju@)2Nx z!R6cQ&DHIrEP!v|Xwd*0YAX&AD4*p0q9xcx*#dackTC@G%uP7HAAmE=fj7rs{n-oY zS8^bbIh^ZdH?y3#jrnH_MhLiYYxYHy3yDWKmg~%#{pOScmAPo75TJBH)glmW3${Lu z$2o+&;}HH<230~(C7yTdOQ#H_RfbEe44Y*CC2{`=ji|^{J`ixx(~6h)ogb%~-OpTM R%{Tx6002ovPDHLkV1lq|x6l9p literal 294 zcmV+>0oneEP)moQBWYX-KxuM8a?b(pD^M_gOLF}QO>{W2s2&X8n4^stF3ndC=B(Mc`_OwJ{tw0TVFnn(qVeWI z%?31$VB78-j_84EY5-yZAWi_{evC8$jbjYkkMHl^4AgL*U`oVcKm*ifq6|<2B@%Q) s9v<;t2K7Qek{8yKlvAOuKn}!y0GvUp8p2DNCjbBd07*qoM6N<$f{z?`E&u=k From 822473f00ebeceb10774f16dcfbde03a0e95255b Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Wed, 13 Sep 2017 16:16:28 +0200 Subject: [PATCH 23/25] [groovy] honor returns when computing last statement (IDEA-178598) --- .../codeInspection/utils/ControlFlowUtils.java | 14 ++------------ .../lang/highlighting/GrInspectionTest.groovy | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 450f5d0abffe..458a88e632a4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -415,20 +415,10 @@ public class ControlFlowUtils { } private static boolean statementIsLastInBlock(@NotNull GrStatementOwner block, @NotNull GrStatement statement) { - final GrStatement[] statements = block.getStatements(); - for (int i = statements.length - 1; i >= 0; i--) { - final GrStatement childStatement = statements[i]; - if (statement.equals(childStatement)) { - return true; - } - if (!(childStatement instanceof GrReturnStatement)) { - return false; - } - } - return false; + GrStatement lastStatement = ArrayUtil.getLastElement(block.getStatements()); + return statement == lastStatement; } - @NotNull public static List collectReturns(@Nullable PsiElement element) { return collectReturns(element, element instanceof GrCodeBlock || element instanceof GroovyFile); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy index 21767b186e71..8054da137ab9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -292,6 +292,21 @@ for(i in []) { print 4 } } + +for (i in []) { + if (cond) { + continue + } + return +} + +for (i in []) { + if (cond) { + continue + } else { + return + } +} ''', GroovyUnnecessaryContinueInspection) } From 0c00e625a955ba2f385fb7bcaec1d197d44f3200 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 13 Sep 2017 16:24:13 +0200 Subject: [PATCH 24/25] disable .gitignore plugins that causes deadlock / start up problem IDEA-178803, IDEA-178534 --- platform/platform-resources/src/brokenPlugins.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index 09635cd1cb1e..f2f550374d75 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -30,7 +30,7 @@ com.intellij.apacheConfig 144.3713 143.2287.2 143.381.48 142.5266 141.388 139.78 org.intellij.clojure 0.2.1.178 net.nicoulaj.idea.markdown 0.9.7 0.9.6 0.9.5 0.9.4 0.9.3 0.9.2 0.9.1 0.8.3 0.8.2 0.8.1 0.8 0.7 0.6.1 0.6 0.5.1 0.5 0.4 0.3 0.2 0.1 zielu.gittoolbox 13.1.0 13.5.2 -mobi.hsz.idea.gitignore 1.2 1.3 1.3.3 1.4.1 1.5 1.6 1.7.5 1.7.6 2.0.4 +mobi.hsz.idea.gitignore 1.2 1.3 1.3.3 1.4.1 1.5 1.6 1.7.5 1.7.6 2.0.4 2.1.1 2.2.0 com.vladsch.idea.multimarkdown 1.4.2 1.4.7 com.jetbrains.chronon 134.1221 134.1414 134.1618 135.1291 135.476 135.666 ArgoUML.Integration 0.1.1 0.1.2 From 55cf0b0506ec305af62f10d54da76343052aab04 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 13 Sep 2017 17:39:31 +0200 Subject: [PATCH 25/25] Fix path the stubs are read from --- .../index-tools/src/org/jetbrains/index/stubs/StubsGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/index-tools/src/org/jetbrains/index/stubs/StubsGenerator.kt b/tools/index-tools/src/org/jetbrains/index/stubs/StubsGenerator.kt index 04cc88379ada..d47c6ea2248f 100644 --- a/tools/index-tools/src/org/jetbrains/index/stubs/StubsGenerator.kt +++ b/tools/index-tools/src/org/jetbrains/index/stubs/StubsGenerator.kt @@ -155,7 +155,7 @@ fun mergeStubs(paths: List, stubsFilePath: String, projectPath: String, for (path in paths) { println("Reading stubs from $path") var count = 0 - val fromStorageFile = File(stubsFilePath + ".input") + val fromStorageFile = File(path + ".input") val fromStorage = PersistentHashMap(fromStorageFile, HashCodeDescriptor.instance, stubExternalizer)