Add option to enable new inference only for IDE analysis

#KT-30453 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-04-29 17:37:29 +03:00
parent e857425b35
commit a3247b1b92
15 changed files with 179 additions and 13 deletions
@@ -223,6 +223,7 @@ add.script.runtime.to.classpath=Add kotlin-script-runtime.jar to the classpath
kotlin.compiler.option.generate.no.warnings=Report compiler &warnings
kotlin.compiler.option.additional.command.line.parameters=&Additional command line parameters:
kotlin.compiler.option.additional.command.line.parameters.dialog.title=Additional command line parameters
kotlin.compiler.option.enable.new.inference.in.ide=Enable new type inference algorithm for IDE analysis (experimental)
# Kotlin to JVM
kotlin.compiler.jvm.option.panel.title=Kotlin to JVM
@@ -252,3 +253,4 @@ android.klint.inspections.group.name=Android Lint for Kotlin
scratch.run.button=Run Scratch File
scratch.stop.button=Stop scratch execution
scratch.clear.button=Clear results
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.project
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.project.Project
object NewInferenceForIDEAnalysisComponent {
private const val inferenceOption = "kotlin.use.new.inference.for.ide.analysis"
private const val defaultState = false
@JvmStatic
fun setEnabled(project: Project, state: Boolean) {
PropertiesComponent.getInstance(project).setValue(inferenceOption, state, defaultState)
}
@JvmStatic
fun isEnabled(project: Project): Boolean {
return PropertiesComponent.getInstance(project).getBoolean(inferenceOption, defaultState)
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
@@ -138,6 +139,7 @@ fun Project.getLanguageVersionSettings(
CoroutineSupport.byCompilerArguments(KotlinCommonCompilerArgumentsHolder.getInstance(this@getLanguageVersionSettings).settings),
languageVersion
)
configureNewInferenceSupportInIDE(this@getLanguageVersionSettings)
if (isReleaseCoroutines != null) {
put(
LanguageFeature.ReleaseCoroutines,
@@ -194,6 +196,7 @@ private fun Module.computeLanguageVersionSettings(): LanguageVersionSettings {
val languageFeatures = facetSettings.mergedCompilerArguments?.configureLanguageFeatures(MessageCollector.NONE)?.apply {
configureCoroutinesSupport(facetSettings.coroutineSupport, languageVersion)
configureMultiplatformSupport(facetSettings.platform?.kind, this@computeLanguageVersionSettings)
configureNewInferenceSupportInIDE(project)
}.orEmpty()
val analysisFlags = facetSettings.mergedCompilerArguments?.configureAnalysisFlags(MessageCollector.NONE).orEmpty()
@@ -248,6 +251,13 @@ fun MutableMap<LanguageFeature, LanguageFeature.State>.configureMultiplatformSup
}
}
fun MutableMap<LanguageFeature, LanguageFeature.State>.configureNewInferenceSupportInIDE(
project: Project
) {
if (NewInferenceForIDEAnalysisComponent.isEnabled(project)) {
putIfAbsent(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
}
}
val PsiElement.languageVersionSettings: LanguageVersionSettings
get() {
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerConfigurableTab">
<grid id="27dc6" binding="contentPane" layout-manager="GridLayoutManager" row-count="12" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="contentPane" layout-manager="GridLayoutManager" row-count="13" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="350" y="20" width="920" height="1171"/>
@@ -12,13 +12,13 @@
<children>
<vspacer id="c5558">
<constraints>
<grid row="11" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="12" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="98e8a" binding="k2jsPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="8" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
<grid row="9" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
</constraints>
<properties>
<visible value="true"/>
@@ -153,7 +153,7 @@
<grid id="483d4" binding="scriptPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="9" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
<grid row="10" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
</constraints>
<properties>
<visible value="true"/>
@@ -229,7 +229,7 @@
<grid id="2f977" binding="k2jvmPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
<grid row="8" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="true"/>
</constraints>
<properties>
<visible value="true"/>
@@ -286,7 +286,7 @@
<grid id="99321" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
@@ -310,7 +310,7 @@
<grid id="775d3" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
@@ -334,7 +334,7 @@
<grid id="7f3d" binding="coroutinesPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
@@ -357,7 +357,7 @@
</grid>
<component id="ba279" class="javax.swing.JLabel" binding="additionalArgsLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.option.additional.command.line.parameters"/>
@@ -365,7 +365,7 @@
</component>
<component id="df236" class="com.intellij.ui.RawCommandLineEditor" binding="additionalArgsOptionsField">
<constraints>
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<dialogCaption value="Additional command line parameters"/>
@@ -373,13 +373,33 @@
</component>
<component id="dae3f" class="com.intellij.util.ui.ThreeStateCheckBox" binding="keepAliveCheckBox">
<constraints>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<state value="NOT_SELECTED"/>
<text value="Keep compiler process alive between invocations"/>
</properties>
</component>
<grid id="8b5c9" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="625f1" class="com.intellij.util.ui.ThreeStateCheckBox" binding="enableNewInferenceInIDECheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="false"/>
<state value="NOT_SELECTED"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.option.enable.new.inference.in.ide"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>
@@ -36,8 +36,10 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.PluginStartupComponent;
import org.jetbrains.kotlin.idea.configuration.ProjectUtilsKt;
import org.jetbrains.kotlin.idea.facet.DescriptionListCellRenderer;
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
import org.jetbrains.kotlin.idea.project.NewInferenceForIDEAnalysisComponent;
import org.jetbrains.kotlin.idea.roots.RootUtilsKt;
import org.jetbrains.kotlin.idea.util.CidrUtil;
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt;
@@ -110,6 +112,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
private JLabel labelForSourceMapPrefix;
private JComboBox sourceMapEmbedSources;
private JPanel coroutinesPanel;
private ThreeStateCheckBox enableNewInferenceInIDECheckBox;
private boolean isEnabled = true;
public KotlinCompilerConfigurableTab(
@@ -150,6 +153,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
}
reportWarningsCheckBox.setThirdStateEnabled(isMultiEditor);
enableNewInferenceInIDECheckBox.setThirdStateEnabled(isMultiEditor);
if (isProjectSettings) {
List<String> modulesOverridingProjectSettings = ArraysKt.mapNotNull(
@@ -207,6 +211,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
keepAliveCheckBox.setVisible(false);
k2jvmPanel.setVisible(false);
enableIncrementalCompilationForJsCheckBox.setVisible(false);
enableNewInferenceInIDECheckBox.setVisible(false);
}
updateOutputDirEnabled();
@@ -438,6 +443,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
@Override
public boolean isModified() {
return isModified(reportWarningsCheckBox, !commonCompilerArguments.getSuppressWarnings()) ||
isModified(enableNewInferenceInIDECheckBox, NewInferenceForIDEAnalysisComponent.isEnabled(project)) ||
!getSelectedLanguageVersionView().equals(KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments)) ||
!getSelectedAPIVersionView().equals(KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments)) ||
!getSelectedCoroutineState().equals(commonCompilerArguments.getCoroutinesState()) ||
@@ -515,7 +521,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
!getSelectedLanguageVersionView().equals(KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments)) ||
!getSelectedAPIVersionView().equals(KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments)) ||
!getSelectedCoroutineState().equals(commonCompilerArguments.getCoroutinesState()) ||
!additionalArgsOptionsField.getText().equals(compilerSettings.getAdditionalArguments());
!additionalArgsOptionsField.getText().equals(compilerSettings.getAdditionalArguments()) ||
enableNewInferenceInIDECheckBox.isSelected() != NewInferenceForIDEAnalysisComponent.isEnabled(project);
if (shouldInvalidateCaches) {
ApplicationUtilsKt.runWriteAction(
@@ -531,6 +538,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
}
commonCompilerArguments.setSuppressWarnings(!reportWarningsCheckBox.isSelected());
NewInferenceForIDEAnalysisComponent.setEnabled(project, enableNewInferenceInIDECheckBox.isSelected());
KotlinFacetSettingsKt.setLanguageVersionView(commonCompilerArguments, getSelectedLanguageVersionView());
KotlinFacetSettingsKt.setApiVersionView(commonCompilerArguments, getSelectedAPIVersionView());
@@ -583,6 +591,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
@Override
public void reset() {
reportWarningsCheckBox.setSelected(!commonCompilerArguments.getSuppressWarnings());
enableNewInferenceInIDECheckBox.setSelected(NewInferenceForIDEAnalysisComponent.isEnabled(project));
languageVersionComboBox.setSelectedItem(KotlinFacetSettingsKt.getLanguageVersionView(commonCompilerArguments));
onLanguageLevelChanged(getSelectedLanguageVersionView());
apiVersionComboBox.setSelectedItem(KotlinFacetSettingsKt.getApiVersionView(commonCompilerArguments));
@@ -635,6 +644,10 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
return reportWarningsCheckBox;
}
public ThreeStateCheckBox getEnableNewInferenceInIDECheckBox() {
return enableNewInferenceInIDECheckBox;
}
public RawCommandLineEditor getAdditionalArgsOptionsField() {
return additionalArgsOptionsField;
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.configuration
import com.intellij.openapi.module.Module
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.search.FileTypeIndex
import org.jetbrains.kotlin.idea.KotlinFileType
@@ -15,4 +16,4 @@ fun hasKotlinFilesOnlyInTests(module: Module): Boolean {
fun hasKotlinFilesInSources(module: Module): Boolean {
return FileTypeIndex.containsFileOfType(KotlinFileType.INSTANCE, module.getModuleScope(false))
}
}
@@ -44,6 +44,7 @@ class MultipleKotlinFacetEditor(
helper.bind(targetPlatformComboBox, editors) { it.tabEditor.targetPlatformComboBox }
with(compilerConfigurable) {
helper.bind(reportWarningsCheckBox, editors) { it.compilerConfigurable.reportWarningsCheckBox }
helper.bind(enableNewInferenceInIDECheckBox, editors) { it.compilerConfigurable.enableNewInferenceInIDECheckBox }
helper.bind(additionalArgsOptionsField.textField, editors) { it.compilerConfigurable.additionalArgsOptionsField.textField }
helper.bind(generateSourceMapsCheckBox, editors) { it.compilerConfigurable.generateSourceMapsCheckBox}
helper.bind(outputPrefixFile.textField, editors) { it.compilerConfigurable.outputPrefixFile.textField }
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtil.toSystemIndependentName
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.testFramework.LightVirtualFile
@@ -707,6 +708,34 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
result.assertSuccessful()
}
/*
* Here we're checking that enabling inference in IDE doesn't affect compilation via JPS
*
* the following two tests are connected:
* - testKotlinProjectWithEnabledNewInferenceInIDE checks that project is compiled when new inference is enabled only in IDE
* - this is done via project component
* - testKotlinProjectWithErrorsBecauseOfNewInference checks that project isn't compiled when new inference is enabled in the compiler
*
* So, if the former will fail => option affects JPS compilation, it's bad. Also, if the latter test fails => test is useless as it's
* compiled with new and old inference.
*
*/
fun testKotlinProjectWithEnabledNewInferenceInIDE() {
doTest()
}
fun testKotlinProjectWithErrorsBecauseOfNewInference() {
initProject(JVM_MOCK_RUNTIME)
val module = myProject.modules.single()
val args = module.kotlinCompilerArguments
args.newInference = true
myProject.kotlinCommonCompilerArguments = args
val result = buildAllModules()
result.assertFailed()
result.checkErrors()
}
private fun createKotlinJavaScriptLibraryArchive() {
val jarFile = File(workDir, KOTLIN_JS_LIBRARY_JAR)
try {
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="kotlinProject" />
</component>
</module>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/kotlinProject.iml" filepath="$PROJECT_DIR$/kotlinProject.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA_JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="PropertiesComponent">
<property name="kotlin.use.new.inference.for.ide.analysis" value="true" />
</component>
</project>
@@ -0,0 +1,5 @@
fun foo() {
ByteArray(42) {
when (Any()) {}
}
}
@@ -0,0 +1 @@
Type mismatch: inferred type is Unit but Byte was expected at line 3, column 9
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="kotlinProject" />
</component>
</module>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/kotlinProject.iml" filepath="$PROJECT_DIR$/kotlinProject.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA_JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -0,0 +1,5 @@
fun foo() {
ByteArray(42) {
when (Any()) {}
}
}