diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 9a9e9d5409c1..3d5ae020bce0 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -952,7 +952,6 @@ def layoutJps(String home, String targetDir, String buildNumber, Closure additio include(name: "ecj*.jar") include(name: "netty-all-*.jar") include(name: "snappy-in-java-*.jar") - include(name: "picocontainer.jar") } fileset(dir: "$home/jps/lib") { include(name: "optimizedFileManager.jar") diff --git a/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.kt b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.kt index b28de358ea41..baf149ac450c 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.kt +++ b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.kt @@ -16,52 +16,78 @@ package com.intellij.testIntegration import com.intellij.execution.RunnerAndConfigurationSettings -import com.intellij.execution.testframework.sm.runner.states.TestStateInfo +import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.util.containers.ContainerUtil import java.util.* +fun SuiteEntry.isMyTest(test: SingleTestEntry): Boolean { + val testName = VirtualFileManager.extractPath(test.url) + return testName.startsWith(this.suiteName) +} + class RecentTestsData { private val runConfigurationSuites = hashMapOf() - private var testsWithoutSuites: MutableList = ContainerUtil.newArrayList() - fun addSuite(url: String, - magnitude: TestStateInfo.Magnitude, - runDate: Date, - runConfiguration: RunnerAndConfigurationSettings) - { + private var unmatchedRunConfigurationTests = arrayListOf() - val suiteInfo = SuiteEntry(url, magnitude, runDate, runConfiguration) + private val urlSuites = mutableListOf() + private var unmatchedUrlTests = mutableListOf() - val configurationId = runConfiguration.uniqueID - val suitePack = runConfigurationSuites[configurationId] - if (suitePack != null) { - suitePack.addSuite(suiteInfo) - return + + fun addSuite(url: String, magnitude: Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings?) { + val suite = SuiteEntry(url, magnitude, runDate) + if (runConfiguration != null) { + addRunConfigurationSuite(suite, runConfiguration) } + else { + addUrlSuite(suite) + } + } + + fun addTest(url: String, magnitude: Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings?) { + val test = SingleTestEntry(url, magnitude, runDate) + if (runConfiguration != null) { + addRunConfigurationTest(test, runConfiguration) + } + else { + addUrlTest(test) + } + } + + private fun addUrlSuite(suite: SuiteEntry) { + val suiteTests = unmatchedUrlTests.filter { suite.isMyTest(it) } + suiteTests.forEach { suite.addTest(it) } - runConfigurationSuites[configurationId] = RunConfigurationEntry(runConfiguration, suiteInfo) + unmatchedUrlTests = unmatchedUrlTests.filterTo(arrayListOf(), { !suite.isMyTest(it) }) + + urlSuites.add(suite) } + private fun addRunConfigurationSuite(suite: SuiteEntry, config: RunnerAndConfigurationSettings) { + val suiteTests = unmatchedRunConfigurationTests.filter { suite.isMyTest(it) } + suiteTests.forEach { suite.addTest(it) } + + unmatchedRunConfigurationTests = unmatchedRunConfigurationTests.filterTo(arrayListOf(), { !suite.isMyTest(it) }) - fun addTest(url: String, - magnitude: TestStateInfo.Magnitude, - runDate: Date, - runConfiguration: RunnerAndConfigurationSettings) { - - val testInfo = SingleTestEntry(url, magnitude, runDate, runConfiguration) - - val suite = findSuite(url, runConfiguration) - if (suite != null) { - suite.addTest(testInfo) - return - } - - testsWithoutSuites.add(testInfo) + val id = config.uniqueID + runConfigurationSuites[id]?.addSuite(suite) ?: runConfigurationSuites.put(id, RunConfigurationEntry(config, suite)) } - private fun findSuite(url: String, runConfiguration: RunnerAndConfigurationSettings): SuiteEntry? { + private fun addUrlTest(test: SingleTestEntry) { + findUrlSuite(test.url)?.addTest(test) ?: unmatchedUrlTests.add(test) + } + + private fun addRunConfigurationTest(test: SingleTestEntry, runConfiguration: RunnerAndConfigurationSettings) { + findRunConfigurationSuite(test.url, runConfiguration)?.addTest(test) ?: unmatchedRunConfigurationTests.add(test) + } + + private fun findUrlSuite(url: String) = urlSuites.find { + val testName = VirtualFileManager.extractPath(url) + testName.startsWith(it.suiteName) + } + + private fun findRunConfigurationSuite(url: String, runConfiguration: RunnerAndConfigurationSettings): SuiteEntry? { val pack: RunConfigurationEntry = runConfigurationSuites[runConfiguration.uniqueID] ?: return null val testName = VirtualFileManager.extractPath(url) @@ -75,13 +101,15 @@ class RecentTestsData { } fun getTestsToShow(): List { - testsWithoutSuites.forEach { - val url = it.url - findSuite(url, it.runConfiguration)?.addTest(it) - } - - val packsByDate = runConfigurationSuites.values.sortedByDescending { it.runDate } - return packsByDate.fold(listOf(), { list, pack -> list + pack.entriesToShow() }) + val allEntries: List = runConfigurationSuites.values + urlSuites + return allEntries + .sortedByDescending { it.runDate } + .fold(listOf(), { popupList, currentEntry -> + when (currentEntry) { + is RunConfigurationEntry -> popupList + currentEntry.entriesToShow() + else -> popupList + currentEntry + } + }) } } diff --git a/java/execution/impl/src/com/intellij/testIntegration/RecentTestsListProvider.java b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsListProvider.java index 1619134f6919..66ff8617809e 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/RecentTestsListProvider.java +++ b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsListProvider.java @@ -99,9 +99,7 @@ public class RecentTestsListProvider { RunnerAndConfigurationSettings runConfiguration = myConfigurationProvider.getConfiguration(record); if (TestLocator.isSuite(url)) { - if (runConfiguration != null) { - data.addSuite(url, magnitude, record.date, runConfiguration); - } + data.addSuite(url, magnitude, record.date, runConfiguration); } else { data.addTest(url, magnitude, record.date, runConfiguration); diff --git a/java/execution/impl/src/com/intellij/testIntegration/RunConfigurationEntry.kt b/java/execution/impl/src/com/intellij/testIntegration/RunConfigurationEntry.kt index bb23cb41a909..7f7b1357e666 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/RunConfigurationEntry.kt +++ b/java/execution/impl/src/com/intellij/testIntegration/RunConfigurationEntry.kt @@ -35,10 +35,9 @@ interface RecentTestsPopupEntry { open fun navigatableElement(locator: TestLocator): PsiElement? = null } -open class SingleTestEntry(val url: String, - override val magnitude: TestStateInfo.Magnitude, - override val runDate: Date, - val runConfiguration: RunnerAndConfigurationSettings) : RecentTestsPopupEntry +open class SingleTestEntry(val url: String, + override val magnitude: TestStateInfo.Magnitude, + override val runDate: Date) : RecentTestsPopupEntry { override val presentation = VirtualFileManager.extractPath(url) @@ -52,10 +51,8 @@ open class SingleTestEntry(val url: String, } -class SuiteEntry(url: String, magnitude: TestStateInfo.Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings) - : SingleTestEntry(url, magnitude, runDate, runConfiguration) -{ - +class SuiteEntry(url: String, magnitude: TestStateInfo.Magnitude, runDate: Date) : SingleTestEntry(url, magnitude, runDate) { + private val tests = hashSetOf() override val testsUrls: List diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 1a691c344c62..9c2fef343845 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -213,6 +213,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } catch (IndexNotReadyException ignored) { } } + + myHolder.add(DefaultHighlightUtil.checkBadCharacter(element)); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index 743e5d2bd7de..bdc1273196fb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -220,6 +220,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection aClass.getInitializers().length == 0) { final PsiMethod method = methods[0]; return method.getBody() != null && + method.getDocComment() == null && !hasForbiddenRefsInsideBody(method, aClass) && !hasRuntimeAnnotations(method, ignoredRuntimeAnnotations) && !method.hasModifierProperty(PsiModifier.SYNCHRONIZED); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java index f5b95d7b41d7..f72106cf8b3e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java @@ -23,19 +23,22 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.RedundantCastUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.Collection; import java.util.Collections; /** * User: anna */ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalInspectionTool { - public static final Logger LOG = Logger.getInstance("#" + AnonymousCanBeMethodReferenceInspection.class.getName()); + private static final Logger LOG = Logger.getInstance("#" + AnonymousCanBeMethodReferenceInspection.class.getName()); public boolean reportNotAnnotatedInterfaces = true; @@ -132,19 +135,38 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI final String methodRefText = LambdaCanBeMethodReferenceInspection.convertToMethodReference(methods[0].getBody(), parameters, anonymousClass.getBaseClassType(), anonymousClass.getParent()); - if (methodRefText != null) { - final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText(); - final PsiExpression psiExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText("(" + canonicalText + ")" + methodRefText, anonymousClass); - - PsiElement castExpr = anonymousClass.getParent().replace(psiExpression); - if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)castExpr)) { - final PsiExpression operand = ((PsiTypeCastExpression)castExpr).getOperand(); - LOG.assertTrue(operand != null); - castExpr = castExpr.replace(operand); - } - JavaCodeStyleManager.getInstance(project).shortenClassReferences(castExpr); - } + replaceWithMethodReference(project, methodRefText, anonymousClass.getBaseClassType(), anonymousClass.getParent()); } } + } + + static void replaceWithMethodReference(@NotNull Project project, + String methodRefText, + PsiType castType, + PsiElement replacementTarget) { + final Collection comments = ContainerUtil.map(PsiTreeUtil.findChildrenOfType(replacementTarget, PsiComment.class), + comment -> (PsiComment)comment.copy()); + + if (methodRefText != null) { + final String canonicalText = castType.getCanonicalText(); + final PsiExpression psiExpression = JavaPsiFacade + .getElementFactory(project).createExpressionFromText("(" + canonicalText + ")" + methodRefText, replacementTarget); + + PsiElement castExpr = replacementTarget.replace(psiExpression); + if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)castExpr)) { + final PsiExpression operand = ((PsiTypeCastExpression)castExpr).getOperand(); + LOG.assertTrue(operand != null); + castExpr = castExpr.replace(operand); + } + + PsiElement anchor = PsiTreeUtil.getParentOfType(castExpr, PsiStatement.class); + if (anchor == null) { + anchor = castExpr; + } + for (PsiComment comment : comments) { + anchor.getParent().addBefore(comment, anchor); + } + JavaCodeStyleManager.getInstance(project).shortenClassReferences(castExpr); } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaLineIndentProvider.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaLineIndentProvider.java index feb3ad1db87c..3857da0cc18d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaLineIndentProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaLineIndentProvider.java @@ -19,14 +19,14 @@ import com.intellij.lang.Language; import com.intellij.lang.java.JavaLanguage; import com.intellij.psi.JavaTokenType; import com.intellij.psi.TokenType; -import com.intellij.psi.impl.source.codeStyle.JavaLikeLangLineIndentProvider; +import com.intellij.psi.impl.source.codeStyle.lineIndent.JavaLikeLangLineIndentProvider; import com.intellij.psi.impl.source.codeStyle.SemanticEditorPosition; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.psi.impl.source.codeStyle.JavaLikeLangLineIndentProvider.JavaLikeElement.*; +import static com.intellij.psi.impl.source.codeStyle.lineIndent.JavaLikeLangLineIndentProvider.JavaLikeElement.*; /** * @author Rustam Vishnyakov diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index 47e70cd0b247..ed2ddf2f8abe 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -337,7 +337,13 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { final PsiClass[] sources = entry.getValue(); if (psiFile instanceof PsiClassOwner && sources != null) { final PsiFile createdFile = copy(psiFile, targetDirectory, copyClassName, map == null ? null : map.get(psiFile), choice); - if (createdFile == null) return null; + if (createdFile == null) { + //do not touch unmodified classes + for (PsiClass aClass : ((PsiClassOwner)psiFile).getClasses()) { + oldToNewMap.remove(aClass); + } + continue; + } for (final PsiClass destination : ((PsiClassOwner)createdFile).getClasses()) { if (isSynthetic(destination)) { continue; diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/RepeatCount.java b/java/java-runtime/src/com/intellij/rt/execution/junit/RepeatCount.java similarity index 100% rename from plugins/junit_rt/src/com/intellij/rt/execution/junit/RepeatCount.java rename to java/java-runtime/src/com/intellij/rt/execution/junit/RepeatCount.java diff --git a/java/java-runtime/src/com/intellij/rt/execution/testFrameworks/ForkedSplitter.java b/java/java-runtime/src/com/intellij/rt/execution/testFrameworks/ForkedSplitter.java index 3b9b8b282f78..3e124dd2d4d8 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/testFrameworks/ForkedSplitter.java +++ b/java/java-runtime/src/com/intellij/rt/execution/testFrameworks/ForkedSplitter.java @@ -15,6 +15,8 @@ */ package com.intellij.rt.execution.testFrameworks; +import com.intellij.rt.execution.junit.RepeatCount; + import java.io.File; import java.io.IOException; import java.io.PrintStream; @@ -39,9 +41,13 @@ public abstract class ForkedSplitter extends ForkedByModuleSplitter { } sendTree(myRootDescription); if (myWorkingDirsPath == null || new File(myWorkingDirsPath).length() == 0) { + final String classpath = System.getProperty("java.class.path"); + if (RepeatCount.getCount(repeatCount) != 0 && myForkMode.equals("repeat")) { + return startChildFork(createChildArgs(myRootDescription), null, classpath, repeatCount); + } final List children = getChildren(myRootDescription); final boolean forkTillMethod = myForkMode.equalsIgnoreCase("method"); - return splitChildren(children, 0, forkTillMethod, null, System.getProperty("java.class.path"), repeatCount); + return splitChildren(children, 0, forkTillMethod, null, classpath, repeatCount); } else { return splitPerModule(repeatCount); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/FieldDeclaredInFileWithoutFunctionalInterfaces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/FieldDeclaredInFileWithoutFunctionalInterfaces.java new file mode 100644 index 000000000000..e56083252085 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/findUsages/FieldDeclaredInFileWithoutFunctionalInterfaces.java @@ -0,0 +1,3 @@ +public interface I { + void m(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeMethodJavadoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeMethodJavadoc.java new file mode 100644 index 000000000000..8c2eb8083c54 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeMethodJavadoc.java @@ -0,0 +1,13 @@ +// "Replace with lambda" "false" +class Test { + { + Runnable r = new Runnable() { + /** + * important javadoc + */ + @Override + public void run() { + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterComments.java new file mode 100644 index 000000000000..5bedd1497aa8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterComments.java @@ -0,0 +1,13 @@ +// "Replace with method reference" "true" +class Test { + + private void doTest (){} + + void foo(Runnable r){} + + { + //some comment + foo (this::doTest); + } + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeComments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeComments.java new file mode 100644 index 000000000000..e4c8b906079a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeComments.java @@ -0,0 +1,18 @@ +// "Replace with method reference" "true" +class Test { + + private void doTest (){} + + void foo(Runnable r){} + + { + foo (new Runnable() { + @Override + public void run() { + //some comment + doTest(); + } + }); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java index fdccb3c34cdd..cc967135b311 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.lambda; import com.intellij.JavaTestUtil; +import com.intellij.idea.Bombed; import com.intellij.psi.*; import com.intellij.psi.impl.search.JavaFunctionalExpressionSearcher; import com.intellij.psi.search.GlobalSearchScope; @@ -26,31 +27,45 @@ import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; +import java.util.Calendar; import java.util.Collection; import java.util.function.Predicate; public class FindFunctionalInterfaceTest extends LightCodeInsightFixtureTestCase { public void testMethodArgument() throws Exception { - myFixture.configureByFile(getTestName(false) + ".java"); - final PsiElement elementAtCaret = myFixture.getElementAtCaret(); - assertNotNull(elementAtCaret); - final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false); - assertTrue(psiClass != null && psiClass.isInterface()); - final Collection expressions = FunctionalExpressionSearch.search(psiClass).findAll(); - assertTrue(expressions.size() == 1); - final PsiFunctionalExpression next = expressions.iterator().next(); - assertNotNull(next); - assertEquals("() -> {}", next.getText()); + doTestOneExpression(); } public void testMethodArgumentByTypeParameter() throws Exception { + doTestOneExpression(); + } + + @Bombed(month = Calendar.AUGUST, day = 1, user = "ann peter") + public void testFieldDeclaredInFileWithoutFunctionalInterfaces() throws Exception { + myFixture.addClass("class B {" + + " void f(A a) {" + + " a.r = () -> {};" + + " }" + + "}"); + myFixture.addClass("public class A {" + + " public I r;" + + "}"); + for (int i = 0; i < JavaFunctionalExpressionSearcher.SMART_SEARCH_THRESHOLD + 1; i++) { + myFixture.addClass("class B" + i + " { {Runnable r = () -> {};}}"); //ensure common case is used + } + + doTestOneExpression(); + } + + private void doTestOneExpression() { myFixture.configureByFile(getTestName(false) + ".java"); final PsiElement elementAtCaret = myFixture.getElementAtCaret(); assertNotNull(elementAtCaret); final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false); assertTrue(psiClass != null && psiClass.isInterface()); final Collection expressions = FunctionalExpressionSearch.search(psiClass).findAll(); - assertTrue(expressions.size() == 1); + int size = expressions.size(); + assertEquals(1, size); final PsiFunctionalExpression next = expressions.iterator().next(); assertNotNull(next); assertEquals("() -> {}", next.getText()); diff --git a/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt b/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt index ab7fe6a8b8df..6424974bad14 100644 --- a/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt +++ b/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt @@ -16,7 +16,8 @@ package com.intellij.testIntergration import com.intellij.execution.RunnerAndConfigurationSettings -import com.intellij.execution.testframework.sm.runner.states.TestStateInfo +import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.FAILED_INDEX +import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.PASSED_INDEX import com.intellij.testFramework.LightIdeaTestCase import com.intellij.testIntegration.RecentTestsData import org.assertj.core.api.Assertions.assertThat @@ -24,6 +25,9 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import java.util.* +fun String.suite() = "java:suite://$this" +fun String.test() = "java:test://$this" + class RecentTestsStepTest: LightIdeaTestCase() { lateinit var data: RecentTestsData @@ -38,16 +42,24 @@ class RecentTestsStepTest: LightIdeaTestCase() { `when`(allTests.name).thenAnswer { "all tests" } now = Date() } + + fun `test show suites without run configuration`() { + data.addTest("Test.x".test(), PASSED_INDEX, now, null) + data.addSuite("Test".suite(), PASSED_INDEX, now, null) + + val tests = data.getTestsToShow() + assertThat(tests).hasSize(1) + } fun `test all tests passed`() { - data.addTest("java:test://Test.textXXX", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addSuite("java:suite://Test", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addSuite("java:suite://JavaFormatterSuperDuperTest", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addTest("java:test://Test.textYYY", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addTest("java:test://Test.textZZZ", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addTest("java:test://Test.textQQQ", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) + data.addTest("Test.textXXX".test(), PASSED_INDEX, now, allTests) + data.addSuite("Test".suite(), PASSED_INDEX, now, allTests) + data.addSuite("JFSDTest".suite(), PASSED_INDEX, now, allTests) + data.addTest("Test.textYYY".test(), PASSED_INDEX, now, allTests) + data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), PASSED_INDEX, now, allTests) + data.addTest("Test.textZZZ".test(), PASSED_INDEX, now, allTests) + data.addTest("Test.textQQQ".test(), PASSED_INDEX, now, allTests) + data.addTest("JFSDTest.testUnconditionalAlignmentErrorneous".test(), PASSED_INDEX, now, allTests) val tests = data.getTestsToShow() assertThat(tests).hasSize(1) @@ -56,31 +68,31 @@ class RecentTestsStepTest: LightIdeaTestCase() { fun `test if one failed in run configuration show failed suite`() { - data.addSuite("java:suite://JavaFormatterSuperDuperTest", TestStateInfo.Magnitude.FAILED_INDEX, now, allTests) - data.addSuite("java:suite://Test", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) + data.addSuite("JFSDTest".suite(), FAILED_INDEX, now, allTests) + data.addSuite("Test".test(), PASSED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt", TestStateInfo.Magnitude.FAILED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) + data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), FAILED_INDEX, now, allTests) + data.addTest("JFSDTest.testUnconditionalAlignmentErrorneous".test(), PASSED_INDEX, now, allTests) - data.addTest("java:test://Test.textXXX", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) + data.addTest("Test.textXXX".test(), PASSED_INDEX, now, allTests) val tests = data.getTestsToShow() assertThat(tests).hasSize(2) - assertThat(tests[0].presentation).isEqualTo("JavaFormatterSuperDuperTest") + assertThat(tests[0].presentation).isEqualTo("JFSDTest") assertThat(tests[1].presentation).isEqualTo("all tests") } fun `test if configuration with single test show failed test`() { - data.addSuite("java:suite://JavaFormatterSuperDuperTest", TestStateInfo.Magnitude.FAILED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt", TestStateInfo.Magnitude.FAILED_INDEX, now, allTests) - data.addTest("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", TestStateInfo.Magnitude.PASSED_INDEX, now, allTests) + data.addSuite("JFSDTest".suite(), FAILED_INDEX, now, allTests) + data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), FAILED_INDEX, now, allTests) + data.addTest("JFSDTest.testUnconditionalAlignmentErrorneous".test(), PASSED_INDEX, now, allTests) val tests = data.getTestsToShow() assertThat(tests).hasSize(2) - assertThat(tests[0].presentation).isEqualTo("JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt") - assertThat(tests[1].presentation).isEqualTo("JavaFormatterSuperDuperTest") + assertThat(tests[0].presentation).isEqualTo("JFSDTest.testItMakesMeSadToFixIt") + assertThat(tests[1].presentation).isEqualTo("JFSDTest") } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightUtil.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightUtil.java new file mode 100644 index 000000000000..23115b9fb39b --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightUtil.java @@ -0,0 +1,39 @@ +/* + * 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.codeInsight.daemon.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.TokenType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DefaultHighlightUtil { + @Nullable + public static HighlightInfo checkBadCharacter(@NotNull PsiElement element) { + ASTNode node = element.getNode(); + if (node != null && node.getElementType() == TokenType.BAD_CHARACTER) { + char c = element.textToCharArray()[0]; + boolean printable = StringUtil.isPrintableUnicode(c) && !Character.isSpaceChar(c); + String hex = String.format("U+%04X", (int)c); + String text = "Illegal character: " + (printable ? c + " (" + hex + ")" : hex); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(text).create(); + } + + return null; + } +} \ No newline at end of file diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java index 029a920ded25..d13095f4c1ad 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.daemon.impl; import com.intellij.codeInsight.daemon.impl.analysis.ErrorQuickFixProvider; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; import com.intellij.codeInsight.highlighting.HighlightErrorFilter; -import com.intellij.lang.ASTNode; import com.intellij.lang.LanguageUtil; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.Annotator; @@ -29,7 +28,10 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiErrorElement; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -47,18 +49,22 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { private final DumbService myDumbService; private HighlightInfoHolder myHolder; private final boolean myBatchMode; - private final CachedAnnotators cachedAnnotators; + private final CachedAnnotators myCachedAnnotators; @SuppressWarnings("UnusedDeclaration") DefaultHighlightVisitor(@NotNull Project project, @NotNull CachedAnnotators cachedAnnotators) { this(project, true, true, false, cachedAnnotators); } - DefaultHighlightVisitor(@NotNull Project project, boolean highlightErrorElements, boolean runAnnotators, boolean batchMode, @NotNull CachedAnnotators cachedAnnotators) { + DefaultHighlightVisitor(@NotNull Project project, + boolean highlightErrorElements, + boolean runAnnotators, + boolean batchMode, + @NotNull CachedAnnotators cachedAnnotators) { myProject = project; myHighlightErrorElements = highlightErrorElements; myRunAnnotators = runAnnotators; - this.cachedAnnotators = cachedAnnotators; + myCachedAnnotators = cachedAnnotators; myErrorFilters = Extensions.getExtensions(HighlightErrorFilter.EP_NAME, project); myDumbService = DumbService.getInstance(project); myBatchMode = batchMode; @@ -93,15 +99,6 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { if (myHighlightErrorElements) visitErrorElement((PsiErrorElement)element); } else { - ASTNode node = element.getNode(); - if (node != null && node.getElementType() == TokenType.BAD_CHARACTER) { - char c = element.textToCharArray()[0]; - boolean printable = StringUtil.isPrintableUnicode(c) && !Character.isSpaceChar(c); - String hex = String.format("U+%04X", (int)c); - String text = "Illegal character: " + (printable ? c + " (" + hex + ")" : hex); - myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(text).create()); - } - if (myRunAnnotators) runAnnotators(element); } @@ -117,7 +114,7 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { @Override @NotNull public HighlightVisitor clone() { - return new DefaultHighlightVisitor(myProject, myHighlightErrorElements, myRunAnnotators, myBatchMode,cachedAnnotators); + return new DefaultHighlightVisitor(myProject, myHighlightErrorElements, myRunAnnotators, myBatchMode, myCachedAnnotators); } @Override @@ -126,7 +123,7 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { } private void runAnnotators(PsiElement element) { - List annotators = cachedAnnotators.get(element.getLanguage().getID()); + List annotators = myCachedAnnotators.get(element.getLanguage().getID()); if (annotators.isEmpty()) return; final boolean dumb = myDumbService.isDumb(); @@ -203,4 +200,4 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware { } return info; } -} +} \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 7d6673ece18f..2b64e76ba2ba 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -533,30 +533,34 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen @Override public void performLaterWhenAllCommitted(@NotNull final Runnable runnable) { - final ModalityState modalityState = ModalityState.current(); - UIUtil.invokeLaterIfNeeded(new Runnable() { + final ModalityState modalityState = ModalityState.defaultModalityState(); + final Runnable whenAllCommitted = new Runnable() { @Override public void run() { - performWhenAllCommitted(new Runnable() { + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - // later because we may end up in write action here if there was a synchronous commit - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (hasUncommitedDocuments()) { - // no luck, will try later - performLaterWhenAllCommitted(runnable); - } - else { - runnable.run(); - } - } - }, modalityState, myProject.getDisposed()); + if (hasUncommitedDocuments()) { + // no luck, will try later + performLaterWhenAllCommitted(runnable); + } + else { + runnable.run(); + } } - }); + }, modalityState, myProject.getDisposed()); } - }); + }; + if (ApplicationManager.getApplication().isDispatchThread() && isInsideCommitHandler()) { + whenAllCommitted.run(); + } else { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + performWhenAllCommitted(whenAllCommitted); + } + }); + } } private static class CompositeRunnable extends ArrayList implements Runnable { @@ -586,7 +590,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen if (!hasUncommitedDocuments() && !actionsWhenAllDocumentsAreCommitted.isEmpty()) { List> entries = new ArrayList>(new LinkedHashMap(actionsWhenAllDocumentsAreCommitted).entrySet()); - weAreInsideAfterCommitHandler(); + beforeCommitHandler(); try { for (Map.Entry entry : entries) { @@ -605,15 +609,19 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen } } - private void weAreInsideAfterCommitHandler() { + private void beforeCommitHandler() { actionsWhenAllDocumentsAreCommitted.put(PERFORM_ALWAYS_KEY, EmptyRunnable.getInstance()); // to prevent listeners from registering new actions during firing } private void checkWeAreOutsideAfterCommitHandler() { - if (actionsWhenAllDocumentsAreCommitted.get(PERFORM_ALWAYS_KEY) == EmptyRunnable.getInstance()) { + if (isInsideCommitHandler()) { throw new IncorrectOperationException("You must not call performWhenAllCommitted()/cancelAndRunWhenCommitted() from within after-commit handler"); } } + private boolean isInsideCommitHandler() { + return actionsWhenAllDocumentsAreCommitted.get(PERFORM_ALWAYS_KEY) == EmptyRunnable.getInstance(); + } + @Override public void addListener(@NotNull Listener listener) { myListeners.add(listener); diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/AstPathPsiMap.java b/platform/core-impl/src/com/intellij/psi/impl/source/AstPathPsiMap.java index 50764706ca1e..0be43afc1577 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/AstPathPsiMap.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/AstPathPsiMap.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.source; +import com.intellij.concurrency.JobScheduler; import com.intellij.extapi.psi.StubBasedPsiElementBase; import com.intellij.psi.impl.source.tree.AstPath; import com.intellij.psi.impl.source.tree.CompositeElement; @@ -26,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; /** * A weak cache for all instantiated stub-based PSI to allow {@link CompositeElement#getPsi()} return it when AST is reloaded.

@@ -39,6 +41,16 @@ class AstPathPsiMap { */ private final ConcurrentMap myMap = ContainerUtil.newConcurrentMap(); + static { + JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + // clean up AstPath objects when no PSI is accessed, e.g. after project closing + processQueue(); + } + }, 5, 5, TimeUnit.SECONDS); + } + void invalidatePsi() { processQueue(); for (MyReference reference : myMap.values()) { diff --git a/platform/util/src/com/intellij/openapi/extensions/AreaPicoContainer.java b/platform/extensions/src/com/intellij/openapi/extensions/AreaPicoContainer.java similarity index 100% rename from platform/util/src/com/intellij/openapi/extensions/AreaPicoContainer.java rename to platform/extensions/src/com/intellij/openapi/extensions/AreaPicoContainer.java diff --git a/platform/util/src/com/intellij/util/pico/AssignableToComponentAdapter.java b/platform/extensions/src/com/intellij/util/pico/AssignableToComponentAdapter.java similarity index 100% rename from platform/util/src/com/intellij/util/pico/AssignableToComponentAdapter.java rename to platform/extensions/src/com/intellij/util/pico/AssignableToComponentAdapter.java diff --git a/platform/util/src/com/intellij/util/pico/ConstructorInjectionComponentAdapter.java b/platform/extensions/src/com/intellij/util/pico/ConstructorInjectionComponentAdapter.java similarity index 100% rename from platform/util/src/com/intellij/util/pico/ConstructorInjectionComponentAdapter.java rename to platform/extensions/src/com/intellij/util/pico/ConstructorInjectionComponentAdapter.java diff --git a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java similarity index 99% rename from platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java rename to platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java index f569c2060090..0624371db0ac 100644 --- a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java +++ b/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.*; import org.picocontainer.defaults.*; +import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; import java.io.Serializable; import java.util.*; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProvider.java b/platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProvider.java similarity index 97% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProvider.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProvider.java index 78b5dcce0554..d2baf99b9cbe 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProvider.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.impl.source.codeStyle; +package com.intellij.psi.codeStyle.lineIndent; import com.intellij.lang.Language; import com.intellij.openapi.editor.Editor; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProviderEP.java b/platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProviderEP.java similarity index 92% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProviderEP.java rename to platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProviderEP.java index d1f2c9f34a0f..3b7176609b73 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/LineIndentProviderEP.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/lineIndent/LineIndentProviderEP.java @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.impl.source.codeStyle; +package com.intellij.psi.codeStyle.lineIndent; import com.intellij.lang.Language; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.codeStyle.lineIndent.LineIndentProvider; import org.jetbrains.annotations.Nullable; /** diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java index 8473af9a7196..2ca18f1d0c7b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java @@ -27,9 +27,10 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.lineIndent.LineIndentProvider; +import com.intellij.psi.codeStyle.lineIndent.LineIndentProviderEP; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/FormatterBasedLineIndentProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/FormatterBasedLineIndentProvider.java similarity index 92% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/FormatterBasedLineIndentProvider.java rename to platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/FormatterBasedLineIndentProvider.java index 7de5a996cddd..38e2812b02d5 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/FormatterBasedLineIndentProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/FormatterBasedLineIndentProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.impl.source.codeStyle; +package com.intellij.psi.impl.source.codeStyle.lineIndent; import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.lineIndent.LineIndentProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/JavaLikeLangLineIndentProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/JavaLikeLangLineIndentProvider.java similarity index 95% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/JavaLikeLangLineIndentProvider.java rename to platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/JavaLikeLangLineIndentProvider.java index 15c681139c0c..b722136fd402 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/JavaLikeLangLineIndentProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/lineIndent/JavaLikeLangLineIndentProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.impl.source.codeStyle; +package com.intellij.psi.impl.source.codeStyle.lineIndent; import com.intellij.formatting.IndentInfo; import com.intellij.lang.Language; @@ -26,6 +26,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.impl.source.codeStyle.SemanticEditorPosition; import com.intellij.psi.impl.source.codeStyle.SemanticEditorPosition.SyntaxElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.text.CharArrayUtil; @@ -34,7 +35,7 @@ import org.jetbrains.annotations.Nullable; import static com.intellij.formatting.Indent.Type; import static com.intellij.formatting.Indent.Type.*; -import static com.intellij.psi.impl.source.codeStyle.JavaLikeLangLineIndentProvider.JavaLikeElement.*; +import static com.intellij.psi.impl.source.codeStyle.lineIndent.JavaLikeLangLineIndentProvider.JavaLikeElement.*; /** * A base class Java-like language line indent provider. If JavaLikeLangLineIndentProvider is unable to calculate @@ -88,6 +89,11 @@ public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineI )) { return createIndentData(CONTINUATION, ArrayOpeningBracket); } + else if (getPosition(editor, offset).matchesRule( + position -> position.before().isAt(LeftParenthesis) + )) { + return createIndentData(CONTINUATION, LeftParenthesis); + } else if (getPosition(editor, offset).matchesRule( position -> position.before().isAt(BlockOpeningBrace) )) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 11d2b26b95be..ce40c9c714c5 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -44,6 +44,7 @@ import com.intellij.ui.UIBundle; import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.components.JBOptionButton; import com.intellij.ui.components.JBScrollPane; +import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.TimeoutUtil; @@ -468,8 +469,15 @@ public abstract class DialogWrapper { actions = ArrayUtil.remove(actions, getHelpAction()); } - JPanel panel = new JPanel(new BorderLayout()); - final JPanel lrButtonsPanel = new JPanel(new GridBagLayout()); + JPanel panel = new JPanel(new BorderLayout()) { + @Override + public Color getBackground() { + final Color bg = UIManager.getColor("DialogWrapper.southPanelBackground"); + return bg != null ? bg : super.getBackground(); + } + }; + final JPanel lrButtonsPanel = new NonOpaquePanel(new GridBagLayout()); + //noinspection UseDPIAwareInsets final Insets insets = SystemInfo.isMacOSLeopard ? UIUtil.isUnderIntelliJLaF() ? JBUI.insets(0, 8) : JBUI.emptyInsets() : new Insets(8, 0, 0, 0); //don't wrap to JBInsets if (actions.length > 0 || leftSideActions.length > 0) { @@ -551,12 +559,12 @@ public abstract class DialogWrapper { } if (getStyle() == DialogStyle.COMPACT) { - Border line = new CustomLineBorder(OnePixelDivider.BACKGROUND, 1, 0, 0, 0); + final Color color = UIManager.getColor("DialogWrapper.southPanelDivider"); + Border line = new CustomLineBorder(color != null ? color : OnePixelDivider.BACKGROUND, 1, 0, 0, 0); panel.setBorder(new CompoundBorder(line, JBUI.Borders.empty(8, 12))); } else { panel.setBorder(JBUI.Borders.emptyTop(8)); } - return panel; } @@ -636,7 +644,7 @@ public abstract class DialogWrapper { } } - JPanel buttonsPanel = new JPanel(new GridLayout(1, actions.length, SystemInfo.isMacOSLeopard ? UIUtil.isUnderIntelliJLaF() ? 8 : 0 : 5, 0)); + JPanel buttonsPanel = new NonOpaquePanel(new GridLayout(1, actions.length, SystemInfo.isMacOSLeopard ? UIUtil.isUnderIntelliJLaF() ? 8 : 0 : 5, 0)); for (final Action action : actions) { JButton button = createJButtonForAction(action); final Object value = action.getValue(Action.MNEMONIC_KEY); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java index d92d97b001b9..1312dabe6064 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -36,7 +36,10 @@ import java.awt.event.MouseEvent; * @author Konstantin Bulenkov */ public class OnePixelDivider extends Divider { - public static final Color BACKGROUND = new JBColor(Gray.xC5, Gray.x51); + public static final Color BACKGROUND = new JBColor(() -> { + final Color bg = UIManager.getColor("OnePixelDivider.background"); + return bg != null ? bg : new JBColor(Gray.xC5, Gray.x51); + }); private boolean myVertical; private Splittable mySplitter; diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java index edf9be653c90..3bf162eacf61 100644 --- a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java +++ b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java @@ -187,6 +187,7 @@ public class CheckBoxList extends JBList { public void addItem(T item, String text, boolean selected) { JCheckBox checkBox = new JCheckBox(text, selected); + checkBox.setOpaque(true); // to paint selection background myItemMap.put(item, checkBox); //noinspection unchecked ((DefaultListModel)getModel()).addElement(checkBox); diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java index cbca7f173ad9..6558ab3f7d2b 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableModelAdapter.java @@ -22,6 +22,7 @@ import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.table.AbstractTableModel; import javax.swing.tree.TreePath; +import java.util.concurrent.atomic.AtomicInteger; /** * This is a wrapper class takes a TreeTableModel and implements @@ -35,6 +36,9 @@ import javax.swing.tree.TreePath; * @author Scott Violet */ public class TreeTableModelAdapter extends AbstractTableModel { + + private final AtomicInteger modificationStamp = new AtomicInteger(); + private final JTree tree; private final TreeTableModel treeTableModel; private final JTable table; @@ -123,7 +127,12 @@ public class TreeTableModelAdapter extends AbstractTableModel { * processed. SwingUtilities.invokeLater is used to handle this. */ protected void delayedFireTableDataChanged() { - SwingUtilities.invokeLater(() -> fireTableDataChanged()); + long stamp = modificationStamp.incrementAndGet(); + //noinspection SSBasedInspection + SwingUtilities.invokeLater(() -> { + if (stamp != modificationStamp.get()) return; + fireTableDataChanged(); + }); } public void fireTableDataChanged() { diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index b1a453727bd7..33815d491c1d 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -949,6 +949,9 @@ public class HintManagerImpl extends HintManager implements Disposable { myQuestionAction = null; myQuestionHint = null; + if (myLastEditor != null && project == myLastEditor.getProject()) { + updateLastEditor(null); + } } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java index 5abe61cefbda..a4c18667b0cb 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java @@ -162,13 +162,19 @@ public class DarculaButtonUI extends BasicButtonUI { @Override public void update(Graphics g, JComponent c) { super.update(g, c); - if (isDefaultButton(c) && !SystemInfo.isMac) { - if (!c.getFont().isBold()) { - c.setFont(new FontUIResource(c.getFont().deriveFont(Font.BOLD))); + if (isDefaultButton(c)) { + setupDefaultButton((JButton)c); + } + } + + protected void setupDefaultButton(JButton button) { + if (!SystemInfo.isMac) { + if (!button.getFont().isBold()) { + button.setFont(new FontUIResource(button.getFont().deriveFont(Font.BOLD))); } } } - + public static boolean isHelpButton(JComponent button) { return (SystemInfo.isMac || (SystemInfo.isWindows && Registry.is("ide.intellij.laf.win10.ui"))) && button instanceof JButton diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonPainter.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonPainter.java index 43592a33e577..72cf7a73989a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonPainter.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonPainter.java @@ -35,15 +35,9 @@ public class WinIntelliJButtonPainter implements Border, UIResource { @Override public void paintBorder(Component c, Graphics graphics, int x, int y, int width, int height) { Graphics2D g = (Graphics2D)graphics; - final Insets ins = getBorderInsets(c); - final int yOff = (ins.top + ins.bottom) / 4; - final boolean square = DarculaButtonUI.isSquare(c); - int offset = JBUI.scale(square ? 1 : getOffset()); - int w = c.getWidth(); - int h = c.getHeight(); - int diam = JBUI.scale(22); - - if (c.hasFocus() || DarculaButtonUI.isDefaultButton((JComponent)c)) { + final boolean hasFocus = c.hasFocus(); + final boolean isDefault = DarculaButtonUI.isDefaultButton((JComponent)c); + if (hasFocus || isDefault) { if (DarculaButtonUI.isHelpButton((JComponent)c)) { //todo } else { @@ -52,7 +46,7 @@ public class WinIntelliJButtonPainter implements Border, UIResource { g.translate(x,y); g.drawRect(JBUI.scale(1), JBUI.scale(1), width-2*JBUI.scale(1), height-2*JBUI.scale(1)); - if (c.hasFocus()) { + if (hasFocus) { g.setStroke(new BasicStroke(JBUI.scale(1f))); g.setColor(Gray.x00); UIUtil.drawDottedRectangle(g, JBUI.scale(1) + 1, JBUI.scale(1) + 1, width-2*JBUI.scale(1) - 1, height-2*JBUI.scale(1) - 1); @@ -72,12 +66,12 @@ public class WinIntelliJButtonPainter implements Border, UIResource { @Override public Insets getBorderInsets(Component c) { if (c.getParent() instanceof ActionToolbar) { - return JBUI.insets(4, 16, 4, 16); + return JBUI.insets(4, 16).asUIResource(); } if (DarculaButtonUI.isSquare(c)) { - return JBUI.insets(2, 0, 2, 0).asUIResource(); + return JBUI.insets(2, 0).asUIResource(); } - return JBUI.insets(3, 17, 3, 15).asUIResource(); + return JBUI.insets(3, 17).asUIResource(); } protected int getOffset() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonUI.java index 98d2718ee8d9..7ac4613cc805 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJButtonUI.java @@ -74,6 +74,11 @@ public class WinIntelliJButtonUI extends DarculaButtonUI { return true; } + @Override + protected void setupDefaultButton(JButton button) { + //do nothing + } + @Override protected void paintDisabledText(Graphics g, String text, JComponent c, Rectangle textRect, FontMetrics metrics) { g.setColor(UIManager.getColor("Button.disabledText")); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJCheckBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJCheckBoxUI.java index e5e7272a8dc1..8bbe1c252804 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJCheckBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJCheckBoxUI.java @@ -67,4 +67,9 @@ public class WinIntelliJCheckBoxUI extends IntelliJCheckBoxUI { UIUtil.drawDottedRectangle(g, textRect.x - 2, textRect.y - 1, textRect.width + textRect.x + 1, textRect.height + 3); } } + + @Override + public Icon getDefaultIcon() { + return JBUI.emptyIcon(18).asUIResource(); + } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties index d7e706395cd6..dcc1e3710cd0 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties @@ -18,6 +18,9 @@ textInactiveText=999999 textText=000000 infoText=000000 OptionPane.messageForeground=000000 +DialogWrapper.southPanelDivider=f0f0f0 +DialogWrapper.southPanelBackground=f0f0f0 +OnePixelDivider.background=ffffff Menu.maxGutterIconWidth=18 MenuItem.maxGutterIconWidth=18 diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index b1d266303395..dd2315af8b49 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -289,7 +289,7 @@ - + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index b6d60fe42d55..6374f7eb25fe 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -953,7 +953,7 @@ - + diff --git a/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java index 221c3413d837..e311e1a04c75 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java @@ -671,4 +671,22 @@ public class PsiDocumentManagerImplTest extends PlatformTestCase { assertTrue(PsiDocumentManager.getInstance(myProject).isCommitted(document)); } + @SuppressWarnings("ConstantConditions") + public void testPerformLaterWhenAllCommittedFromCommitHandler() throws Exception { + PsiFile file = getPsiManager().findFile(getVirtualFile(createTempFile("X.txt", ""))); + Document document = file.getViewProvider().getDocument(); + + PsiDocumentManager pdm = PsiDocumentManager.getInstance(myProject); + WriteCommandAction.runWriteCommandAction(null, () -> document.insertString(0, "a")); + pdm.performWhenAllCommitted( + () -> pdm.performLaterWhenAllCommitted( + () -> WriteCommandAction.runWriteCommandAction(null, () -> document.insertString(1, "b")))); + + assertTrue(pdm.hasUncommitedDocuments()); + assertEquals("a", document.getText()); + + DocumentCommitThread.getInstance().waitForAllCommits(); + assertEquals("ab", document.getText()); + } + } diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java b/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java index 2dd983353f16..8ec737a0bc87 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java @@ -58,10 +58,16 @@ public abstract class UsageContextPanelBase extends JPanel implements UsageConte @Override public final void updateLayout(@Nullable final List infos) { - PsiDocumentManager.getInstance(myProject).performLaterWhenAllCommitted(() -> { - if (isDisposed || myProject.isDisposed()) return; + PsiDocumentManager pdm = PsiDocumentManager.getInstance(myProject); + if (!pdm.hasUncommitedDocuments()) { updateLayoutLater(infos); - }); + } else { + pdm.performLaterWhenAllCommitted(() -> { + if (isDisposed || myProject.isDisposed()) return; + updateLayoutLater(infos); + }); + } + } protected abstract void updateLayoutLater(@Nullable List infos); diff --git a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java index 6cdc38e60b53..f323abb22c45 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java @@ -17,6 +17,7 @@ package com.intellij.usages.impl; import com.intellij.lang.injection.InjectedLanguageManager; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; @@ -34,6 +35,7 @@ import com.intellij.usageView.UsageViewBundle; import com.intellij.usages.UsageContextPanel; import com.intellij.usages.UsageView; import com.intellij.usages.UsageViewPresentation; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,7 +46,7 @@ import java.util.List; /** * @author cdr */ -public class UsagePreviewPanel extends UsageContextPanelBase { +public class UsagePreviewPanel extends UsageContextPanelBase implements DataProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.usages.impl.UsagePreviewPanel"); private Editor myEditor; private final boolean myIsEditor; @@ -61,6 +63,15 @@ public class UsagePreviewPanel extends UsageContextPanelBase { myIsEditor = isEditor; } + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (CommonDataKeys.EDITOR.getName().equals(dataId) && myEditor != null) { + return myEditor; + } + return null; + } + public static class Provider implements UsageContextPanel.Provider { @NotNull @Override @@ -211,6 +222,8 @@ public class UsagePreviewPanel extends UsageContextPanelBase { } } + + @Override public void updateLayoutLater(@Nullable final List infos) { if (infos == null) { diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index ad2819ecd883..26ae90a2a369 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -1572,7 +1572,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra VirtualFile[] data = UsageDataUtil.provideVirtualFileArray(ua, getSelectedUsageTargets()); sink.put(CommonDataKeys.VIRTUAL_FILE_ARRAY, data); } - + else if (key == CommonDataKeys.EDITOR && myCurrentUsageContextPanel instanceof DataProvider) { + Object editor = ((DataProvider)myCurrentUsageContextPanel).getData(key.getName()); + if (editor != null) sink.put(key, editor); + } else if (key == PlatformDataKeys.HELP_ID) { sink.put(PlatformDataKeys.HELP_ID, HELP_ID); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index f7ac6808e474..50b263a9ba16 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -268,7 +268,7 @@ vcs.log.recent.commits.count=1000 vcs.log.recent.commits.count.description=Before full log is loaded (which can take some time), a number of recent commits is loaded to show quickly vcs.log.open.another.log.visible=false vcs.log.open.another.log.visible.description=An action that opens a new tab with log -vcs.log.keep.up.to.date=false +vcs.log.keep.up.to.date=true vcs.log.keep.up.to.date.description=Load log on start after heavy tasks are completed and keep it up to date even when not visible vcs.executable.validator.timeout.sec=60 diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index f76b29a37d5b..ea69e529f687 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -33,7 +33,6 @@ import org.jdom.Document; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.picocontainer.PicoContainer; import java.io.*; import java.net.URL; @@ -455,7 +454,6 @@ public class PathManager { Document.class, // jDOM Appender.class, // log4j THashSet.class, // trove4j - PicoContainer.class, // PicoContainer TypeMapper.class, // JNA FileUtils.class, // JNA (jna-platform) PatternMatcher.class, // OROMatcher diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index a17feb37587e..e6235c2a36d7 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -98,6 +98,10 @@ public class FileUtil extends FileUtilRt { return new File(path).isAbsolute(); } + public static boolean exists(@Nullable String path) { + return path != null && new File(path).exists(); + } + /** * Check if the {@code ancestor} is an ancestor of {@code file}. * diff --git a/platform/util/util.iml b/platform/util/util.iml index 6a9a8e8049f5..e5314d8d8076 100644 --- a/platform/util/util.iml +++ b/platform/util/util.iml @@ -15,7 +15,6 @@ - diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/OverloadedVarargsMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/OverloadedVarargsMethodInspection.java index eab7e149ca4e..edc13b60c5a1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/OverloadedVarargsMethodInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/OverloadedVarargsMethodInspection.java @@ -17,7 +17,9 @@ package com.siyeh.ig.naming; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -65,7 +67,11 @@ public class OverloadedVarargsMethodInspection extends BaseInspection { final String methodName = method.getName(); final PsiMethod[] sameNameMethods = aClass.findMethodsByName(methodName, true); for (PsiMethod sameNameMethod : sameNameMethods) { - if (!MethodSignatureUtil.areSignaturesEqual(sameNameMethod, method)) { + PsiClass superClass = sameNameMethod.getContainingClass(); + PsiSubstitutor substitutor = superClass != null ? TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY) + : PsiSubstitutor.EMPTY; + if (!MethodSignatureUtil.areSignaturesEqual(sameNameMethod.getSignature(substitutor), + method.getSignature(PsiSubstitutor.EMPTY))) { registerMethodError(method, method); return; } diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/OverloadedVarargsMethodInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/OverloadedVarargsMethodInspectionTest.java index 7fdd2709e3b2..5a8aebe72043 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/OverloadedVarargsMethodInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/OverloadedVarargsMethodInspectionTest.java @@ -55,4 +55,14 @@ public class OverloadedVarargsMethodInspectionTest extends LightInspectionTestCa " public void test(String... ss) {}" + "}"); } + + public void testGenericMethods() throws Exception { + doTest("interface Foo {" + + " void makeItSo(T command, int... values);" + + " }" + + " class Bar implements Foo {" + + " public void makeItSo(final String command, final int... values) {" + + " }" + + " }"); + } } diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java index 04fe622e1354..14891d00d147 100644 --- a/plugins/devkit/src/projectRoots/IdeaJdk.java +++ b/plugins/devkit/src/projectRoots/IdeaJdk.java @@ -51,6 +51,8 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static com.intellij.openapi.util.io.FileUtil.toSystemDependentName; + /** * @author anna * @since Nov 22, 2004 @@ -325,8 +327,13 @@ public class IdeaJdk extends JavaDependentSdkType implements JavaSdkType { LocalFileSystem localFileSystem = LocalFileSystem.getInstance(); VirtualFile out = localFileSystem.refreshAndFindFileByPath(sdkHome + OUT_CLASSES); if (out != null) { - for (VirtualFile dir : out.getChildren()) { + List suppressed = Arrays.asList("jps-plugin-system"); + for (VirtualFile dir : JBIterable.of(out.findChild("resources")).append(out.getChildren())) { if (!dir.isDirectory()) continue; + String name = dir.getName(); + if (name.endsWith("-ide") || suppressed.contains(name)) continue; + if (!name.equals("ultimate-resources") && + FileUtil.exists(toSystemDependentName(dir.getPath() + "/META-INF/plugin.xml"))) continue; sdkModificator.addRoot(dir, OrderRootType.CLASSES); } } diff --git a/plugins/devkit/src/run/PluginRunConfiguration.java b/plugins/devkit/src/run/PluginRunConfiguration.java index 8e257a994817..d9bdc0ad0c40 100644 --- a/plugins/devkit/src/run/PluginRunConfiguration.java +++ b/plugins/devkit/src/run/PluginRunConfiguration.java @@ -186,8 +186,6 @@ public class PluginRunConfiguration extends RunConfigurationBase implements Modu if (fromIdeaProject) { for (String url : usedIdeaJdk.getRootProvider().getUrls(OrderRootType.CLASSES)) { String s = StringUtil.trimEnd(VfsUtilCore.urlToPath(url), JarFileSystem.JAR_SEPARATOR); - if (s.endsWith("plugin-system")) continue; - if (new File(toSystemDependentName(s+ "/META-INF/plugin.xml")).exists()) continue; params.getClassPath().add(toSystemDependentName(s)); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 607e247b2eb1..801966a3cb05 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -63,6 +63,7 @@ public class JUnitConfiguration extends JavaTestConfigurationBase { @NonNls public static final String FORK_NONE = "none"; @NonNls public static final String FORK_METHOD = "method"; @NonNls public static final String FORK_KLASS = "class"; + @NonNls public static final String FORK_REPEAT = "repeat"; // See #26522 @NonNls public static final String JUNIT_START_CLASS = "com.intellij.rt.execution.junit.JUnitStarter"; @NonNls private static final String PATTERN_EL_NAME = "pattern"; diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClass.java b/plugins/junit/src/com/intellij/execution/junit/TestClass.java index c3d0d142646d..1ce6428519dc 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClass.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClass.java @@ -20,10 +20,12 @@ import com.intellij.execution.ExecutionBundle; import com.intellij.execution.ExecutionException; import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.configurations.*; +import com.intellij.execution.junit2.configuration.JUnitConfigurationModel; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.refactoring.listeners.RefactoringElementListener; +import org.jetbrains.annotations.NotNull; class TestClass extends TestObject { public TestClass(JUnitConfiguration configuration, ExecutionEnvironment environment) { @@ -38,6 +40,13 @@ class TestClass extends TestObject { return javaParameters; } + @NotNull + @Override + protected String getForkMode() { + String forkMode = super.getForkMode(); + return JUnitConfiguration.FORK_KLASS.equals(forkMode) ? JUnitConfiguration.FORK_REPEAT : forkMode; + } + @Override public String suggestActionName() { String name = getConfiguration().getPersistentData().MAIN_CLASS_NAME; diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 3bf98f3732c8..9fea8e0fcf64 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -233,7 +233,16 @@ public class JUnitConfigurable extends SettingsEdi } } ); - myModel.setType(JUnitConfigurationModel.CLASS); + + myRepeatCb.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if ((Integer) myTypeChooser.getSelectedItem() == JUnitConfigurationModel.CLASS) { + myForkCb.setModel(getForkModelBasedOnRepeat()); + } + } + }); + //myModel.setType(JUnitConfigurationModel.CLASS); installDocuments(); addRadioButtonsListeners(new JRadioButton[]{myWholeProjectScope, mySingleModuleScope, myModuleWDScope}, null); myWholeProjectScope.addChangeListener(new ChangeListener() { @@ -286,6 +295,11 @@ public class JUnitConfigurable extends SettingsEdi } public void resetEditorFrom(final JUnitConfiguration configuration) { + final int count = configuration.getRepeatCount(); + myRepeatCountField.setText(String.valueOf(count)); + myRepeatCountField.setEnabled(count > 1); + myRepeatCb.setSelectedItem(configuration.getRepeatMode()); + myModel.reset(configuration); myCommonJavaParameters.reset(configuration); getModuleSelector().reset(configuration); @@ -302,10 +316,6 @@ public class JUnitConfigurable extends SettingsEdi myJrePathEditor .setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); myForkCb.setSelectedItem(configuration.getForkMode()); - final int count = configuration.getRepeatCount(); - myRepeatCountField.setText(String.valueOf(count)); - myRepeatCountField.setEnabled(count > 1); - myRepeatCb.setSelectedItem(configuration.getRepeatMode()); } private void changePanel () { @@ -346,7 +356,7 @@ public class JUnitConfigurable extends SettingsEdi myCategory.setVisible(false); myMethod.setVisible(false); myForkCb.setEnabled(true); - myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE)); + myForkCb.setModel(getForkModelBasedOnRepeat()); myForkCb.setSelectedItem(selectedItem != JUnitConfiguration.FORK_KLASS ? selectedItem : JUnitConfiguration.FORK_METHOD); } else if (selectedType == JUnitConfigurationModel.METHOD){ @@ -385,6 +395,10 @@ public class JUnitConfigurable extends SettingsEdi } } + private DefaultComboBoxModel getForkModelBasedOnRepeat() { + return new DefaultComboBoxModel(RepeatCount.ONCE.equals(myRepeatCb.getSelectedItem()) ? FORK_MODE : FORK_MODE_ALL); + } + public ModulesComboBox getModulesComponent() { return myModule.getComponent(); } diff --git a/python/src/com/jetbrains/python/psi/resolve/PythonPathCache.java b/python/src/com/jetbrains/python/psi/resolve/PythonPathCache.java index 87a402df3f67..2ff1e388c903 100644 --- a/python/src/com/jetbrains/python/psi/resolve/PythonPathCache.java +++ b/python/src/com/jetbrains/python/psi/resolve/PythonPathCache.java @@ -15,12 +15,15 @@ */ package com.jetbrains.python.psi.resolve; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiElement; import com.intellij.psi.util.QualifiedName; -import com.intellij.util.containers.ConcurrentHashMap; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -28,28 +31,37 @@ import java.util.Map; * @author yole */ public abstract class PythonPathCache { - private final Map> myCache = new ConcurrentHashMap>(); - private final Map> myQNameCache = new ConcurrentHashMap>(); + private final Map> myCache = ContainerUtil.newConcurrentMap(); + private final Map> myQNameCache = ContainerUtil.newConcurrentMap(); public void clearCache() { myCache.clear(); myQNameCache.clear(); } + @Nullable public List get(QualifiedName qualifiedName) { - return myCache.get(qualifiedName); + final List result = myCache.get(qualifiedName); + if (result == null) { + return null; + } + final boolean staleElementRemoved = result.removeIf(e -> !e.isValid()); + if (staleElementRemoved) { + Logger.getInstance(PythonPathCache.class).warn("Removing invalid element from cache"); + } + return (!result.isEmpty() ? result : null); } public void put(QualifiedName qualifiedName, List results) { - myCache.put(qualifiedName, results); + myCache.put(qualifiedName, new ArrayList<>(results)); } public List getNames(VirtualFile vFile) { return myQNameCache.get(vFile); } - + public void putNames(VirtualFile vFile, List qNames) { - myQNameCache.put(vFile, qNames); + myQNameCache.put(vFile, new ArrayList<>(qNames)); } protected class MyVirtualFileAdapter extends VirtualFileAdapter { diff --git a/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java b/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java index bdd921d40aba..b7e9e419b228 100644 --- a/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java +++ b/python/testSrc/com/jetbrains/env/PyProcessWithConsoleTestTask.java @@ -15,12 +15,12 @@ */ package com.jetbrains.env; -import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; @@ -53,6 +53,7 @@ import java.lang.reflect.InvocationTargetException; * @author Ilya.Kazakevich */ public abstract class PyProcessWithConsoleTestTask extends PyExecutionFixtureTestTask { + private static final Logger LOG = Logger.getInstance(PyProcessWithConsoleTestTask.class); @NotNull private final SdkCreationType myRequiredSdkType; @@ -91,6 +92,7 @@ public abstract class PyProcessWithConsoleTestTask + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/xml/XmlEntityManagerCaching.ui.xml b/xml/tests/testData/xml/XmlEntityManagerCaching.ui.xml new file mode 100644 index 000000000000..197ce309c79e --- /dev/null +++ b/xml/tests/testData/xml/XmlEntityManagerCaching.ui.xml @@ -0,0 +1,5 @@ + + + Hello World + \ No newline at end of file diff --git a/xml/tests/testData/xml/xhtml.ent b/xml/tests/testData/xml/xhtml.ent new file mode 100644 index 000000000000..21cbb5442c58 --- /dev/null +++ b/xml/tests/testData/xml/xhtml.ent @@ -0,0 +1 @@ + \ No newline at end of file