summaryrefslogtreecommitdiff
path: root/plugins/kotlin/jvm/src/org/jetbrains/kotlin/idea/facet/FrameworkLibraryValidatorWithDynamicDescription.kt
blob: 864597f01087182f865f6e8e2cffce8bc6334470 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package org.jetbrains.kotlin.idea.facet

import com.intellij.facet.impl.ui.libraries.LibrariesValidatorContext
import com.intellij.facet.ui.FacetConfigurationQuickFix
import com.intellij.facet.ui.FacetValidatorsManager
import com.intellij.facet.ui.ValidationResult
import com.intellij.facet.ui.libraries.FrameworkLibraryValidator
import com.intellij.ide.IdeBundle
import com.intellij.openapi.roots.ui.configuration.libraries.AddCustomLibraryDialog
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager
import org.jetbrains.kotlin.idea.KotlinJvmBundle
import org.jetbrains.kotlin.idea.platform.tooling
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.impl.isCommon
import javax.swing.JComponent

// Based on com.intellij.facet.impl.ui.libraries.FrameworkLibraryValidatorImpl
class FrameworkLibraryValidatorWithDynamicDescription(
    private val context: LibrariesValidatorContext,
    private val validatorsManager: FacetValidatorsManager,
    private val libraryCategoryName: String,
    private val getPlatform: () -> TargetPlatform?
) : FrameworkLibraryValidator() {
    private val IdePlatformKind.libraryDescription: CustomLibraryDescription?
        get() = this.tooling.getLibraryDescription(context.module.project)

    private fun checkLibraryIsConfigured(platform: IdePlatformKind): Boolean {
        // TODO: propose to configure kotlin-stdlib-common once it's available
        if (platform.isCommon) return true

        if (KotlinVersionInfoProvider.EP_NAME.extensions.any {
                it.getLibraryVersions(context.module, platform, context.rootModel).isNotEmpty()
            }
        ) return true

        val libraryDescription = platform.libraryDescription ?: return true
        val libraryKinds = libraryDescription.suitableLibraryKinds
        var found = false
        val presentationManager = LibraryPresentationManager.getInstance()
        context.rootModel
            .orderEntries()
            .using(context.modulesProvider)
            .recursively()
            .librariesOnly()
            .forEachLibrary { library ->
                if (presentationManager.isLibraryOfKind(library, context.librariesContainer, libraryKinds)) {
                    found = true
                }
                !found
            }
        return found
    }

    override fun check(): ValidationResult {
        val targetPlatform = getPlatform() ?: return ValidationResult(KotlinJvmBundle.message("no.target.platforms.selected"))

        if (checkLibraryIsConfigured(targetPlatform.idePlatformKind)) {
            val conflictingPlatforms = IdePlatformKind.ALL_KINDS
                .filter {
                    !it.isCommon && it.name != targetPlatform.idePlatformKind.name
                            && it.libraryDescription != null && checkLibraryIsConfigured(it)
                }

            if (conflictingPlatforms.isNotEmpty()) {
                val platformText = conflictingPlatforms.mapTo(LinkedHashSet()) { it.name }.joinToString()
                return ValidationResult(
                    KotlinJvmBundle.message(
                        "libraries.for.the.following.platform.are.also.present.in.the.module.dependencies.0",
                        platformText
                    )
                )
            }

            return ValidationResult.OK
        }

        return ValidationResult(
            KotlinJvmBundle.message("label.missed.libraries.text", libraryCategoryName),
            LibrariesQuickFix(targetPlatform.idePlatformKind.libraryDescription!!)
        )
    }

    private inner class LibrariesQuickFix(
        private val myDescription: CustomLibraryDescription
    ) : FacetConfigurationQuickFix(IdeBundle.message("button.fix")) {
        override fun run(place: JComponent) {
            val dialog = AddCustomLibraryDialog.createDialog(
                myDescription, context.librariesContainer,
                context.module, context.modifiableRootModel,
                null
            )
            dialog.show()
            validatorsManager.validate()
        }
    }
}