From c4ecb9663ac53bd8149672d5415027968d96072d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 12 Nov 2013 23:21:24 +0400 Subject: [PATCH] Basic utility for rendering DataFlowValues --- .../jet/generators/tests/GenerateTests.java | 7 ++ .../DataFlowInfoUtilForCopmletion.kt | 25 ++++++ .../dataFlowValueRendering/classProperty.kt | 9 ++ .../dataFlowValueRendering/classProperty.txt | 1 + .../complexIdentifier.kt | 9 ++ .../complexIdentifier.txt | 1 + .../complexIdentifierWithImplicitReceiver.kt | 9 ++ .../complexIdentifierWithImplicitReceiver.txt | 1 + ...IdentifierWithInitiallyNullableReceiver.kt | 9 ++ ...dentifierWithInitiallyNullableReceiver.txt | 2 + .../complexIdentifierWithReceiver.kt | 9 ++ .../complexIdentifierWithReceiver.txt | 1 + .../multipleVariables.kt | 7 ++ .../multipleVariables.txt | 2 + .../dataFlowValueRendering/packageProperty.kt | 9 ++ .../packageProperty.txt | 1 + .../dataFlowValueRendering/receivers.kt | 7 ++ .../dataFlowValueRendering/receivers.txt | 2 + .../dataFlowValueRendering/smartCast.kt | 5 ++ .../dataFlowValueRendering/smartCast.txt | 1 + .../dataFlowValueRendering/smartNotNull.kt | 5 ++ .../dataFlowValueRendering/smartNotNull.txt | 1 + .../completion/DataFlowValueRenderingTest.kt | 52 +++++++++++ .../DataFlowValueRenderingTestGenerated.java | 89 +++++++++++++++++++ 24 files changed, 264 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/DataFlowInfoUtilForCopmletion.kt create mode 100644 idea/testData/dataFlowValueRendering/classProperty.kt create mode 100644 idea/testData/dataFlowValueRendering/classProperty.txt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifier.kt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifier.txt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.kt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.txt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.kt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.txt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.kt create mode 100644 idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.txt create mode 100644 idea/testData/dataFlowValueRendering/multipleVariables.kt create mode 100644 idea/testData/dataFlowValueRendering/multipleVariables.txt create mode 100644 idea/testData/dataFlowValueRendering/packageProperty.kt create mode 100644 idea/testData/dataFlowValueRendering/packageProperty.txt create mode 100644 idea/testData/dataFlowValueRendering/receivers.kt create mode 100644 idea/testData/dataFlowValueRendering/receivers.txt create mode 100644 idea/testData/dataFlowValueRendering/smartCast.kt create mode 100644 idea/testData/dataFlowValueRendering/smartCast.txt create mode 100644 idea/testData/dataFlowValueRendering/smartNotNull.kt create mode 100644 idea/testData/dataFlowValueRendering/smartNotNull.txt create mode 100644 idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTest.kt create mode 100644 idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTestGenerated.java diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java index e5a1daa3177..869fe5a7c53 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.java @@ -523,6 +523,13 @@ public class GenerateTests { AbstractOutOfBlockModificationTest.class, testModel("idea/testData/codeInsight/outOfBlock") ); + + generateTest( + "idea/tests/", + "DataFlowValueRenderingTestGenerated", + AbstractDataFlowValueRenderingTest.class, + testModel("idea/testData/dataFlowValueRendering") + ); } private static SimpleTestClassModel testModel(@NotNull String rootPath) { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DataFlowInfoUtilForCopmletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/DataFlowInfoUtilForCopmletion.kt new file mode 100644 index 00000000000..44791dd7cad --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/DataFlowInfoUtilForCopmletion.kt @@ -0,0 +1,25 @@ +package org.jetbrains.jet.plugin.completion + +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue +import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.descriptors.VariableDescriptor +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor +import org.jetbrains.jet.lang.resolve.DescriptorUtils + +fun renderDataFlowValue(value: DataFlowValue): String? { + // If it is not a stable identifier, there's no point in rendering it + if (!value.isStableIdentifier()) return null + + fun renderId(id: Any?): String? { + return when (id) { + is JetExpression -> id.getText() + is ThisReceiver -> "this@${id.getDeclarationDescriptor().getName()}" + is VariableDescriptor -> id.getName().asString() + is NamespaceDescriptor -> DescriptorUtils.getFQName(id).asString() + is com.intellij.openapi.util.Pair<*, *> -> renderId(id.first) + "." + renderId(id.second) + else -> null + } + } + return renderId(value.getId()) +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/classProperty.kt b/idea/testData/dataFlowValueRendering/classProperty.kt new file mode 100644 index 00000000000..e65e35eb21f --- /dev/null +++ b/idea/testData/dataFlowValueRendering/classProperty.kt @@ -0,0 +1,9 @@ +class C { + val a: Any? = null + + fun test() { + if (a is String) { + null + } + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/classProperty.txt b/idea/testData/dataFlowValueRendering/classProperty.txt new file mode 100644 index 00000000000..83a0f41cc3d --- /dev/null +++ b/idea/testData/dataFlowValueRendering/classProperty.txt @@ -0,0 +1 @@ +this@C.a \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifier.kt b/idea/testData/dataFlowValueRendering/complexIdentifier.kt new file mode 100644 index 00000000000..a8b9983b53a --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifier.kt @@ -0,0 +1,9 @@ +fun outer(c: C) { + if (c.x is String) { + null + } +} + +class C { + val x: Any? = null +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifier.txt b/idea/testData/dataFlowValueRendering/complexIdentifier.txt new file mode 100644 index 00000000000..cb7c3cea3dd --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifier.txt @@ -0,0 +1 @@ +c.x \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.kt b/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.kt new file mode 100644 index 00000000000..92afe1bcb4c --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.kt @@ -0,0 +1,9 @@ +fun C.outer(a: Any?) { + if (x is String) { + null + } +} + +class C { + val x: Any? = null +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.txt b/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.txt new file mode 100644 index 00000000000..47248a8cdb9 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.txt @@ -0,0 +1 @@ +this@outer.x \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.kt b/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.kt new file mode 100644 index 00000000000..24307a78307 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.kt @@ -0,0 +1,9 @@ +fun outer(c: C?) { + if (c != null && c.x is String) { + null + } +} + +class C { + val x: Any? = null +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.txt b/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.txt new file mode 100644 index 00000000000..7e2809afcc7 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.txt @@ -0,0 +1,2 @@ +c +c.x \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.kt b/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.kt new file mode 100644 index 00000000000..ca1b6604dae --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.kt @@ -0,0 +1,9 @@ +fun C.outer(a: Any?) { + if (this.x is String) { + null + } +} + +class C { + val x: Any? = null +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.txt b/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.txt new file mode 100644 index 00000000000..47248a8cdb9 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.txt @@ -0,0 +1 @@ +this@outer.x \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/multipleVariables.kt b/idea/testData/dataFlowValueRendering/multipleVariables.kt new file mode 100644 index 00000000000..8ac8dd633b9 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/multipleVariables.kt @@ -0,0 +1,7 @@ +fun outer(a: Any?) { + fun inner(b: Any?) { + if (a is String && b is String) { + null + } + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/multipleVariables.txt b/idea/testData/dataFlowValueRendering/multipleVariables.txt new file mode 100644 index 00000000000..0a207c060e6 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/multipleVariables.txt @@ -0,0 +1,2 @@ +a +b \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/packageProperty.kt b/idea/testData/dataFlowValueRendering/packageProperty.kt new file mode 100644 index 00000000000..4b347c59b03 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/packageProperty.kt @@ -0,0 +1,9 @@ +package foo + +val a: Any? = null + +fun outer() { + if (a is String) { + null + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/packageProperty.txt b/idea/testData/dataFlowValueRendering/packageProperty.txt new file mode 100644 index 00000000000..2e65efe2a14 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/packageProperty.txt @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/receivers.kt b/idea/testData/dataFlowValueRendering/receivers.kt new file mode 100644 index 00000000000..b97adcef16e --- /dev/null +++ b/idea/testData/dataFlowValueRendering/receivers.kt @@ -0,0 +1,7 @@ +fun Any?.outer() { + fun Any?.inner() { + if (this is String && this@outer is String) { + null + } + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/receivers.txt b/idea/testData/dataFlowValueRendering/receivers.txt new file mode 100644 index 00000000000..1abdc2621ee --- /dev/null +++ b/idea/testData/dataFlowValueRendering/receivers.txt @@ -0,0 +1,2 @@ +this@inner +this@outer \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/smartCast.kt b/idea/testData/dataFlowValueRendering/smartCast.kt new file mode 100644 index 00000000000..29aabf7f78f --- /dev/null +++ b/idea/testData/dataFlowValueRendering/smartCast.kt @@ -0,0 +1,5 @@ +fun outer(a: Any?) { + if (a is String) { + null + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/smartCast.txt b/idea/testData/dataFlowValueRendering/smartCast.txt new file mode 100644 index 00000000000..2e65efe2a14 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/smartCast.txt @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/smartNotNull.kt b/idea/testData/dataFlowValueRendering/smartNotNull.kt new file mode 100644 index 00000000000..5cf6c25004d --- /dev/null +++ b/idea/testData/dataFlowValueRendering/smartNotNull.kt @@ -0,0 +1,5 @@ +fun outer(a: Any?) { + if (a != null) { + null + } +} \ No newline at end of file diff --git a/idea/testData/dataFlowValueRendering/smartNotNull.txt b/idea/testData/dataFlowValueRendering/smartNotNull.txt new file mode 100644 index 00000000000..2e65efe2a14 --- /dev/null +++ b/idea/testData/dataFlowValueRendering/smartNotNull.txt @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTest.kt b/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTest.kt new file mode 100644 index 00000000000..9675711d434 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2013 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.completion + +import org.jetbrains.jet.plugin.PluginTestCaseBase +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache +import org.jetbrains.jet.lang.psi.JetFile +import org.jetbrains.jet.lang.resolve.BindingContext +import org.jetbrains.jet.lang.psi.JetExpression +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.jet.plugin.completion.renderDataFlowValue +import org.jetbrains.jet.JetTestUtils +import com.intellij.openapi.util.io.FileUtil +import java.io.File + +abstract class AbstractDataFlowValueRenderingTest: LightCodeInsightFixtureTestCase() { + override fun getTestDataPath() : String { + return PluginTestCaseBase.getTestDataPathBase() + "/dataFlowValueRendering/" + } + + fun doTest(fileName: String) { + val fixture = myFixture!! + fixture.configureByFile(fileName) + + val jetFile = fixture.getFile() as JetFile + val bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(jetFile).getBindingContext() + + val element = jetFile.findElementAt(fixture.getCaretOffset()) + val expression = PsiTreeUtil.getParentOfType(element, javaClass()) + val info = bindingContext.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression)!! + + val allValues = (info.getCompleteTypeInfo().keySet() + info.getCompleteNullabilityInfo().keySet()).toSet() + val actual = allValues.map { renderDataFlowValue(it) }.filterNotNull().sort().makeString("\n") + + JetTestUtils.assertEqualsToFile(File(FileUtil.getNameWithoutExtension(fileName) + ".txt"), actual) + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTestGenerated.java new file mode 100644 index 00000000000..8fa5eef7328 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/DataFlowValueRenderingTestGenerated.java @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2013 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.completion; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.io.File; +import java.util.regex.Pattern; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; + +import org.jetbrains.jet.completion.AbstractDataFlowValueRenderingTest; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/dataFlowValueRendering") +public class DataFlowValueRenderingTestGenerated extends AbstractDataFlowValueRenderingTest { + public void testAllFilesPresentInDataFlowValueRendering() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/dataFlowValueRendering"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("classProperty.kt") + public void testClassProperty() throws Exception { + doTest("idea/testData/dataFlowValueRendering/classProperty.kt"); + } + + @TestMetadata("complexIdentifier.kt") + public void testComplexIdentifier() throws Exception { + doTest("idea/testData/dataFlowValueRendering/complexIdentifier.kt"); + } + + @TestMetadata("complexIdentifierWithImplicitReceiver.kt") + public void testComplexIdentifierWithImplicitReceiver() throws Exception { + doTest("idea/testData/dataFlowValueRendering/complexIdentifierWithImplicitReceiver.kt"); + } + + @TestMetadata("complexIdentifierWithInitiallyNullableReceiver.kt") + public void testComplexIdentifierWithInitiallyNullableReceiver() throws Exception { + doTest("idea/testData/dataFlowValueRendering/complexIdentifierWithInitiallyNullableReceiver.kt"); + } + + @TestMetadata("complexIdentifierWithReceiver.kt") + public void testComplexIdentifierWithReceiver() throws Exception { + doTest("idea/testData/dataFlowValueRendering/complexIdentifierWithReceiver.kt"); + } + + @TestMetadata("multipleVariables.kt") + public void testMultipleVariables() throws Exception { + doTest("idea/testData/dataFlowValueRendering/multipleVariables.kt"); + } + + @TestMetadata("packageProperty.kt") + public void testPackageProperty() throws Exception { + doTest("idea/testData/dataFlowValueRendering/packageProperty.kt"); + } + + @TestMetadata("receivers.kt") + public void testReceivers() throws Exception { + doTest("idea/testData/dataFlowValueRendering/receivers.kt"); + } + + @TestMetadata("smartCast.kt") + public void testSmartCast() throws Exception { + doTest("idea/testData/dataFlowValueRendering/smartCast.kt"); + } + + @TestMetadata("smartNotNull.kt") + public void testSmartNotNull() throws Exception { + doTest("idea/testData/dataFlowValueRendering/smartNotNull.kt"); + } + +}