diff --git a/idea/testData/quickfix/autoImports/classImport.after.kt b/idea/testData/quickfix/autoImports/classImport.after.kt index 4ddc3857bc0..c9cca3295d4 100644 --- a/idea/testData/quickfix/autoImports/classImport.after.kt +++ b/idea/testData/quickfix/autoImports/classImport.after.kt @@ -1,4 +1,5 @@ // "Import" "true" +// ERROR: Unresolved reference: TestSample import TestData.TestSample diff --git a/idea/testData/quickfix/autoImports/classImport.before.Main.kt b/idea/testData/quickfix/autoImports/classImport.before.Main.kt index ab8cea6b991..b18ccde13d5 100644 --- a/idea/testData/quickfix/autoImports/classImport.before.Main.kt +++ b/idea/testData/quickfix/autoImports/classImport.before.Main.kt @@ -1,4 +1,5 @@ // "Import" "true" +// ERROR: Unresolved reference: TestSample fun test() { val a = TestSample diff --git a/idea/testData/quickfix/autoImports/extensionFunctionImport.after.kt b/idea/testData/quickfix/autoImports/extensionFunctionImport.after.kt index c30acf30a0c..dbc34985349 100644 --- a/idea/testData/quickfix/autoImports/extensionFunctionImport.after.kt +++ b/idea/testData/quickfix/autoImports/extensionFunctionImport.after.kt @@ -1,4 +1,5 @@ // "Import" "true" +// ERROR: Unresolved reference: someFun package testingExtensionFunctionsImport import testingExtensionFunctionsImport.data.someFun diff --git a/idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt b/idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt index 5fd44e63d99..555da87889a 100644 --- a/idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt +++ b/idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt @@ -1,4 +1,5 @@ // "Import" "true" +// ERROR: Unresolved reference: someFun package testingExtensionFunctionsImport fun some() { diff --git a/idea/testData/quickfix/autoImports/functionImport.after.kt b/idea/testData/quickfix/autoImports/functionImport.after.kt index 8579b97024f..a26880df3a7 100644 --- a/idea/testData/quickfix/autoImports/functionImport.after.kt +++ b/idea/testData/quickfix/autoImports/functionImport.after.kt @@ -1,4 +1,6 @@ // "Import" "true" +// ERROR: Unresolved reference: someTestFun + package functionimporttest import functionimporttest.data.someTestFun diff --git a/idea/testData/quickfix/autoImports/functionImport.before.Main.kt b/idea/testData/quickfix/autoImports/functionImport.before.Main.kt index f35ac3858d2..e933ea9d610 100644 --- a/idea/testData/quickfix/autoImports/functionImport.before.Main.kt +++ b/idea/testData/quickfix/autoImports/functionImport.before.Main.kt @@ -1,4 +1,6 @@ // "Import" "true" +// ERROR: Unresolved reference: someTestFun + package functionimporttest fun functionImportTest() { diff --git a/idea/testData/quickfix/autoImports/noImportForPrivateClass.after.kt b/idea/testData/quickfix/autoImports/noImportForPrivateClass.after.kt index 880e647c559..225e623a55a 100644 --- a/idea/testData/quickfix/autoImports/noImportForPrivateClass.after.kt +++ b/idea/testData/quickfix/autoImports/noImportForPrivateClass.after.kt @@ -1,4 +1,5 @@ // "Import Class" "false" +// ERROR: Unresolved reference: PrivateClass fun test() { PrivateClass diff --git a/idea/testData/quickfix/autoImports/noImportForPrivateClass.before.Main.kt b/idea/testData/quickfix/autoImports/noImportForPrivateClass.before.Main.kt index 926bed4da6b..7df5815c5d2 100644 --- a/idea/testData/quickfix/autoImports/noImportForPrivateClass.before.Main.kt +++ b/idea/testData/quickfix/autoImports/noImportForPrivateClass.before.Main.kt @@ -1,4 +1,5 @@ // "Import" "false" +// ERROR: Unresolved reference: PrivateClass fun test() { PrivateClass diff --git a/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt b/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt index 65e523502af..2622c46bac5 100644 --- a/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt +++ b/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.after.kt @@ -1,5 +1,4 @@ // "Import" "false" -// ACTION: Change to constructor invocation // ERROR: Unresolved reference: SomeTest package testing diff --git a/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt b/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt index 65e523502af..2622c46bac5 100644 --- a/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt +++ b/idea/testData/quickfix/autoImports/noImportInQualifiedUserTypeNotFirst.before.Main.kt @@ -1,5 +1,4 @@ // "Import" "false" -// ACTION: Change to constructor invocation // ERROR: Unresolved reference: SomeTest package testing diff --git a/idea/testData/quickfix/typeAddition/beforePublicFunWithoutBody.kt b/idea/testData/quickfix/typeAddition/beforePublicFunWithoutBody.kt index 580eed90ae9..5f6dc640f14 100644 --- a/idea/testData/quickfix/typeAddition/beforePublicFunWithoutBody.kt +++ b/idea/testData/quickfix/typeAddition/beforePublicFunWithoutBody.kt @@ -1,5 +1,8 @@ // "Specify return type explicitly" "false" // ERROR: Function 'foo' without a body must be abstract +// ACTION: Add function body +// ACTION: Make 'foo' abstract + package a class A() { diff --git a/idea/testData/quickfix/typeImports/afterImportFromAnotherFile.kt b/idea/testData/quickfix/typeImports/afterImportFromAnotherFile.kt index 06b3336bbdd..efae01e6375 100644 --- a/idea/testData/quickfix/typeImports/afterImportFromAnotherFile.kt +++ b/idea/testData/quickfix/typeImports/afterImportFromAnotherFile.kt @@ -1,4 +1,5 @@ // "Specify type explicitly" "true" +// ERROR: Public or protected member should have specified type package a diff --git a/idea/testData/quickfix/typeImports/beforeImportFromAnotherFile.Main.kt b/idea/testData/quickfix/typeImports/beforeImportFromAnotherFile.Main.kt index b5680eb04da..57fad46eaec 100644 --- a/idea/testData/quickfix/typeImports/beforeImportFromAnotherFile.Main.kt +++ b/idea/testData/quickfix/typeImports/beforeImportFromAnotherFile.Main.kt @@ -1,4 +1,5 @@ // "Specify type explicitly" "true" +// ERROR: Public or protected member should have specified type package a diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixMultiFileTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixMultiFileTest.java index 231ced9e1f0..3dd0bcc81dd 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixMultiFileTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixMultiFileTest.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.plugin.quickfix; -import com.google.common.collect.Sets; import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; @@ -27,13 +26,12 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Pair; import com.intellij.util.ui.UIUtil; import junit.framework.ComparisonFailure; -import org.jetbrains.jet.InTextDirectivesUtils; +import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.plugin.PluginTestCaseBase; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Set; /** * @author Nikolay Krasko @@ -64,9 +62,11 @@ public abstract class JetQuickFixMultiFileTest extends DaemonAnalyzerTestCase { final boolean actionShouldBeAvailable = pair.getSecond(); + QuickFixActionsUtils.checkForUnexpectedErrors((JetFile) getFile()); + doAction(text, actionShouldBeAvailable, getTestDataPath()); } - catch (ComparisonFailure e){ + catch (ComparisonFailure e) { throw e; } catch (Throwable e) { @@ -93,13 +93,7 @@ public abstract class JetQuickFixMultiFileTest extends DaemonAnalyzerTestCase { "Infos:" + infos); } else { - Set validActions = Sets.newHashSet(InTextDirectivesUtils.findLinesWithPrefixRemoved("// ACTION:", getFile().getText())); - for (IntentionAction availableAction : availableActions) { - if (!validActions.contains(availableAction.getText())) { - fail(String.format("Unexpected action available at current position: %s. Use // ACTION: directive", - availableAction.getText())); - } - } + QuickFixActionsUtils.checkAvailableActionsAreExpected((JetFile) getFile(), availableActions); } } else { diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java index c0d9b3fd0d1..3199c32c483 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java @@ -18,27 +18,25 @@ package org.jetbrains.jet.plugin.quickfix; import com.google.common.collect.Lists; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; -import junit.framework.Assert; +import com.intellij.openapi.util.Pair; import junit.framework.Test; import junit.framework.TestSuite; import org.apache.commons.lang.SystemUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.InTextDirectivesUtils; import org.jetbrains.jet.JetTestCaseBuilder; -import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.plugin.PluginTestCaseBase; -import org.jetbrains.jet.plugin.highlighter.IdeErrorMessages; -import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import org.jetbrains.jet.testing.ConfigRuntimeUtil; import java.io.File; import java.io.FilenameFilter; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * @author svtk @@ -117,45 +115,35 @@ public class JetQuickFixTest extends LightQuickFixTestCase { try { doSingleTest(name.substring("before".length()) + ".kt"); + checkAvailableActionsAreExpected(); checkForUnexpectedErrors(); - } finally { + } + finally { if (isWithRuntime) { ConfigRuntimeUtil.unConfigureKotlinRuntime(getModule(), getProjectJDK()); } } } - private static void checkForUnexpectedErrors() { - AnalyzeExhaust exhaust = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getFile()); - Collection diagnostics = exhaust.getBindingContext().getDiagnostics(); - - if (diagnostics.size() != 0) { - List expectedErrorStrings = InTextDirectivesUtils.findLinesWithPrefixRemoved("// ERROR:", getFile().getText()); - - Collection expectedErrors = new HashSet(expectedErrorStrings); - - StringBuilder builder = new StringBuilder(); - boolean hasErrors = false; - - for (Diagnostic diagnostic : diagnostics) { - if (diagnostic.getSeverity() == Severity.ERROR) { - String errorText = IdeErrorMessages.RENDERER.render(diagnostic); - if (!expectedErrors.contains(errorText)) { - hasErrors = true; - builder.append("// ERROR: ").append(errorText).append("\n"); - } - } - } - - Assert.assertFalse("There should be no unexpected errors after applying fix (Use \"// ERROR:\" directive): \n" + builder.toString(), hasErrors); + public void checkAvailableActionsAreExpected() { + List actions = getAvailableActions(); + final Pair pair = parseActionHintImpl(getFile(), getEditor().getDocument().getText()); + if (!pair.getSecond()) { + // Action shouldn't be found. Check that other actions are expected and thus tested action isn't there under another name. + QuickFixActionsUtils.checkAvailableActionsAreExpected((JetFile) getFile(), actions); } } + public static void checkForUnexpectedErrors() { + QuickFixActionsUtils.checkForUnexpectedErrors((JetFile) getFile()); + } + @Override protected String getBasePath() { return "/quickfix/" + dataPath; } + @NotNull @Override protected String getTestDataPath() { return PluginTestCaseBase.getTestDataPathBase(); diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixActionsUtils.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixActionsUtils.java new file mode 100644 index 00000000000..ff247553b03 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixActionsUtils.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2012 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.jet.plugin.quickfix; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.testFramework.UsefulTestCase; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.InTextDirectivesUtils; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.Severity; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.plugin.highlighter.IdeErrorMessages; +import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class QuickFixActionsUtils { + private QuickFixActionsUtils() { + } + + public static void checkForUnexpectedErrors(JetFile file) { + AnalyzeExhaust exhaust = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); + + Collection diagnostics = exhaust.getBindingContext().getDiagnostics(); + Collection errorDiagnostics = Collections2.filter(diagnostics, new Predicate() { + @Override + public boolean apply(@Nullable Diagnostic diagnostic) { + assert (diagnostic != null); + return diagnostic.getSeverity() == Severity.ERROR; + } + }); + Collection actualErrorStrings = Collections2.transform(errorDiagnostics, new Function() { + @Override + public String apply(@Nullable Diagnostic diagnostic) { + assert (diagnostic != null); + return IdeErrorMessages.RENDERER.render(diagnostic); + } + }); + + List expectedErrorStrings = InTextDirectivesUtils.findLinesWithPrefixRemoved("// ERROR:", file.getText()); + Collections.sort(expectedErrorStrings); + + UsefulTestCase.assertOrderedEquals( + "All actual errors should be mentioned in test data with // ERROR: directive. But no unnecessary errors should be me mentioned", + Ordering.natural().sortedCopy(actualErrorStrings), expectedErrorStrings); + } + + public static void checkAvailableActionsAreExpected(JetFile file, Collection availableActions) { + List validActions = Ordering.natural().sortedCopy( + Sets.newHashSet(InTextDirectivesUtils.findLinesWithPrefixRemoved("// ACTION:", file.getText()))); + + Collection actualActions = Ordering.natural().sortedCopy( + Collections2.transform(availableActions, new Function() { + @Override + public String apply(@Nullable IntentionAction input) { + assert input != null; + return input.getText(); + } + })); + + UsefulTestCase.assertOrderedEquals("Some unexpected actions available at current position: %s. Use // ACTION: directive", + actualActions, validActions); + } +}