as32: Update to AS 3.2 C10
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalAnnotator language="kotlin" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,120 @@
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<xi:include href="android-lint.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<gotoDeclarationHandler implementation="org.jetbrains.kotlin.android.navigation.KotlinAndroidGotoDeclarationHandler"/>
|
||||
|
||||
<moduleService serviceInterface="org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager"
|
||||
serviceImplementation="org.jetbrains.kotlin.android.synthetic.idea.res.IDEAndroidLayoutXmlFileManager"/>
|
||||
<psi.treeChangePreprocessor implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor"/>
|
||||
<errorHandler implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidExtensionsReportSubmitter"/>
|
||||
<gotoDeclarationHandler implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidGotoDeclarationHandler"/>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.android.inspection.IllegalIdentifierInspection"
|
||||
displayName="Illegal Android Identifier"
|
||||
groupName="Kotlin Android"
|
||||
enabledByDefault="true"
|
||||
level="ERROR"/>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.android.inspection.TypeParameterFindViewByIdInspection"
|
||||
displayName="Cast can be converted to findViewById with type parameter"
|
||||
groupName="Kotlin Android"
|
||||
enabledByDefault="true"
|
||||
cleanupTool="true"
|
||||
level="WEAK WARNING"
|
||||
language="kotlin" />
|
||||
|
||||
<codeInsight.lineMarkerProvider language="kotlin" implementationClass="org.jetbrains.kotlin.android.KotlinAndroidLineMarkerProvider"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.KotlinAndroidAddStringResource</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.android.configure.KotlinGradleAndroidModuleModelProjectDataService"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.AddActivityToManifest</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.AddServiceToManifest</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.ImplementParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.RemoveParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.RedoParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<codeInsight.unresolvedReferenceQuickFixProvider
|
||||
implementation="org.jetbrains.kotlin.android.inspection.KotlinAndroidResourceQuickFixProvider"/>
|
||||
|
||||
<lang.foldingBuilder language="kotlin" implementationClass="org.jetbrains.kotlin.android.folding.ResourceFoldingBuilder" />
|
||||
|
||||
<annotator language="kotlin" implementationClass="org.jetbrains.kotlin.android.AndroidResourceReferenceAnnotator" />
|
||||
|
||||
<referencesSearch implementation="org.jetbrains.kotlin.AndroidExtensionsReferenceSearchExecutor"/>
|
||||
|
||||
<externalProjectDataService implementation="org.jetbrains.kotlin.android.configure.KotlinAndroidGradleLibraryDataService"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
|
||||
<projectResolve implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidExtensionsProjectResolverExtension"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.IDEAndroidExtensionsExpressionCodegenExtension"/>
|
||||
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.android.synthetic.AndroidExtensionPropertiesComponentContainerContributor"/>
|
||||
<classBuilderFactoryInterceptorExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.IDEAndroidOnDestroyClassBuilderInterceptorExtension"/>
|
||||
<packageFragmentProviderExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.res.IDEAndroidPackageFragmentProviderExtension"/>
|
||||
<simpleNameReferenceExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidSimpleNameReferenceExtension"/>
|
||||
<kotlinIndicesHelperExtension implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidIndicesHelperExtension"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.android.synthetic.idea.AndroidExtensionsGradleImportHandler"/>
|
||||
|
||||
<quickFixContributor implementation="org.jetbrains.kotlin.android.quickfix.AndroidQuickFixRegistrar"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.android.configure.KotlinAndroidGradleModuleConfigurator"/>
|
||||
<gradleModelFacade implementation="org.jetbrains.kotlin.android.configure.AndroidGradleModelFacade"/>
|
||||
<completionInformationProvider implementation="org.jetbrains.kotlin.AndroidExtensionsCompletionInformationProvider" />
|
||||
|
||||
<expressionCodegenExtension implementation="org.jetbrains.kotlin.android.parcel.IDEParcelableCodegenExtension"/>
|
||||
<syntheticResolveExtension implementation="org.jetbrains.kotlin.android.parcel.IDEParcelableResolveExtension"/>
|
||||
<classBuilderFactoryInterceptorExtension implementation="org.jetbrains.kotlin.android.synthetic.codegen.ParcelableClinitClassBuilderInterceptorExtension"/>
|
||||
<quickFixContributor implementation="org.jetbrains.kotlin.android.parcel.quickfixes.ParcelableQuickFixContributor"/>
|
||||
|
||||
<androidDexer implementation="org.jetbrains.kotlin.android.debugger.AndroidDexerImpl"/>
|
||||
|
||||
<highlighterExtension implementation="org.jetbrains.kotlin.android.AndroidHighlighterExtension"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.android.tools.idea">
|
||||
<npw.template.convertJavaToKotlinProvider implementation="org.jetbrains.kotlin.android.ConvertJavaToKotlinProviderImpl"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.android">
|
||||
<androidLintQuickFixProvider implementation="org.jetbrains.kotlin.android.quickfix.KotlinAndroidQuickFixProvider" />
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.android.gradle.sync">
|
||||
<postSyncModuleSetupStep implementation="org.jetbrains.kotlin.android.configure.KotlinAndroidModuleSetupStep"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.android.model">
|
||||
<androidModuleInfoProvider implementation="org.jetbrains.kotlin.android.model.impl.AndroidModuleInfoProviderImpl"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -6,9 +6,10 @@
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="173.4548.28" until-build="173.*"/>
|
||||
<idea-version since-build="181.1" until-build="181.*"/>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.remoteServers</depends>
|
||||
|
||||
<!-- required for Kotlin/Native plugin -->
|
||||
<depends optional="true">org.jetbrains.kotlin.native.platform.deps</depends>
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.actions
|
||||
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||
import com.intellij.ide.scratch.ScratchFileService
|
||||
import com.intellij.ide.scratch.ScratchRootType
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.ex.MessagesEx
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.j2k.ConverterSettings
|
||||
import org.jetbrains.kotlin.j2k.JavaToKotlinConverter
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class JavaToKotlinAction : AnAction() {
|
||||
companion object {
|
||||
private fun uniqueKotlinFileName(javaFile: VirtualFile): String {
|
||||
val ioFile = File(javaFile.path.replace('/', File.separatorChar))
|
||||
|
||||
var i = 0
|
||||
while (true) {
|
||||
val fileName = javaFile.nameWithoutExtension + (if (i > 0) i else "") + ".kt"
|
||||
if (!ioFile.resolveSibling(fileName).exists()) return fileName
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
val title = "Convert Java to Kotlin"
|
||||
|
||||
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
|
||||
try {
|
||||
val document = PsiDocumentManager.getInstance(psiFile.project).getDocument(psiFile)
|
||||
if (document == null) {
|
||||
MessagesEx.error(psiFile.project, "Failed to save conversion result: couldn't find document for " + psiFile.name).showLater()
|
||||
continue
|
||||
}
|
||||
document.replaceString(0, document.textLength, text)
|
||||
FileDocumentManager.getInstance().saveDocument(document)
|
||||
|
||||
val virtualFile = psiFile.virtualFile
|
||||
if (ScratchRootType.getInstance().containsFile(virtualFile)) {
|
||||
val mapping = ScratchFileService.getInstance().scratchesMapping
|
||||
mapping.setMapping(virtualFile, KotlinFileType.INSTANCE.language)
|
||||
}
|
||||
else {
|
||||
val fileName = uniqueKotlinFileName(virtualFile)
|
||||
virtualFile.rename(this, fileName)
|
||||
}
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.project, e.message ?: "").showLater()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun convertFiles(javaFiles: List<PsiJavaFile>, project: Project,
|
||||
enableExternalCodeProcessing: Boolean = true,
|
||||
askExternalCodeProcessing: Boolean = true): List<KtFile> {
|
||||
var converterResult: JavaToKotlinConverter.FilesResult? = null
|
||||
fun convert() {
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices)
|
||||
converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().progressIndicator!!)
|
||||
}
|
||||
|
||||
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
::convert,
|
||||
title,
|
||||
true,
|
||||
project)) return emptyList()
|
||||
|
||||
|
||||
var externalCodeUpdate: (() -> Unit)? = null
|
||||
|
||||
if (enableExternalCodeProcessing && converterResult!!.externalCodeProcessing != null) {
|
||||
val question = "Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?"
|
||||
if (!askExternalCodeProcessing || (Messages.showOkCancelDialog(project, question, title, Messages.getQuestionIcon()) == Messages.OK)) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction {
|
||||
externalCodeUpdate = converterResult!!.externalCodeProcessing!!.prepareWriteOperation(ProgressManager.getInstance().progressIndicator!!)
|
||||
}
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)
|
||||
}
|
||||
}
|
||||
|
||||
return project.executeWriteCommand("Convert files from Java to Kotlin", null) {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
val newFiles = saveResults(javaFiles, converterResult!!.results)
|
||||
|
||||
externalCodeUpdate?.invoke()
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
|
||||
newFiles.map { it.toPsiFile(project) as KtFile }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val javaFiles = selectedJavaFiles(e).filter { it.isWritable }.toList()
|
||||
val project = CommonDataKeys.PROJECT.getData(e.dataContext)!!
|
||||
|
||||
val firstSyntaxError = javaFiles.asSequence().map { PsiTreeUtil.findChildOfType(it, PsiErrorElement::class.java) }.firstOrNull()
|
||||
|
||||
if (firstSyntaxError != null) {
|
||||
val count = javaFiles.filter { PsiTreeUtil.hasErrorElements(it) }.count()
|
||||
val question = firstSyntaxError.containingFile.name +
|
||||
(if (count > 1) " and ${count - 1} more Java files" else " file") +
|
||||
" contain syntax errors, the conversion result may be incorrect"
|
||||
|
||||
val okText = "Investigate Errors"
|
||||
val cancelText = "Proceed with Conversion"
|
||||
if (Messages.showOkCancelDialog(
|
||||
project,
|
||||
question,
|
||||
title,
|
||||
okText,
|
||||
cancelText,
|
||||
Messages.getWarningIcon()
|
||||
) == Messages.OK) {
|
||||
NavigationUtil.activateFileWithPsiElement(firstSyntaxError.navigationElement)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
convertFiles(javaFiles, project)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return
|
||||
val project = e.project ?: return
|
||||
|
||||
e.presentation.isEnabled = isAnyJavaFileSelected(project, virtualFiles)
|
||||
}
|
||||
|
||||
private fun isAnyJavaFileSelected(project: Project, files: Array<VirtualFile>): Boolean {
|
||||
val manager = PsiManager.getInstance(project)
|
||||
|
||||
if (files.any { manager.findFile(it) is PsiJavaFile && it.isWritable }) return true
|
||||
return files.any { it.isDirectory && isAnyJavaFileSelected(project, it.children) }
|
||||
}
|
||||
|
||||
private fun selectedJavaFiles(e: AnActionEvent): Sequence<PsiJavaFile> {
|
||||
val virtualFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY) ?: return sequenceOf()
|
||||
val project = e.project ?: return sequenceOf()
|
||||
return allJavaFiles(virtualFiles, project)
|
||||
}
|
||||
|
||||
private fun allJavaFiles(filesOrDirs: Array<VirtualFile>, project: Project): Sequence<PsiJavaFile> {
|
||||
val manager = PsiManager.getInstance(project)
|
||||
return allFiles(filesOrDirs)
|
||||
.asSequence()
|
||||
.mapNotNull { manager.findFile(it) as? PsiJavaFile }
|
||||
}
|
||||
|
||||
private fun allFiles(filesOrDirs: Array<VirtualFile>): Collection<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for (file in filesOrDirs) {
|
||||
VfsUtilCore.visitChildrenRecursively(file, object : VirtualFileVisitor<Unit>() {
|
||||
override fun visitFile(file: VirtualFile): Boolean {
|
||||
result.add(file)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.kotlin.idea.facet
|
||||
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.projectRoots.JavaSdk
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ModuleRootModel
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.*
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
||||
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.versions.*
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
|
||||
for (platform in TargetPlatformKind.ALL_PLATFORMS) {
|
||||
if (getRuntimeLibraryVersions(module, rootModel, platform).isNotEmpty()) {
|
||||
return platform
|
||||
}
|
||||
}
|
||||
|
||||
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
|
||||
val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk!!)
|
||||
return when {
|
||||
sdkVersion == null || sdkVersion >= JavaSdkVersion.JDK_1_8 -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_8]
|
||||
else -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinFacetSettings.initializeIfNeeded(
|
||||
module: Module,
|
||||
rootModel: ModuleRootModel?,
|
||||
platformKind: TargetPlatformKind<*>? = null, // if null, detect by module dependencies
|
||||
languageVersion: String? = null
|
||||
) {
|
||||
val project = module.project
|
||||
|
||||
val shouldInferLanguageLevel = languageLevel == null
|
||||
val shouldInferAPILevel = apiLevel == null
|
||||
|
||||
if (compilerSettings == null) {
|
||||
compilerSettings = KotlinCompilerSettings.getInstance(project).settings
|
||||
}
|
||||
|
||||
val commonArguments = KotlinCommonCompilerArgumentsHolder.getInstance(module.project).settings
|
||||
|
||||
if (compilerArguments == null) {
|
||||
val targetPlatformKind = platformKind ?: getDefaultTargetPlatform(module, rootModel)
|
||||
compilerArguments = targetPlatformKind.createCompilerArguments {
|
||||
targetPlatformKind.getPlatformCompilerArgumentsByProject(module.project)?.let { mergeBeans(it, this) }
|
||||
mergeBeans(commonArguments, this)
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldInferLanguageLevel) {
|
||||
languageLevel = (if (useProjectSettings) LanguageVersion.fromVersionString(commonArguments.languageVersion) else null)
|
||||
?: getDefaultLanguageLevel(module, languageVersion)
|
||||
}
|
||||
|
||||
if (shouldInferAPILevel) {
|
||||
apiLevel = if (useProjectSettings) {
|
||||
LanguageVersion.fromVersionString(commonArguments.apiVersion) ?: languageLevel
|
||||
}
|
||||
else {
|
||||
languageLevel!!.coerceAtMost(getLibraryLanguageLevel(module, rootModel, targetPlatformKind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun TargetPlatformKind<*>.getPlatformCompilerArgumentsByProject(project: Project): CommonCompilerArguments? {
|
||||
return when (this) {
|
||||
is TargetPlatformKind.Jvm -> Kotlin2JvmCompilerArgumentsHolder.getInstance(project).settings
|
||||
is TargetPlatformKind.JavaScript -> Kotlin2JsCompilerArgumentsHolder.getInstance(project).settings
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val TargetPlatformKind<*>.mavenLibraryIds: List<String>
|
||||
get() = when (this) {
|
||||
is TargetPlatformKind.Jvm -> listOf(MAVEN_STDLIB_ID, MAVEN_STDLIB_ID_JRE7, MAVEN_STDLIB_ID_JDK7, MAVEN_STDLIB_ID_JRE8, MAVEN_STDLIB_ID_JDK8)
|
||||
is TargetPlatformKind.JavaScript -> listOf(MAVEN_JS_STDLIB_ID, MAVEN_OLD_JS_STDLIB_ID)
|
||||
is TargetPlatformKind.Common -> listOf(MAVEN_COMMON_STDLIB_ID)
|
||||
}
|
||||
|
||||
val mavenLibraryIdToPlatform: Map<String, TargetPlatformKind<*>> by lazy {
|
||||
TargetPlatformKind.ALL_PLATFORMS
|
||||
.flatMap { platform -> platform.mavenLibraryIds.map { it to platform } }
|
||||
.sortedByDescending { it.first.length }
|
||||
.toMap()
|
||||
}
|
||||
|
||||
fun Module.getOrCreateFacet(modelsProvider: IdeModifiableModelsProvider,
|
||||
useProjectSettings: Boolean,
|
||||
commitModel: Boolean = false): KotlinFacet {
|
||||
val facetModel = modelsProvider.getModifiableFacetModel(this)
|
||||
|
||||
val facet = facetModel.findFacet(KotlinFacetType.TYPE_ID, KotlinFacetType.INSTANCE.defaultFacetName)
|
||||
?: with(KotlinFacetType.INSTANCE) { createFacet(this@getOrCreateFacet, defaultFacetName, createDefaultConfiguration(), null) }
|
||||
.apply { facetModel.addFacet(this) }
|
||||
facet.configuration.settings.useProjectSettings = useProjectSettings
|
||||
if (commitModel) {
|
||||
runWriteAction {
|
||||
facetModel.commit()
|
||||
}
|
||||
}
|
||||
return facet
|
||||
}
|
||||
|
||||
fun KotlinFacet.configureFacet(
|
||||
compilerVersion: String,
|
||||
coroutineSupport: LanguageFeature.State,
|
||||
platformKind: TargetPlatformKind<*>?, // if null, detect by module dependencies
|
||||
modelsProvider: IdeModifiableModelsProvider
|
||||
) {
|
||||
val module = module
|
||||
with(configuration.settings) {
|
||||
compilerArguments = null
|
||||
compilerSettings = null
|
||||
initializeIfNeeded(
|
||||
module,
|
||||
modelsProvider.getModifiableRootModel(module),
|
||||
platformKind,
|
||||
compilerVersion
|
||||
)
|
||||
val apiLevel = apiLevel
|
||||
val languageLevel = languageLevel
|
||||
if (languageLevel != null && apiLevel != null && apiLevel > languageLevel) {
|
||||
this.apiLevel = languageLevel
|
||||
}
|
||||
this.coroutineSupport = coroutineSupport
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinFacet.noVersionAutoAdvance() {
|
||||
configuration.settings.compilerArguments?.let {
|
||||
it.autoAdvanceLanguageVersion = false
|
||||
it.autoAdvanceApiVersion = false
|
||||
}
|
||||
}
|
||||
|
||||
// "Primary" fields are written to argument beans directly and thus not presented in the "additional arguments" string
|
||||
// Update these lists when facet/project settings UI changes
|
||||
val commonUIExposedFields = listOf(CommonCompilerArguments::languageVersion.name,
|
||||
CommonCompilerArguments::apiVersion.name,
|
||||
CommonCompilerArguments::suppressWarnings.name,
|
||||
CommonCompilerArguments::coroutinesState.name)
|
||||
private val commonUIHiddenFields = listOf(CommonCompilerArguments::pluginClasspaths.name,
|
||||
CommonCompilerArguments::pluginOptions.name)
|
||||
private val commonPrimaryFields = commonUIExposedFields + commonUIHiddenFields
|
||||
|
||||
private val jvmSpecificUIExposedFields = listOf(K2JVMCompilerArguments::jvmTarget.name,
|
||||
K2JVMCompilerArguments::destination.name,
|
||||
K2JVMCompilerArguments::classpath.name)
|
||||
val jvmUIExposedFields = commonUIExposedFields + jvmSpecificUIExposedFields
|
||||
private val jvmPrimaryFields = commonPrimaryFields + jvmSpecificUIExposedFields
|
||||
|
||||
private val jsSpecificUIExposedFields = listOf(K2JSCompilerArguments::sourceMap.name,
|
||||
K2JSCompilerArguments::sourceMapPrefix.name,
|
||||
K2JSCompilerArguments::sourceMapEmbedSources.name,
|
||||
K2JSCompilerArguments::outputPrefix.name,
|
||||
K2JSCompilerArguments::outputPostfix.name,
|
||||
K2JSCompilerArguments::moduleKind.name)
|
||||
val jsUIExposedFields = commonUIExposedFields + jsSpecificUIExposedFields
|
||||
private val jsPrimaryFields = commonPrimaryFields + jsSpecificUIExposedFields
|
||||
|
||||
private val metadataSpecificUIExposedFields = listOf(K2MetadataCompilerArguments::destination.name,
|
||||
K2MetadataCompilerArguments::classpath.name)
|
||||
val metadataUIExposedFields = commonUIExposedFields + metadataSpecificUIExposedFields
|
||||
private val metadataPrimaryFields = commonPrimaryFields + metadataSpecificUIExposedFields
|
||||
|
||||
private val CommonCompilerArguments.primaryFields: List<String>
|
||||
get() = when (this) {
|
||||
is K2JVMCompilerArguments -> jvmPrimaryFields
|
||||
is K2JSCompilerArguments -> jsPrimaryFields
|
||||
is K2MetadataCompilerArguments -> metadataPrimaryFields
|
||||
else -> commonPrimaryFields
|
||||
}
|
||||
|
||||
private val CommonCompilerArguments.ignoredFields: List<String>
|
||||
get() = when (this) {
|
||||
is K2JVMCompilerArguments -> listOf(K2JVMCompilerArguments::noJdk.name, K2JVMCompilerArguments::jdkHome.name)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
private fun Module.configureSdkIfPossible(compilerArguments: CommonCompilerArguments, modelsProvider: IdeModifiableModelsProvider) {
|
||||
val allSdks = ProjectJdkTable.getInstance().allJdks
|
||||
val sdk = if (compilerArguments is K2JVMCompilerArguments) {
|
||||
val jdkHome = compilerArguments.jdkHome ?: return
|
||||
allSdks.firstOrNull { it.sdkType is JavaSdk && FileUtil.comparePaths(it.homePath, jdkHome) == 0 } ?: return
|
||||
} else {
|
||||
allSdks.firstOrNull { it.sdkType is KotlinSdkType } ?: KotlinSdkType.INSTANCE.createSdkWithUniqueName(allSdks.toList())
|
||||
}
|
||||
|
||||
modelsProvider.getModifiableRootModel(this).sdk = sdk
|
||||
}
|
||||
|
||||
fun parseCompilerArgumentsToFacet(
|
||||
arguments: List<String>,
|
||||
defaultArguments: List<String>,
|
||||
kotlinFacet: KotlinFacet,
|
||||
modelsProvider: IdeModifiableModelsProvider?
|
||||
) {
|
||||
with(kotlinFacet.configuration.settings) {
|
||||
val compilerArguments = this.compilerArguments ?: return
|
||||
|
||||
val defaultCompilerArguments = compilerArguments::class.java.newInstance()
|
||||
parseCommandLineArguments(defaultArguments, defaultCompilerArguments)
|
||||
defaultCompilerArguments.convertPathsToSystemIndependent()
|
||||
|
||||
parseCommandLineArguments(arguments, compilerArguments)
|
||||
|
||||
compilerArguments.convertPathsToSystemIndependent()
|
||||
|
||||
// Retain only fields exposed (and not explicitly ignored) in facet configuration editor.
|
||||
// The rest is combined into string and stored in CompilerSettings.additionalArguments
|
||||
|
||||
if (modelsProvider != null)
|
||||
kotlinFacet.module.configureSdkIfPossible(compilerArguments, modelsProvider)
|
||||
|
||||
val primaryFields = compilerArguments.primaryFields
|
||||
val ignoredFields = compilerArguments.ignoredFields
|
||||
|
||||
fun exposeAsAdditionalArgument(property: KProperty1<CommonCompilerArguments, Any?>) =
|
||||
property.name !in primaryFields && property.get(compilerArguments) != property.get(defaultCompilerArguments)
|
||||
|
||||
val additionalArgumentsString = with(compilerArguments::class.java.newInstance()) {
|
||||
copyFieldsSatisfying(compilerArguments, this) { exposeAsAdditionalArgument(it) && it.name !in ignoredFields }
|
||||
ArgumentUtils.convertArgumentsToStringList(this).joinToString(separator = " ") {
|
||||
if (StringUtil.containsWhitespaces(it) || it.startsWith('"')) {
|
||||
StringUtil.wrapWithDoubleQuote(StringUtil.escapeQuotes(it))
|
||||
} else it
|
||||
}
|
||||
}
|
||||
compilerSettings?.additionalArguments =
|
||||
if (additionalArgumentsString.isNotEmpty()) additionalArgumentsString else CompilerSettings.DEFAULT_ADDITIONAL_ARGUMENTS
|
||||
|
||||
with(compilerArguments::class.java.newInstance()) {
|
||||
copyFieldsSatisfying(this, compilerArguments) { exposeAsAdditionalArgument(it) || it.name in ignoredFields }
|
||||
}
|
||||
|
||||
val languageLevel = languageLevel
|
||||
val apiLevel = apiLevel
|
||||
if (languageLevel != null && apiLevel != null && apiLevel > languageLevel) {
|
||||
this.apiLevel = languageLevel
|
||||
}
|
||||
|
||||
updateMergedArguments()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.idea.reporter
|
||||
|
||||
import com.intellij.diagnostic.ITNReporter
|
||||
import com.intellij.openapi.diagnostic.IdeaLoggingEvent
|
||||
import com.intellij.openapi.diagnostic.SubmittedReportInfo
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.util.Consumer
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUpdater
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
import org.jetbrains.kotlin.idea.PluginUpdateStatus
|
||||
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
|
||||
import java.awt.Component
|
||||
|
||||
/**
|
||||
* We need to wrap ITNReporter for force showing or errors from kotlin plugin even from released version of IDEA.
|
||||
*/
|
||||
class KotlinReportSubmitter : ITNReporter() {
|
||||
private var hasUpdate = false
|
||||
private var hasLatestVersion = false
|
||||
|
||||
override fun showErrorInRelease(event: IdeaLoggingEvent): Boolean {
|
||||
val notificationEnabled = "disabled" != System.getProperty("kotlin.fatal.error.notification", "enabled")
|
||||
return notificationEnabled && (!hasUpdate || KotlinInternalMode.enabled)
|
||||
}
|
||||
|
||||
override fun submit(events: Array<IdeaLoggingEvent>, additionalInfo: String?, parentComponent: Component?, consumer: Consumer<SubmittedReportInfo>): Boolean {
|
||||
if (hasUpdate) {
|
||||
if (KotlinInternalMode.enabled) {
|
||||
return super.submit(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if (hasLatestVersion) {
|
||||
return super.submit(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
|
||||
KotlinPluginUpdater.getInstance().runUpdateCheck { status ->
|
||||
if (status is PluginUpdateStatus.Update) {
|
||||
hasUpdate = true
|
||||
if (parentComponent != null) {
|
||||
|
||||
if (KotlinInternalMode.enabled) {
|
||||
super.submit(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
|
||||
val rc = Messages.showDialog(parentComponent,
|
||||
"You're running Kotlin plugin version ${KotlinPluginUtil.getPluginVersion()}, " +
|
||||
"while the latest version is ${status.pluginDescriptor.version}",
|
||||
"Update Kotlin Plugin",
|
||||
arrayOf("Update", "Ignore"),
|
||||
0, Messages.getInformationIcon())
|
||||
if (rc == 0) {
|
||||
KotlinPluginUpdater.getInstance().installPluginUpdate(status)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
hasLatestVersion = true
|
||||
super.submit(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user