From 2340a86d8de16fadb2d18737137a67906665da9d Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 14 Feb 2020 17:42:30 +0300 Subject: [PATCH] Update to 201.5259.13-EAP-SNAPSHOT - No UIUtil.removeLeakingAppleListeners anymore - getParameterHints nullability - versions of lz4-java and guava were changed --- .../build.gradle.kts | 2 +- .../test/testFramework/KtUsefulTestCase.java | 6 + .../testFramework/KtUsefulTestCase.java.201 | 1181 +++++++++++++++++ gradle/versions.properties | 1 + gradle/versions.properties.192 | 1 + gradle/versions.properties.201 | 5 +- gradle/versions.properties.as36 | 1 + gradle/versions.properties.as40 | 1 + .../KotlinInlayParameterHintsProvider.kt | 4 +- prepare/compiler/build.gradle.kts | 2 +- 10 files changed, 1198 insertions(+), 6 deletions(-) create mode 100644 compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java.201 diff --git a/compiler/incremental-compilation-impl/build.gradle.kts b/compiler/incremental-compilation-impl/build.gradle.kts index b76bcf79e9d..2ca58fdf556 100644 --- a/compiler/incremental-compilation-impl/build.gradle.kts +++ b/compiler/incremental-compilation-impl/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { testCompile(intellijDep()) { includeJars("log4j", "jdom") } if (Platform.P192.orHigher()) { - testRuntime(intellijDep()) { includeJars("lz4-java-1.6.0") } + testRuntime(intellijDep()) { includeJars("lz4-java", rootProject = rootProject) } } else { testRuntime(intellijDep()) { includeJars("lz4-1.3.0") } } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java b/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java index eb7859998af..4c808dff94d 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java @@ -107,11 +107,13 @@ public abstract class KtUsefulTestCase extends TestCase { @Override protected void setUp() throws Exception { + // -- KOTLIN ADDITIONAL START -- application = ApplicationManager.getApplication(); if (application != null && application.isDisposed()) { MockComponentManagerCreationTracer.diagnoseDisposedButNotClearedApplication(application); } + // -- KOTLIN ADDITIONAL END -- super.setUp(); @@ -122,11 +124,13 @@ public abstract class KtUsefulTestCase extends TestCase { myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER, testName, false); FileUtil.resetCanonicalTempPathCache(myTempDir.getPath()); } + boolean isStressTest = isStressTest(); ApplicationInfoImpl.setInStressTest(isStressTest); if (isPerformanceTest()) { Timings.getStatistics(); } + // turn off Disposer debugging for performance tests Disposer.setDebugMode(!isStressTest); } @@ -164,8 +168,10 @@ public abstract class KtUsefulTestCase extends TestCase { } finally { super.tearDown(); + // -- KOTLIN ADDITIONAL START -- TestApplicationUtilKt.resetApplicationToNull(application); application = null; + // -- KOTLIN ADDITIONAL END -- } } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java.201 b/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java.201 new file mode 100644 index 00000000000..decc4368d61 --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtUsefulTestCase.java.201 @@ -0,0 +1,1181 @@ +/* + * Copyright 2010-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 org.jetbrains.kotlin.test.testFramework; + +import com.intellij.codeInsight.CodeInsightSettings; +import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory; +import com.intellij.diagnostic.PerformanceWatcher; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.impl.ApplicationInfoImpl; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileVisitor; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.impl.DocumentCommitProcessor; +import com.intellij.psi.impl.DocumentCommitThread; +import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.rt.execution.junit.FileComparisonFailure; +import com.intellij.testFramework.*; +import com.intellij.testFramework.exceptionCases.AbstractExceptionCase; +import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy; +import com.intellij.util.*; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.PeekableIterator; +import com.intellij.util.containers.PeekableIteratorWrapper; +import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.FileBasedIndexImpl; +import com.intellij.util.lang.CompoundRuntimeException; +import com.intellij.util.ui.UIUtil; +import gnu.trove.Equality; +import gnu.trove.THashSet; +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; +import org.jdom.Element; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.testFramework.MockComponentManagerCreationTracer; +import org.junit.Assert; +import org.junit.ComparisonFailure; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * @author peter + */ +@SuppressWarnings("ALL") +public abstract class KtUsefulTestCase extends TestCase { + public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null; + public static final String TEMP_DIR_MARKER = "unitTest_"; + public static final boolean OVERWRITE_TESTDATA = Boolean.getBoolean("idea.tests.overwrite.data"); + + private static final String ORIGINAL_TEMP_DIR = FileUtil.getTempDirectory(); + + private static final Map TOTAL_SETUP_COST_MILLIS = new HashMap<>(); + private static final Map TOTAL_TEARDOWN_COST_MILLIS = new HashMap<>(); + + private Application application; + + static { + IdeaForkJoinWorkerThreadFactory.setupPoisonFactory(); + Logger.setFactory(TestLoggerFactory.class); + } + protected static final Logger LOG = Logger.getInstance(KtUsefulTestCase.class); + + @NotNull + private final Disposable myTestRootDisposable = new TestDisposable(); + + static Path ourPathToKeep; + private final List myPathsToKeep = new ArrayList<>(); + + private String myTempDir; + + private static final String DEFAULT_SETTINGS_EXTERNALIZED; + private static final CodeInsightSettings defaultSettings = new CodeInsightSettings(); + static { + // Radar #5755208: Command line Java applications need a way to launch without a Dock icon. + System.setProperty("apple.awt.UIElement", "true"); + + try { + Element oldS = new Element("temp"); + defaultSettings.writeExternal(oldS); + DEFAULT_SETTINGS_EXTERNALIZED = JDOMUtil.writeElement(oldS); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Pass here the exception you want to be thrown first + * E.g.
+     * {@code
+     *   void tearDown() {
+     *     try {
+     *       doTearDowns();
+     *     }
+     *     catch(Exception e) {
+     *       addSuppressedException(e);
+     *     }
+     *     finally {
+     *       super.tearDown();
+     *     }
+     *   }
+     * }
+     * 
+ * + */ + protected void addSuppressedException(@NotNull Throwable e) { + List list = mySuppressedExceptions; + if (list == null) { + mySuppressedExceptions = list = new SmartList<>(); + } + list.add(e); + } + private List mySuppressedExceptions; + + + public KtUsefulTestCase() { + } + + public KtUsefulTestCase(@NotNull String name) { + super(name); + } + + protected boolean shouldContainTempFiles() { + return true; + } + + @Override + protected void setUp() throws Exception { + // -- KOTLIN ADDITIONAL START -- + application = ApplicationManager.getApplication(); + + if (application != null && application.isDisposed()) { + MockComponentManagerCreationTracer.diagnoseDisposedButNotClearedApplication(application); + } + // -- KOTLIN ADDITIONAL END -- + + super.setUp(); + + if (shouldContainTempFiles()) { + IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current(); + String testName = null; + if (policy != null) { + testName = policy.getPerTestTempDirName(); + } + if (testName == null) { + testName = FileUtil.sanitizeFileName(getTestName(true)); + } + testName = new File(testName).getName(); // in case the test name contains file separators + myTempDir = FileUtil.createTempDirectory(TEMP_DIR_MARKER + testName, "", false).getPath(); + FileUtil.resetCanonicalTempPathCache(myTempDir); + } + + boolean isStressTest = isStressTest(); + ApplicationInfoImpl.setInStressTest(isStressTest); + if (isPerformanceTest()) { + Timings.getStatistics(); + } + + // turn off Disposer debugging for performance tests + Disposer.setDebugMode(!isStressTest); + + if (isIconRequired()) { + // ensure that IconLoader will use dummy empty icon + IconLoader.deactivate(); + //IconManager.activate(); + } + } + + protected boolean isIconRequired() { + return false; + } + + @Override + protected void tearDown() throws Exception { + try { + // don't use method references here to make stack trace reading easier + //noinspection Convert2MethodRef + new RunAll( + () -> { + if (isIconRequired()) { + //IconManager.deactivate(); + } + }, + () -> disposeRootDisposable(), + () -> cleanupSwingDataStructures(), + () -> cleanupDeleteOnExitHookList(), + () -> Disposer.setDebugMode(true), + () -> { + if (shouldContainTempFiles()) { + FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR); + if (hasTmpFilesToKeep()) { + File[] files = new File(myTempDir).listFiles(); + if (files != null) { + for (File file : files) { + if (!shouldKeepTmpFile(file)) { + FileUtil.delete(file); + } + } + } + } + else { + FileUtil.delete(new File(myTempDir)); + } + } + }, + () -> waitForAppLeakingThreads(10, TimeUnit.SECONDS) + ).run(ObjectUtils.notNull(mySuppressedExceptions, Collections.emptyList())); + } + finally { + // -- KOTLIN ADDITIONAL START -- + TestApplicationUtilKt.resetApplicationToNull(application); + application = null; + // -- KOTLIN ADDITIONAL END -- + } + } + + protected final void disposeRootDisposable() { + Disposer.dispose(getTestRootDisposable()); + } + + protected void addTmpFileToKeep(@NotNull File file) { + myPathsToKeep.add(file.getPath()); + } + + private boolean hasTmpFilesToKeep() { + return ourPathToKeep != null && FileUtil.isAncestor(myTempDir, ourPathToKeep.toString(), false) || !myPathsToKeep.isEmpty(); + } + + private boolean shouldKeepTmpFile(@NotNull File file) { + String path = file.getPath(); + if (FileUtil.pathsEqual(path, ourPathToKeep.toString())) return true; + for (String pathToKeep : myPathsToKeep) { + if (FileUtil.pathsEqual(path, pathToKeep)) return true; + } + return false; + } + + private static final Set DELETE_ON_EXIT_HOOK_DOT_FILES; + private static final Class DELETE_ON_EXIT_HOOK_CLASS; + static { + Class aClass; + try { + aClass = Class.forName("java.io.DeleteOnExitHook"); + } + catch (Exception e) { + throw new RuntimeException(e); + } + @SuppressWarnings("unchecked") Set files = ReflectionUtil.getStaticFieldValue(aClass, Set.class, "files"); + DELETE_ON_EXIT_HOOK_CLASS = aClass; + DELETE_ON_EXIT_HOOK_DOT_FILES = files; + } + + @SuppressWarnings("SynchronizeOnThis") + private static void cleanupDeleteOnExitHookList() { + // try to reduce file set retained by java.io.DeleteOnExitHook + List list; + synchronized (DELETE_ON_EXIT_HOOK_CLASS) { + if (DELETE_ON_EXIT_HOOK_DOT_FILES.isEmpty()) return; + list = new ArrayList<>(DELETE_ON_EXIT_HOOK_DOT_FILES); + } + for (int i = list.size() - 1; i >= 0; i--) { + String path = list.get(i); + File file = new File(path); + if (file.delete() || !file.exists()) { + synchronized (DELETE_ON_EXIT_HOOK_CLASS) { + DELETE_ON_EXIT_HOOK_DOT_FILES.remove(path); + } + } + } + } + + @SuppressWarnings("ConstantConditions") + private static void cleanupSwingDataStructures() throws Exception { + Object manager = ReflectionUtil.getDeclaredMethod(Class.forName("javax.swing.KeyboardManager"), "getCurrentManager").invoke(null); + Map componentKeyStrokeMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "componentKeyStrokeMap"); + componentKeyStrokeMap.clear(); + Map containerMap = ReflectionUtil.getField(manager.getClass(), manager, Hashtable.class, "containerMap"); + containerMap.clear(); + } + + static void doCheckForSettingsDamage(@NotNull CodeStyleSettings oldCodeStyleSettings, @NotNull CodeStyleSettings currentCodeStyleSettings) { + final CodeInsightSettings settings = CodeInsightSettings.getInstance(); + // don't use method references here to make stack trace reading easier + //noinspection Convert2MethodRef + new RunAll() + .append(() -> { + try { + checkCodeInsightSettingsEqual(defaultSettings, settings); + } + catch (AssertionError error) { + CodeInsightSettings clean = new CodeInsightSettings(); + for (Field field : clean.getClass().getFields()) { + try { + ReflectionUtil.copyFieldValue(clean, settings, field); + } + catch (Exception ignored) { + } + } + throw error; + } + }) + .append(() -> { + currentCodeStyleSettings.getIndentOptions(StdFileTypes.JAVA); + try { + checkCodeStyleSettingsEqual(oldCodeStyleSettings, currentCodeStyleSettings); + } + finally { + currentCodeStyleSettings.clearCodeStyleSettings(); + } + }) + .run(); + } + + @NotNull + public Disposable getTestRootDisposable() { + return myTestRootDisposable; + } + + @Override + protected void runTest() throws Throwable { + final Throwable[] throwables = new Throwable[1]; + + Runnable runnable = () -> { + try { + TestLoggerFactory.onTestStarted(); + super.runTest(); + TestLoggerFactory.onTestFinished(true); + } + catch (InvocationTargetException e) { + TestLoggerFactory.onTestFinished(false); + e.fillInStackTrace(); + throwables[0] = e.getTargetException(); + } + catch (IllegalAccessException e) { + TestLoggerFactory.onTestFinished(false); + e.fillInStackTrace(); + throwables[0] = e; + } + catch (Throwable e) { + TestLoggerFactory.onTestFinished(false); + throwables[0] = e; + } + }; + + invokeTestRunnable(runnable); + + if (throwables[0] != null) { + throw throwables[0]; + } + } + + protected boolean shouldRunTest() { + return TestFrameworkUtil.canRunTest(getClass()); + } + + protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception { + if (runInDispatchThread()) { + EdtTestUtilKt.runInEdtAndWait(() -> { + runnable.run(); + return null; + }); + } + else { + runnable.run(); + } + } + + protected void defaultRunBare() throws Throwable { + Throwable exception = null; + try { + long setupStart = System.nanoTime(); + setUp(); + long setupCost = (System.nanoTime() - setupStart) / 1000000; + logPerClassCost(setupCost, TOTAL_SETUP_COST_MILLIS); + + runTest(); + } + catch (Throwable running) { + exception = running; + } + finally { + try { + long teardownStart = System.nanoTime(); + tearDown(); + long teardownCost = (System.nanoTime() - teardownStart) / 1000000; + logPerClassCost(teardownCost, TOTAL_TEARDOWN_COST_MILLIS); + } + catch (Throwable tearingDown) { + if (exception == null) { + exception = tearingDown; + } + else { + exception = new CompoundRuntimeException(Arrays.asList(exception, tearingDown)); + } + } + } + if (exception != null) { + throw exception; + } + } + + /** + * Logs the setup cost grouped by test fixture class (superclass of the current test class). + * + * @param cost setup cost in milliseconds + */ + private void logPerClassCost(long cost, @NotNull Map costMap) { + Class superclass = getClass().getSuperclass(); + Long oldCost = costMap.get(superclass.getName()); + long newCost = oldCost == null ? cost : oldCost + cost; + costMap.put(superclass.getName(), newCost); + } + + @SuppressWarnings("UseOfSystemOutOrSystemErr") + static void logSetupTeardownCosts() { + System.out.println("Setup costs"); + long totalSetup = 0; + for (Map.Entry entry : TOTAL_SETUP_COST_MILLIS.entrySet()) { + System.out.println(String.format(" %s: %d ms", entry.getKey(), entry.getValue())); + totalSetup += entry.getValue(); + } + System.out.println("Teardown costs"); + long totalTeardown = 0; + for (Map.Entry entry : TOTAL_TEARDOWN_COST_MILLIS.entrySet()) { + System.out.println(String.format(" %s: %d ms", entry.getKey(), entry.getValue())); + totalTeardown += entry.getValue(); + } + System.out.println(String.format("Total overhead: setup %d ms, teardown %d ms", totalSetup, totalTeardown)); + System.out.println(String.format("##teamcity[buildStatisticValue key='ideaTests.totalSetupMs' value='%d']", totalSetup)); + System.out.println(String.format("##teamcity[buildStatisticValue key='ideaTests.totalTeardownMs' value='%d']", totalTeardown)); + } + + @Override + public void runBare() throws Throwable { + if (!shouldRunTest()) return; + + if (runInDispatchThread()) { + TestRunnerUtil.replaceIdeEventQueueSafely(); + EdtTestUtil.runInEdtAndWait(this::defaultRunBare); + } + else { + defaultRunBare(); + } + } + + protected boolean runInDispatchThread() { + IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current(); + if (policy != null) { + return policy.runInDispatchThread(); + } + return true; + } + + /** + * If you want a more shorter name than runInEdtAndWait. + */ + protected void edt(@NotNull ThrowableRunnable runnable) { + EdtTestUtil.runInEdtAndWait(runnable); + } + + @NotNull + public static String toString(@NotNull Iterable collection) { + if (!collection.iterator().hasNext()) { + return ""; + } + + final StringBuilder builder = new StringBuilder(); + for (final Object o : collection) { + if (o instanceof THashSet) { + builder.append(new TreeSet<>((THashSet)o)); + } + else { + builder.append(o); + } + builder.append('\n'); + } + return builder.toString(); + } + + @SafeVarargs + public static void assertOrderedEquals(@NotNull T[] actual, @NotNull T... expected) { + assertOrderedEquals(Arrays.asList(actual), expected); + } + + @SafeVarargs + public static void assertOrderedEquals(@NotNull Iterable actual, @NotNull T... expected) { + assertOrderedEquals("", actual, expected); + } + + public static void assertOrderedEquals(@NotNull byte[] actual, @NotNull byte[] expected) { + assertEquals(expected.length, actual.length); + for (int i = 0; i < actual.length; i++) { + byte a = actual[i]; + byte e = expected[i]; + assertEquals("not equals at index: "+i, e, a); + } + } + + public static void assertOrderedEquals(@NotNull int[] actual, @NotNull int[] expected) { + if (actual.length != expected.length) { + fail("Expected size: "+expected.length+"; actual: "+actual.length+"\nexpected: "+Arrays.toString(expected)+"\nactual : "+Arrays.toString(actual)); + } + for (int i = 0; i < actual.length; i++) { + int a = actual[i]; + int e = expected[i]; + assertEquals("not equals at index: "+i, e, a); + } + } + + @SafeVarargs + public static void assertOrderedEquals(@NotNull String errorMsg, @NotNull Iterable actual, @NotNull T... expected) { + assertOrderedEquals(errorMsg, actual, Arrays.asList(expected)); + } + + public static void assertOrderedEquals(@NotNull Iterable actual, @NotNull Iterable expected) { + assertOrderedEquals("", actual, expected); + } + + public static void assertOrderedEquals(@NotNull String errorMsg, + @NotNull Iterable actual, + @NotNull Iterable expected) { + //noinspection unchecked + assertOrderedEquals(errorMsg, actual, expected, Equality.CANONICAL); + } + + public static void assertOrderedEquals(@NotNull String errorMsg, + @NotNull Iterable actual, + @NotNull Iterable expected, + @NotNull Equality comparator) { + if (!equals(actual, expected, comparator)) { + String expectedString = toString(expected); + String actualString = toString(actual); + Assert.assertEquals(errorMsg, expectedString, actualString); + Assert.fail("Warning! 'toString' does not reflect the difference.\nExpected: " + expectedString + "\nActual: " + actualString); + } + } + + private static boolean equals(@NotNull Iterable a1, + @NotNull Iterable a2, + @NotNull Equality comparator) { + Iterator it1 = a1.iterator(); + Iterator it2 = a2.iterator(); + while (it1.hasNext() || it2.hasNext()) { + if (!it1.hasNext() || !it2.hasNext()) return false; + if (!comparator.equals(it1.next(), it2.next())) return false; + } + return true; + } + + @SafeVarargs + public static void assertOrderedCollection(@NotNull T[] collection, @NotNull Consumer... checkers) { + assertOrderedCollection(Arrays.asList(collection), checkers); + } + + /** + * Checks {@code actual} contains same elements (in {@link #equals(Object)} meaning) as {@code expected} irrespective of their order + */ + @SafeVarargs + public static void assertSameElements(@NotNull T[] actual, @NotNull T... expected) { + assertSameElements(Arrays.asList(actual), expected); + } + + /** + * Checks {@code actual} contains same elements (in {@link #equals(Object)} meaning) as {@code expected} irrespective of their order + */ + @SafeVarargs + public static void assertSameElements(@NotNull Collection actual, @NotNull T... expected) { + assertSameElements(actual, Arrays.asList(expected)); + } + + /** + * Checks {@code actual} contains same elements (in {@link #equals(Object)} meaning) as {@code expected} irrespective of their order + */ + public static void assertSameElements(@NotNull Collection actual, @NotNull Collection expected) { + assertSameElements("", actual, expected); + } + + /** + * Checks {@code actual} contains same elements (in {@link #equals(Object)} meaning) as {@code expected} irrespective of their order + */ + public static void assertSameElements(@NotNull String message, @NotNull Collection actual, @NotNull Collection expected) { + if (actual.size() != expected.size() || !new HashSet<>(expected).equals(new HashSet(actual))) { + Assert.assertEquals(message, new HashSet<>(expected), new HashSet(actual)); + } + } + + @SafeVarargs + public static void assertContainsOrdered(@NotNull Collection collection, @NotNull T... expected) { + assertContainsOrdered(collection, Arrays.asList(expected)); + } + + public static void assertContainsOrdered(@NotNull Collection collection, @NotNull Collection expected) { + PeekableIterator expectedIt = new PeekableIteratorWrapper<>(expected.iterator()); + PeekableIterator actualIt = new PeekableIteratorWrapper<>(collection.iterator()); + + while (actualIt.hasNext() && expectedIt.hasNext()) { + T expectedElem = expectedIt.peek(); + T actualElem = actualIt.peek(); + if (expectedElem.equals(actualElem)) { + expectedIt.next(); + } + actualIt.next(); + } + if (expectedIt.hasNext()) { + throw new ComparisonFailure("", toString(expected), toString(collection)); + } + } + + @SafeVarargs + public static void assertContainsElements(@NotNull Collection collection, @NotNull T... expected) { + assertContainsElements(collection, Arrays.asList(expected)); + } + + public static void assertContainsElements(@NotNull Collection collection, @NotNull Collection expected) { + ArrayList copy = new ArrayList<>(collection); + copy.retainAll(expected); + assertSameElements(toString(collection), copy, expected); + } + + @NotNull + public static String toString(@NotNull Object[] collection, @NotNull String separator) { + return toString(Arrays.asList(collection), separator); + } + + @SafeVarargs + public static void assertDoesntContain(@NotNull Collection collection, @NotNull T... notExpected) { + assertDoesntContain(collection, Arrays.asList(notExpected)); + } + + public static void assertDoesntContain(@NotNull Collection collection, @NotNull Collection notExpected) { + ArrayList expected = new ArrayList<>(collection); + expected.removeAll(notExpected); + assertSameElements(collection, expected); + } + + @NotNull + public static String toString(@NotNull Collection collection, @NotNull String separator) { + List list = ContainerUtil.map2List(collection, String::valueOf); + Collections.sort(list); + StringBuilder builder = new StringBuilder(); + boolean flag = false; + for (final String o : list) { + if (flag) { + builder.append(separator); + } + builder.append(o); + flag = true; + } + return builder.toString(); + } + + @SafeVarargs + public static void assertOrderedCollection(@NotNull Collection collection, @NotNull Consumer... checkers) { + if (collection.size() != checkers.length) { + Assert.fail(toString(collection)); + } + int i = 0; + for (final T actual : collection) { + try { + checkers[i].consume(actual); + } + catch (AssertionFailedError e) { + //noinspection UseOfSystemOutOrSystemErr + System.out.println(i + ": " + actual); + throw e; + } + i++; + } + } + + @SafeVarargs + public static void assertUnorderedCollection(@NotNull T[] collection, @NotNull Consumer... checkers) { + assertUnorderedCollection(Arrays.asList(collection), checkers); + } + + @SafeVarargs + public static void assertUnorderedCollection(@NotNull Collection collection, @NotNull Consumer... checkers) { + if (collection.size() != checkers.length) { + Assert.fail(toString(collection)); + } + Set> checkerSet = ContainerUtil.set(checkers); + int i = 0; + Throwable lastError = null; + for (final T actual : collection) { + boolean flag = true; + for (final Consumer condition : checkerSet) { + Throwable error = accepts(condition, actual); + if (error == null) { + checkerSet.remove(condition); + flag = false; + break; + } + else { + lastError = error; + } + } + if (flag) { + //noinspection ConstantConditions,CallToPrintStackTrace + lastError.printStackTrace(); + Assert.fail("Incorrect element(" + i + "): " + actual); + } + i++; + } + } + + private static Throwable accepts(@NotNull Consumer condition, final T actual) { + try { + condition.consume(actual); + return null; + } + catch (Throwable e) { + return e; + } + } + + @Contract("null, _ -> fail") + @NotNull + public static T assertInstanceOf(Object o, @NotNull Class aClass) { + Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o); + Assert.assertTrue("Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(), aClass.isInstance(o)); + @SuppressWarnings("unchecked") T t = (T)o; + return t; + } + + public static T assertOneElement(@NotNull Collection collection) { + Iterator iterator = collection.iterator(); + String toString = toString(collection); + Assert.assertTrue(toString, iterator.hasNext()); + T t = iterator.next(); + Assert.assertFalse(toString, iterator.hasNext()); + return t; + } + + public static T assertOneElement(@NotNull T[] ts) { + Assert.assertEquals(Arrays.asList(ts).toString(), 1, ts.length); + return ts[0]; + } + + @SafeVarargs + public static void assertOneOf(T value, @NotNull T... values) { + for (T v : values) { + if (Objects.equals(value, v)) { + return; + } + } + Assert.fail(value + " should be equal to one of " + Arrays.toString(values)); + } + + public static void printThreadDump() { + PerformanceWatcher.dumpThreadsToConsole("Thread dump:"); + } + + public static void assertEmpty(@NotNull Object[] array) { + assertOrderedEquals(array); + } + + public static void assertNotEmpty(final Collection collection) { + assertNotNull(collection); + assertFalse(collection.isEmpty()); + } + + public static void assertEmpty(@NotNull Collection collection) { + assertEmpty(collection.toString(), collection); + } + + public static void assertNullOrEmpty(@Nullable Collection collection) { + if (collection == null) return; + assertEmpty("", collection); + } + + public static void assertEmpty(final String s) { + assertTrue(s, StringUtil.isEmpty(s)); + } + + public static void assertEmpty(@NotNull String errorMsg, @NotNull Collection collection) { + assertOrderedEquals(errorMsg, collection, Collections.emptyList()); + } + + public static void assertSize(int expectedSize, @NotNull Object[] array) { + if (array.length != expectedSize) { + assertEquals(toString(Arrays.asList(array)), expectedSize, array.length); + } + } + + public static void assertSize(int expectedSize, @NotNull Collection c) { + if (c.size() != expectedSize) { + assertEquals(toString(c), expectedSize, c.size()); + } + } + + @NotNull + protected T disposeOnTearDown(@NotNull T disposable) { + Disposer.register(getTestRootDisposable(), disposable); + return disposable; + } + + public static void assertSameLines(@NotNull String expected, @NotNull String actual) { + assertSameLines(null, expected, actual); + } + + public static void assertSameLines(@Nullable String message, @NotNull String expected, @NotNull String actual) { + String expectedText = StringUtil.convertLineSeparators(expected.trim()); + String actualText = StringUtil.convertLineSeparators(actual.trim()); + Assert.assertEquals(message, expectedText, actualText); + } + + public static void assertExists(@NotNull File file){ + assertTrue("File should exist " + file, file.exists()); + } + + public static void assertDoesntExist(@NotNull File file){ + assertFalse("File should not exist " + file, file.exists()); + } + + @NotNull + protected String getTestName(boolean lowercaseFirstLetter) { + return getTestName(getName(), lowercaseFirstLetter); + } + + @NotNull + public static String getTestName(@Nullable String name, boolean lowercaseFirstLetter) { + return name == null ? "" : PlatformTestUtil.getTestName(name, lowercaseFirstLetter); + } + + @NotNull + protected String getTestDirectoryName() { + final String testName = getTestName(true); + return testName.replaceAll("_.*", ""); + } + + public static void assertSameLinesWithFile(@NotNull String filePath, @NotNull String actualText) { + assertSameLinesWithFile(filePath, actualText, true); + } + + public static void assertSameLinesWithFile(@NotNull String filePath, + @NotNull String actualText, + @NotNull Supplier messageProducer) { + assertSameLinesWithFile(filePath, actualText, true, messageProducer); + } + + public static void assertSameLinesWithFile(@NotNull String filePath, @NotNull String actualText, boolean trimBeforeComparing) { + assertSameLinesWithFile(filePath, actualText, trimBeforeComparing, null); + } + + public static void assertSameLinesWithFile(@NotNull String filePath, + @NotNull String actualText, + boolean trimBeforeComparing, + @Nullable Supplier messageProducer) { + String fileText; + try { + if (OVERWRITE_TESTDATA) { + VfsTestUtil.overwriteTestData(filePath, actualText); + //noinspection UseOfSystemOutOrSystemErr + System.out.println("File " + filePath + " created."); + } + fileText = FileUtil.loadFile(new File(filePath), StandardCharsets.UTF_8); + } + catch (FileNotFoundException e) { + VfsTestUtil.overwriteTestData(filePath, actualText); + throw new AssertionFailedError("No output text found. File " + filePath + " created."); + } + catch (IOException e) { + throw new RuntimeException(e); + } + String expected = StringUtil.convertLineSeparators(trimBeforeComparing ? fileText.trim() : fileText); + String actual = StringUtil.convertLineSeparators(trimBeforeComparing ? actualText.trim() : actualText); + if (!Comparing.equal(expected, actual)) { + throw new FileComparisonFailure(messageProducer == null ? null : messageProducer.get(), expected, actual, filePath); + } + } + + protected static void clearFields(@NotNull Object test) throws IllegalAccessException { + Class aClass = test.getClass(); + while (aClass != null) { + clearDeclaredFields(test, aClass); + aClass = aClass.getSuperclass(); + } + } + + public static void clearDeclaredFields(@NotNull Object test, @NotNull Class aClass) throws IllegalAccessException { + for (final Field field : aClass.getDeclaredFields()) { + final String name = field.getDeclaringClass().getName(); + if (!name.startsWith("junit.framework.") && !name.startsWith("com.intellij.testFramework.")) { + final int modifiers = field.getModifiers(); + if ((modifiers & Modifier.FINAL) == 0 && (modifiers & Modifier.STATIC) == 0 && !field.getType().isPrimitive()) { + field.setAccessible(true); + field.set(test, null); + } + } + } + } + + private static void checkCodeStyleSettingsEqual(@NotNull CodeStyleSettings expected, @NotNull CodeStyleSettings settings) { + if (!expected.equals(settings)) { + Element oldS = new Element("temp"); + expected.writeExternal(oldS); + Element newS = new Element("temp"); + settings.writeExternal(newS); + + String newString = JDOMUtil.writeElement(newS); + String oldString = JDOMUtil.writeElement(oldS); + Assert.assertEquals("Code style settings damaged", oldString, newString); + } + } + + private static void checkCodeInsightSettingsEqual(@NotNull CodeInsightSettings oldSettings, @NotNull CodeInsightSettings settings) { + if (!oldSettings.equals(settings)) { + Element newS = new Element("temp"); + settings.writeExternal(newS); + Assert.assertEquals("Code insight settings damaged", DEFAULT_SETTINGS_EXTERNALIZED, JDOMUtil.writeElement(newS)); + } + } + + public boolean isPerformanceTest() { + String testName = getName(); + String className = getClass().getSimpleName(); + return TestFrameworkUtil.isPerformanceTest(testName, className); + } + + /** + * @return true for a test which performs A LOT of computations. + * Such test should typically avoid performing expensive checks, e.g. data structure consistency complex validations. + * If you want your test to be treated as "Stress", please mention one of these words in its name: "Stress", "Slow". + * For example: {@code public void testStressPSIFromDifferentThreads()} + */ + public boolean isStressTest() { + return isStressTest(getName(), getClass().getName()); + } + + private static boolean isStressTest(String testName, String className) { + return TestFrameworkUtil.isPerformanceTest(testName, className) || + containsStressWords(testName) || + containsStressWords(className); + } + + private static boolean containsStressWords(@Nullable String name) { + return name != null && (name.contains("Stress") || name.contains("Slow")); + } + + public static void doPostponedFormatting(@NotNull Project project) { + DocumentUtil.writeInRunUndoTransparentAction(() -> { + PsiDocumentManager.getInstance(project).commitAllDocuments(); + PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); + }); + } + + /** + * Checks that code block throw corresponding exception. + * + * @param exceptionCase Block annotated with some exception type + */ + protected void assertException(@NotNull AbstractExceptionCase exceptionCase) { + assertException(exceptionCase, null); + } + + /** + * Checks that code block throw corresponding exception with expected error msg. + * If expected error message is null it will not be checked. + * + * @param exceptionCase Block annotated with some exception type + * @param expectedErrorMsg expected error message + */ + protected void assertException(@NotNull AbstractExceptionCase exceptionCase, @Nullable String expectedErrorMsg) { + //noinspection unchecked + assertExceptionOccurred(true, exceptionCase, expectedErrorMsg); + } + + /** + * Checks that the code block throws an exception of the specified class. + * + * @param exceptionClass Expected exception type + * @param runnable Block annotated with some exception type + */ + public static void assertThrows(@NotNull Class exceptionClass, + @NotNull ThrowableRunnable runnable) { + assertThrows(exceptionClass, null, runnable); + } + + /** + * Checks that the code block throws an exception of the specified class with expected error msg. + * If expected error message is null it will not be checked. + * + * @param exceptionClass Expected exception type + * @param expectedErrorMsgPart expected error message, of any + * @param runnable Block annotated with some exception type + */ + @SuppressWarnings({"unchecked", "SameParameterValue"}) + public static void assertThrows(@NotNull Class exceptionClass, + @Nullable String expectedErrorMsgPart, + @NotNull ThrowableRunnable runnable) { + assertExceptionOccurred(true, new AbstractExceptionCase() { + @Override + public Class getExpectedExceptionClass() { + return (Class)exceptionClass; + } + + @Override + public void tryClosure() throws Throwable { + runnable.run(); + } + }, expectedErrorMsgPart); + } + + /** + * Checks that code block doesn't throw corresponding exception. + * + * @param exceptionCase Block annotated with some exception type + */ + protected void assertNoException(@NotNull AbstractExceptionCase exceptionCase) throws T { + assertExceptionOccurred(false, exceptionCase, null); + } + + protected void assertNoThrowable(@NotNull Runnable closure) { + String throwableName = null; + try { + closure.run(); + } + catch (Throwable thr) { + throwableName = thr.getClass().getName(); + } + assertNull(throwableName); + } + + private static void assertExceptionOccurred(boolean shouldOccur, + @NotNull AbstractExceptionCase exceptionCase, + String expectedErrorMsgPart) throws T { + boolean wasThrown = false; + try { + exceptionCase.tryClosure(); + } + catch (Throwable e) { + Throwable cause = e; + + if (shouldOccur) { + wasThrown = true; + final String errorMessage = exceptionCase.getAssertionErrorMessage(); + assertEquals(errorMessage, exceptionCase.getExpectedExceptionClass(), cause.getClass()); + if (expectedErrorMsgPart != null) { + assertTrue(cause.getMessage(), cause.getMessage().contains(expectedErrorMsgPart)); + } + } + else if (exceptionCase.getExpectedExceptionClass().equals(cause.getClass())) { + wasThrown = true; + + //noinspection UseOfSystemOutOrSystemErr + System.out.println(); + //noinspection UseOfSystemOutOrSystemErr + e.printStackTrace(System.out); + + fail("Exception isn't expected here. Exception message: " + cause.getMessage()); + } + else { + throw e; + } + } + finally { + if (shouldOccur && !wasThrown) { + fail(exceptionCase.getAssertionErrorMessage()); + } + } + } + + protected boolean annotatedWith(@NotNull Class annotationClass) { + Class aClass = getClass(); + String methodName = "test" + getTestName(false); + boolean methodChecked = false; + while (aClass != null && aClass != Object.class) { + if (aClass.getAnnotation(annotationClass) != null) return true; + if (!methodChecked) { + Method method = ReflectionUtil.getDeclaredMethod(aClass, methodName); + if (method != null) { + if (method.getAnnotation(annotationClass) != null) return true; + methodChecked = true; + } + } + aClass = aClass.getSuperclass(); + } + return false; + } + + @NotNull + protected String getHomePath() { + return PathManager.getHomePath().replace(File.separatorChar, '/'); + } + + public static void refreshRecursively(@NotNull VirtualFile file) { + VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() { + @Override + public boolean visitFile(@NotNull VirtualFile file) { + file.getChildren(); + return true; + } + }); + file.refresh(false, true); + } + + public static VirtualFile refreshAndFindFile(@NotNull final File file) { + return UIUtil.invokeAndWaitIfNeeded(() -> LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)); + } + + public static void waitForAppLeakingThreads(long timeout, @NotNull TimeUnit timeUnit) { + EdtTestUtil.runInEdtAndWait(() -> { + Application app = ApplicationManager.getApplication(); + if (app != null && !app.isDisposed()) { + FileBasedIndexImpl index = (FileBasedIndexImpl)app.getServiceIfCreated(FileBasedIndex.class); + if (index != null) { + index.getChangedFilesCollector().waitForVfsEventsExecuted(timeout, timeUnit); + } + + DocumentCommitThread commitThread = (DocumentCommitThread)app.getServiceIfCreated(DocumentCommitProcessor.class); + if (commitThread != null) { + commitThread.waitForAllCommits(timeout, timeUnit); + } + } + }); + } + + protected class TestDisposable implements Disposable { + private volatile boolean myDisposed; + + public TestDisposable() { + } + + @Override + public void dispose() { + myDisposed = true; + } + + public boolean isDisposed() { + return myDisposed; + } + + @Override + public String toString() { + String testName = getTestName(false); + return KtUsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName); + } + } +} \ No newline at end of file diff --git a/gradle/versions.properties b/gradle/versions.properties index 17f047ad41f..0d985de36f1 100644 --- a/gradle/versions.properties +++ b/gradle/versions.properties @@ -12,6 +12,7 @@ versions.jar.gson=2.8.5 versions.jar.oro=2.0.8 versions.jar.picocontainer=1.2 versions.jar.serviceMessages=2019.1.4 +versions.jar.lz4-java=1.6.0 ignore.jar.snappy-in-java=true versions.gradle-api=4.5.1 versions.shadow=5.2.0 \ No newline at end of file diff --git a/gradle/versions.properties.192 b/gradle/versions.properties.192 index 41c81e8bccc..5a1ac2618e6 100644 --- a/gradle/versions.properties.192 +++ b/gradle/versions.properties.192 @@ -11,6 +11,7 @@ versions.jar.streamex=0.6.8 versions.jar.gson=2.8.5 versions.jar.oro=2.0.8 versions.jar.picocontainer=1.2 +versions.jar.lz4-java=1.6.0 ignore.jar.snappy-in-java=true versions.gradle-api=4.5.1 versions.shadow=5.2.0 \ No newline at end of file diff --git a/gradle/versions.properties.201 b/gradle/versions.properties.201 index 5431d965680..606d9768b91 100644 --- a/gradle/versions.properties.201 +++ b/gradle/versions.properties.201 @@ -1,8 +1,8 @@ -versions.intellijSdk=201.4515.24-EAP-SNAPSHOT +versions.intellijSdk=201.5259.13-EAP-SNAPSHOT versions.androidBuildTools=r23.0.1 versions.idea.NodeJS=181.3494.12 versions.jar.asm-all=7.0.1 -versions.jar.guava=27.1-jre +versions.jar.guava=28.2-jre versions.jar.groovy-all=2.4.17 versions.jar.lombok-ast=0.2.3 versions.jar.swingx-core=1.6.2-2 @@ -12,6 +12,7 @@ versions.jar.gson=2.8.6 versions.jar.oro=2.0.8 versions.jar.picocontainer=1.2 versions.jar.serviceMessages=2019.1.4 +versions.jar.lz4-java=1.7.1 ignore.jar.snappy-in-java=true versions.gradle-api=4.5.1 versions.shadow=5.2.0 \ No newline at end of file diff --git a/gradle/versions.properties.as36 b/gradle/versions.properties.as36 index c122788cad6..542ca22339d 100644 --- a/gradle/versions.properties.as36 +++ b/gradle/versions.properties.as36 @@ -13,6 +13,7 @@ versions.jar.streamex=0.6.8 versions.jar.gson=2.8.5 versions.jar.oro=2.0.8 versions.jar.picocontainer=1.2 +versions.jar.lz4-java=1.6.0 ignore.jar.snappy-in-java=true ignore.jar.common=true ignore.jar.lombok-ast=true diff --git a/gradle/versions.properties.as40 b/gradle/versions.properties.as40 index 63d9590d614..3da91212fe8 100644 --- a/gradle/versions.properties.as40 +++ b/gradle/versions.properties.as40 @@ -14,6 +14,7 @@ versions.jar.gson=2.8.5 versions.jar.oro=2.0.8 versions.jar.picocontainer=1.2 versions.jar.serviceMessages=2019.1.4 +versions.jar.lz4-java=1.6.0 ignore.jar.snappy-in-java=true versions.gradle-api=4.5.1 versions.shadow=5.2.0 diff --git a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinInlayParameterHintsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinInlayParameterHintsProvider.kt index f78e83029d1..db39fea02d8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinInlayParameterHintsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/KotlinInlayParameterHintsProvider.kt @@ -162,9 +162,9 @@ class KotlinInlayParameterHintsProvider : InlayParameterHintsProvider { } } - override fun getParameterHints(element: PsiElement?): List { + override fun getParameterHints(element: PsiElement): List { val resolveToEnabled = HintType.resolveToEnabled(element) ?: return emptyList() - return resolveToEnabled.provideHints(element!!) + return resolveToEnabled.provideHints(element) } override fun getBlackListDependencyLanguage(): Language = JavaLanguage.INSTANCE diff --git a/prepare/compiler/build.gradle.kts b/prepare/compiler/build.gradle.kts index cc319cf9dad..1199b1acd99 100644 --- a/prepare/compiler/build.gradle.kts +++ b/prepare/compiler/build.gradle.kts @@ -200,7 +200,7 @@ dependencies { fatJarContents(intellijDep()) { includeJars("jna-platform") } if (Platform.P192.orHigher()) { - fatJarContents(intellijDep()) { includeJars("lz4-java-1.6.0") } + fatJarContents(intellijDep()) { includeJars("lz4-java", rootProject = rootProject) } } else { fatJarContents(intellijDep()) { includeJars("lz4-1.3.0") } }