Check that quick fixes don't produce new errors

This commit is contained in:
Nikolay Krasko
2012-06-27 17:41:21 +04:00
parent 0f2b3dbf14
commit bade0e0275
24 changed files with 68 additions and 24 deletions
@@ -1,4 +1,4 @@
// "Make 'foo' not abstract" "true" // "Make 'foo' not abstract" "true"
class A() { class A() {
<caret>fun foo() fun foo() {}
} }
@@ -1,4 +1,4 @@
// "Make 'i' not abstract" "true" // "Make 'i' not abstract" "true"
class A() { class A() {
<caret>var i : Int var i : Int = 0
} }
@@ -1,5 +1,5 @@
// "Make 'i' not abstract" "true" // "Make 'i' not abstract" "true"
class B { class B {
<caret>val i: Int val i: Int = 0
get() = $i get() = $i
} }
@@ -1,5 +1,5 @@
// "Make 'j' not abstract" "true" // "Make 'j' not abstract" "true"
class B { class B {
<caret>var j: Int var j: Int = 0
set(v: Int) {} set(v: Int) {}
} }
@@ -1,2 +1,2 @@
// "Make 'foo' not abstract" "true" // "Make 'foo' not abstract" "true"
<caret>fun foo() fun foo() {}
@@ -1,4 +1,4 @@
// "Make 'foo' not abstract" "true" // "Make 'foo' not abstract" "true"
class A() { class A() {
<caret>abstract fun foo() <caret>abstract fun foo() {}
} }
@@ -1,4 +1,4 @@
// "Make 'i' not abstract" "true" // "Make 'i' not abstract" "true"
class A() { class A() {
<caret>abstract var i : Int <caret>abstract var i : Int = 0
} }
@@ -1,5 +1,5 @@
// "Make 'i' not abstract" "true" // "Make 'i' not abstract" "true"
class B { class B {
<caret>abstract val i: Int <caret>abstract val i: Int = 0
get() = $i get() = $i
} }
@@ -1,5 +1,5 @@
// "Make 'j' not abstract" "true" // "Make 'j' not abstract" "true"
class B { class B {
abstract<caret> var j: Int abstract<caret> var j: Int = 0
set(v: Int) {} set(v: Int) {}
} }
@@ -1,2 +1,2 @@
// "Make 'foo' not abstract" "true" // "Make 'foo' not abstract" "true"
<caret>abstract fun foo() <caret>abstract fun foo() {}
@@ -4,5 +4,5 @@ package some
import kotlin.util.measureTimeNano import kotlin.util.measureTimeNano
fun testFun() { fun testFun() {
measureTimeNano() measureTimeNano({})
} }
@@ -1,4 +1,6 @@
// "Import Class" "false" // "Import Class" "false"
// ERROR: Unresolved reference: some[12]
// ERROR: No get method providing array access
package Teting package Teting
@@ -2,5 +2,5 @@
package some package some
fun testFun() { fun testFun() {
<caret>measureTimeNano() <caret>measureTimeNano({})
} }
@@ -1,4 +1,6 @@
// "Import Class" "false" // "Import Class" "false"
// ERROR: Unresolved reference: someFun
// ERROR: Unresolved reference: test
package Teting package Teting
@@ -1,4 +1,6 @@
// "Import Class" "false" // "Import Class" "false"
// ERROR: Unresolved reference: some[12]
// ERROR: No get method providing array access
package Teting package Teting
@@ -1,4 +1,4 @@
// "Remove unnecessary non-null assertion (!!)" "true" // "Remove unnecessary non-null assertion (!!)" "true"
fun test(value : Int) : Int { fun test(value : Int) : Int {
value<caret> return value<caret>
} }
@@ -1,4 +1,4 @@
// "Replace with dot call" "true" // "Replace with dot call" "true"
fun test(value : String) : Int { fun test(value : String) {
return value<caret>.length() value<caret>.equals("test")
} }
@@ -1,4 +1,4 @@
// "Remove unnecessary non-null assertion (!!)" "true" // "Remove unnecessary non-null assertion (!!)" "true"
fun test(value : Int) : Int { fun test(value : Int) : Int {
value<caret>!! return value<caret>!!
} }
@@ -1,4 +1,4 @@
// "Replace with dot call" "true" // "Replace with dot call" "true"
fun test(value : String) : Int { fun test(value : String) {
return value<caret>!!.length() value!!<caret>.equals("test")
} }
@@ -1,6 +1,6 @@
// "Add 'override' modifier" "true" // "Add 'override' modifier" "true"
open class A() { open class A() {
fun foo() {} open fun foo() {}
} }
class B() : A() { class B() : A() {
@@ -1,6 +1,6 @@
// "Add 'override' modifier" "true" // "Add 'override' modifier" "true"
open class A() { open class A() {
fun foo() {} open fun foo() {}
} }
class B() : A() { class B() : A() {
@@ -1,4 +1,6 @@
// "Specify type explicitly" "false" // "Specify type explicitly" "false"
// ERROR: Public or protected member should have specified type
// ERROR: Unresolved reference: foo
class A() { class A() {
public val <caret>t = foo() public val <caret>t = foo()
@@ -1,4 +1,5 @@
// "Specify return type explicitly" "false" // "Specify return type explicitly" "false"
// ERROR: Function 'foo' without a body must be abstract
package a package a
class A() { class A() {
@@ -20,20 +20,25 @@ import com.google.common.collect.Lists;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.Sdk;
import junit.framework.Assert;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.apache.commons.lang.SystemUtils; import org.apache.commons.lang.SystemUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder; 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.PluginTestCaseBase;
import org.jetbrains.jet.plugin.highlighter.IdeErrorMessages;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.testing.ConfigRuntimeUtil; import org.jetbrains.jet.testing.ConfigRuntimeUtil;
import org.jetbrains.jet.testing.InTextDirectivesUtils;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** /**
* @author svtk * @author svtk
@@ -97,6 +102,7 @@ public class JetQuickFixTest extends LightQuickFixTestCase {
return JetTestCaseBuilder.getHomeDirectory() + "/idea/testData/quickfix/"; return JetTestCaseBuilder.getHomeDirectory() + "/idea/testData/quickfix/";
} }
@Override
public String getName() { public String getName() {
return "test" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase()); return "test" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
} }
@@ -111,6 +117,7 @@ public class JetQuickFixTest extends LightQuickFixTestCase {
try { try {
doSingleTest(name.substring("before".length()) + ".kt"); doSingleTest(name.substring("before".length()) + ".kt");
checkForUnexpectedErrors();
} finally { } finally {
if (isWithRuntime) { if (isWithRuntime) {
ConfigRuntimeUtil.unConfigureKotlinRuntime(getModule(), getProjectJDK()); ConfigRuntimeUtil.unConfigureKotlinRuntime(getModule(), getProjectJDK());
@@ -118,6 +125,34 @@ public class JetQuickFixTest extends LightQuickFixTestCase {
} }
} }
private static void checkForUnexpectedErrors() {
AnalyzeExhaust exhaust = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getFile());
Collection<Diagnostic> diagnostics = exhaust.getBindingContext().getDiagnostics();
if (diagnostics.size() != 0) {
String[] expectedErrorStrings = InTextDirectivesUtils.findListWithPrefix("// ERROR:", getFile().getText());
System.out.println(getFile().getText());
Collection<String> expectedErrors = new HashSet<String>(Arrays.asList(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);
}
}
@Override @Override
protected String getBasePath() { protected String getBasePath() {
return "/quickfix/" + dataPath; return "/quickfix/" + dataPath;