Mark dynamic calls in tests

This commit is contained in:
Andrey Breslav
2014-11-13 21:03:37 +03:00
parent c8029307fa
commit 4f3158abb3
8 changed files with 102 additions and 7 deletions
@@ -82,7 +82,12 @@ public class CheckerTestUtil {
private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile(INDIVIDUAL_DIAGNOSTIC);
private static final Pattern INDIVIDUAL_PARAMETER_PATTERN = Pattern.compile(DIAGNOSTIC_PARAMETER);
public static List<Diagnostic> getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, final PsiElement root) {
@NotNull
public static List<Diagnostic> getDiagnosticsIncludingSyntaxErrors(
@NotNull BindingContext bindingContext,
@NotNull final PsiElement root,
boolean markDynamicCalls
) {
List<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
diagnostics.addAll(Collections2.filter(bindingContext.getDiagnostics().all(),
new Predicate<Diagnostic>() {
@@ -94,12 +99,17 @@ public class CheckerTestUtil {
for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
diagnostics.add(new SyntaxErrorDiagnostic(errorElement));
}
List<Diagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext);
List<Diagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls);
diagnostics.addAll(debugAnnotations);
return diagnostics;
}
public static List<Diagnostic> getDebugInfoDiagnostics(@NotNull PsiElement root, @NotNull BindingContext bindingContext) {
@NotNull
public static List<Diagnostic> getDebugInfoDiagnostics(
@NotNull PsiElement root,
@NotNull BindingContext bindingContext,
final boolean markDynamicCalls
) {
final List<Diagnostic> debugAnnotations = Lists.newArrayList();
DebugInfoUtil.markDebugAnnotations(root, bindingContext, new DebugInfoUtil.DebugInfoReporter() {
@Override
@@ -117,6 +127,13 @@ public class CheckerTestUtil {
newDiagnostic(expression, DebugInfoDiagnosticFactory.UNRESOLVED_WITH_TARGET);
}
@Override
public void reportDynamicCall(@NotNull JetReferenceExpression expression) {
if (markDynamicCalls) {
newDiagnostic(expression, DebugInfoDiagnosticFactory.DYNAMIC);
}
}
private void newDiagnostic(JetReferenceExpression expression, DebugInfoDiagnosticFactory factory) {
debugAnnotations.add(new DebugInfoDiagnostic(expression, factory));
}
@@ -486,6 +503,7 @@ public class CheckerTestUtil {
public static final DebugInfoDiagnosticFactory ELEMENT_WITH_ERROR_TYPE = new DebugInfoDiagnosticFactory("ELEMENT_WITH_ERROR_TYPE");
public static final DebugInfoDiagnosticFactory UNRESOLVED_WITH_TARGET = new DebugInfoDiagnosticFactory("UNRESOLVED_WITH_TARGET");
public static final DebugInfoDiagnosticFactory MISSING_UNRESOLVED = new DebugInfoDiagnosticFactory("MISSING_UNRESOLVED");
public static final DebugInfoDiagnosticFactory DYNAMIC = new DebugInfoDiagnosticFactory("DYNAMIC");
private final String name;
private DebugInfoDiagnosticFactory(String name, Severity severity) {
@@ -23,7 +23,9 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.Errors;
@@ -32,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypesPackage;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection;
@@ -55,6 +58,8 @@ public class DebugInfoUtil {
public abstract void reportMissingUnresolved(@NotNull JetReferenceExpression expression);
public abstract void reportUnresolvedWithTarget(@NotNull JetReferenceExpression expression, @NotNull String target);
public void reportDynamicCall(@NotNull JetReferenceExpression expression) { }
}
public static void markDebugAnnotations(
@@ -113,6 +118,14 @@ public class DebugInfoUtil {
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, expression);
if (declarationDescriptor != null) {
target = declarationDescriptor.toString();
if (declarationDescriptor instanceof CallableDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor;
ReceiverParameterDescriptor dispatchReceiverParameter = callableDescriptor.getDispatchReceiverParameter();
if (dispatchReceiverParameter != null && TypesPackage.isDynamic(dispatchReceiverParameter.getReturnType())) {
debugInfoReporter.reportDynamicCall(expression);
}
}
}
if (target == null) {
PsiElement labelTarget = bindingContext.get(LABEL_TARGET, expression);
@@ -0,0 +1,38 @@
// !MARK_DYNAMIC_CALLS
// MODULE[js]: m1
// FILE: k.kt
fun test(d: dynamic) {
d.foo()
d.<!DEBUG_INFO_DYNAMIC!>foo<!>(1)
d.bar()
d.baz()
d == 1
d.equals(1)
d?.equals(1)
d.hashCode()
d?.hashCode()
d.toString()
d?.toString()
}
fun Any.foo() {}
fun Any?.bar() {}
fun String.baz() {}
class C {
fun test(d: dynamic) {
d.<!DEBUG_INFO_DYNAMIC!>member<!>()
d.memberExtension()
}
fun member() {}
fun Any.memberExtension() {}
}
@@ -0,0 +1,16 @@
package
internal fun test(/*0*/ d: dynamic): kotlin.Unit
internal fun kotlin.Any?.bar(): kotlin.Unit
internal fun kotlin.String.baz(): kotlin.Unit
internal fun kotlin.Any.foo(): kotlin.Unit
internal final class C {
public constructor C()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
internal final fun member(): kotlin.Unit
internal final fun test(/*0*/ d: dynamic): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal final fun kotlin.Any.memberExtension(): kotlin.Unit
}
@@ -78,6 +78,8 @@ public abstract class BaseDiagnosticsTest extends
public static final String CHECK_LAZY_LOG_DIRECTIVE = "CHECK_LAZY_LOG";
public static final boolean CHECK_LAZY_LOG_DEFAULT = "true".equals(System.getProperty("check.lazy.logs", "false"));
public static final String MARK_DYNAMIC_CALLS_DIRECTIVE = "MARK_DYNAMIC_CALLS";
@Override
protected TestModule createTestModule(@NotNull String name) {
return new TestModule(name);
@@ -240,6 +242,7 @@ public abstract class BaseDiagnosticsTest extends
private final boolean declareCheckType;
private final boolean declareFlexibleType;
public final boolean checkLazyLog;
private final boolean markDynamicCalls;
public TestFile(
@Nullable TestModule module,
@@ -252,6 +255,7 @@ public abstract class BaseDiagnosticsTest extends
this.checkLazyLog = directives.containsKey(CHECK_LAZY_LOG_DIRECTIVE) || CHECK_LAZY_LOG_DEFAULT;
this.declareCheckType = directives.containsKey(CHECK_TYPE_DIRECTIVE);
this.declareFlexibleType = directives.containsKey(EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE);
this.markDynamicCalls = directives.containsKey(MARK_DYNAMIC_CALLS_DIRECTIVE);
if (fileName.endsWith(".java")) {
PsiFileFactory.getInstance(getProject()).createFileFromText(fileName, JavaLanguage.INSTANCE, textWithMarkers);
// TODO: check there's not syntax errors
@@ -334,7 +338,7 @@ public abstract class BaseDiagnosticsTest extends
final boolean[] ok = { true };
List<Diagnostic> diagnostics = ContainerUtil.filter(
KotlinPackage.plus(CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile),
KotlinPackage.plus(CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile, markDynamicCalls),
jvmSignatureDiagnostics),
whatDiagnosticsToConsider
);
@@ -147,7 +147,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
(JetFile) psiFile)
.getBindingContext();
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString();
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false)).toString();
List<DiagnosedRange> diagnosedRanges = Lists.newArrayList();
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
@@ -155,7 +155,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
diagnosedRange.setFile(psiFile);
}
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile);
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false);
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
makeTestData(diagnostics, diagnosedRanges);
@@ -3746,6 +3746,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("extensions.kt")
public void testExtensions() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/extensions.kt");
doTest(fileName);
}
@TestMetadata("implicitDynamicReceiver.kt")
public void testImplicitDynamicReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/implicitDynamicReceiver.kt");
@@ -42,7 +42,7 @@ public class CopyAsDiagnosticTestAction extends AnAction {
BindingContext bindingContext = ResolvePackage.analyzeFully((JetFile) psiFile);
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile);
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false);
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, diagnostics).toString();
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();