Kotlin Facet: Initial implementation
This commit is contained in:
@@ -207,6 +207,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
|
||||
- [`KT-12398`](https://youtrack.jetbrains.com/issue/KT-12398) Call Hierarchy: Show Kotlin usages of Java methods
|
||||
- [`KT-13976`](https://youtrack.jetbrains.com/issue/KT-13976) Search Everywhere: Render function parameter types
|
||||
- [`KT-13977`](https://youtrack.jetbrains.com/issue/KT-13977) Search Everywhere: Render extension type in prefix position
|
||||
- Implement Kotlin facet
|
||||
|
||||
#### Intention actions, inspections and quickfixes
|
||||
|
||||
|
||||
@@ -731,6 +731,8 @@
|
||||
|
||||
<usageToPsiElementProvider implementation="org.jetbrains.kotlin.idea.codeInsight.KotlinUsageToPsiElementProvider"/>
|
||||
|
||||
<facetType implementation="org.jetbrains.kotlin.idea.facet.KotlinFacetType"/>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.FoldInitializerAndIfToElvisIntention</className>
|
||||
<category>Kotlin</category>
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.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 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 getLibraryDescription: () -> CustomLibraryDescription
|
||||
) : FrameworkLibraryValidator() {
|
||||
override fun check(): ValidationResult {
|
||||
val libraryDescription = getLibraryDescription()
|
||||
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
|
||||
}
|
||||
if (found) return ValidationResult.OK
|
||||
|
||||
return ValidationResult(
|
||||
IdeBundle.message("label.missed.libraries.text", libraryCategoryName),
|
||||
LibrariesQuickFix(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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.facet.Facet
|
||||
import com.intellij.facet.FacetManager.getInstance
|
||||
import com.intellij.openapi.module.Module
|
||||
|
||||
class KotlinFacet(
|
||||
module: Module,
|
||||
name: String,
|
||||
configuration: KotlinFacetConfiguration
|
||||
) : Facet<KotlinFacetConfiguration>(KotlinFacetType.INSTANCE, module, name, configuration, null) {
|
||||
companion object {
|
||||
fun get(module: Module): KotlinFacet? {
|
||||
if (module.isDisposed) return null
|
||||
return getInstance(module).getFacetByType<KotlinFacet>(KotlinFacetType.TYPE_ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.facet.FacetConfiguration
|
||||
import com.intellij.facet.ui.FacetEditorContext
|
||||
import com.intellij.facet.ui.FacetEditorTab
|
||||
import com.intellij.facet.ui.FacetValidatorsManager
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.kotlin.idea.util.DescriptionAware
|
||||
|
||||
class KotlinFacetConfiguration : FacetConfiguration, PersistentStateComponent<KotlinFacetConfiguration.Settings> {
|
||||
enum class LanguageLevel(override val description: String) : DescriptionAware {
|
||||
KOTLIN_1_0("1.0"),
|
||||
KOTLIN_1_1("1.1")
|
||||
}
|
||||
|
||||
enum class TargetPlatform(override val description: String) : DescriptionAware {
|
||||
JVM_1_6("JVM 1.6"),
|
||||
JVM_1_8("JVM 1.8"),
|
||||
JS("JavaScript")
|
||||
}
|
||||
|
||||
class Settings {
|
||||
var languageLevel: LanguageLevel? = null
|
||||
var targetPlatformKind: TargetPlatform? = null
|
||||
}
|
||||
|
||||
private var settings = Settings()
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun readExternal(element: Element?) {
|
||||
|
||||
}
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun writeExternal(element: Element?) {
|
||||
|
||||
}
|
||||
|
||||
override fun loadState(state: Settings) {
|
||||
this.settings = settings
|
||||
}
|
||||
|
||||
override fun getState() = settings
|
||||
|
||||
override fun createEditorTabs(
|
||||
editorContext: FacetEditorContext,
|
||||
validatorsManager: FacetValidatorsManager
|
||||
): Array<FacetEditorTab> = arrayOf(KotlinFacetEditorTab(this, editorContext, validatorsManager))
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.facet.impl.ui.libraries.DelegatingLibrariesValidatorContext
|
||||
import com.intellij.facet.ui.FacetEditorContext
|
||||
import com.intellij.facet.ui.FacetEditorTab
|
||||
import com.intellij.facet.ui.FacetValidatorsManager
|
||||
import com.intellij.facet.ui.libraries.FrameworkLibraryValidator
|
||||
import com.intellij.framework.library.LibraryVersionProperties
|
||||
import com.intellij.openapi.projectRoots.JavaSdk
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider
|
||||
import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription
|
||||
import org.jetbrains.kotlin.idea.framework.getLibraryProperties
|
||||
import org.jetbrains.kotlin.idea.util.DescriptionAware
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import javax.swing.*
|
||||
|
||||
class KotlinFacetEditorTab(
|
||||
private val configuration: KotlinFacetConfiguration,
|
||||
private val editorContext: FacetEditorContext,
|
||||
validatorsManager: FacetValidatorsManager
|
||||
) : FacetEditorTab() {
|
||||
class DescriptionListCellRenderer : DefaultListCellRenderer() {
|
||||
override fun getListCellRendererComponent(list: JList<*>?, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
|
||||
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus).apply {
|
||||
text = (value as? DescriptionAware)?.description ?: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val KotlinFacetConfiguration.TargetPlatform.libraryDescription: CustomLibraryDescription
|
||||
get() {
|
||||
return when (this) {
|
||||
KotlinFacetConfiguration.TargetPlatform.JVM_1_6, KotlinFacetConfiguration.TargetPlatform.JVM_1_8 ->
|
||||
JavaRuntimeLibraryDescription(editorContext.project)
|
||||
KotlinFacetConfiguration.TargetPlatform.JS ->
|
||||
JSLibraryStdDescription(editorContext.project)
|
||||
}
|
||||
}
|
||||
|
||||
private val languageVersionComboBox =
|
||||
JComboBox<KotlinFacetConfiguration.LanguageLevel>(KotlinFacetConfiguration.LanguageLevel.values()).apply {
|
||||
setRenderer(DescriptionListCellRenderer())
|
||||
}
|
||||
|
||||
private val targetPlatformComboBox =
|
||||
JComboBox<KotlinFacetConfiguration.TargetPlatform>(KotlinFacetConfiguration.TargetPlatform.values()).apply {
|
||||
setRenderer(DescriptionListCellRenderer())
|
||||
}
|
||||
|
||||
private val validator: FrameworkLibraryValidator
|
||||
|
||||
private fun getRuntimeLibraryVersions(
|
||||
libToProperties: Library.() -> LibraryVersionProperties?
|
||||
): List<String> {
|
||||
return editorContext
|
||||
.rootModel
|
||||
.orderEntries
|
||||
.asSequence()
|
||||
.filterIsInstance<LibraryOrderEntry>()
|
||||
.mapNotNull { it.library?.libToProperties()?.versionString }
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun getDefaultTargetPlatform(): KotlinFacetConfiguration.TargetPlatform {
|
||||
getRuntimeLibraryVersions { getLibraryProperties(JSLibraryStdPresentationProvider.getInstance(), this) }.firstOrNull()?.let { javaLib ->
|
||||
return KotlinFacetConfiguration.TargetPlatform.JS
|
||||
}
|
||||
|
||||
val sdk = editorContext.rootModel.sdk
|
||||
val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk!!)
|
||||
return when {
|
||||
sdkVersion != null && sdkVersion <= JavaSdkVersion.JDK_1_6 -> KotlinFacetConfiguration.TargetPlatform.JVM_1_6
|
||||
else -> KotlinFacetConfiguration.TargetPlatform.JVM_1_8
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultLanguageLevel(): KotlinFacetConfiguration.LanguageLevel {
|
||||
val libVersion = bundledRuntimeVersion()
|
||||
return when {
|
||||
libVersion.startsWith("1.0") -> KotlinFacetConfiguration.LanguageLevel.KOTLIN_1_0
|
||||
else -> KotlinFacetConfiguration.LanguageLevel.KOTLIN_1_1
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
validator = FrameworkLibraryValidatorWithDynamicDescription(
|
||||
DelegatingLibrariesValidatorContext(editorContext),
|
||||
validatorsManager,
|
||||
"kotlin"
|
||||
) { (targetPlatformComboBox.selectedItem as KotlinFacetConfiguration.TargetPlatform).libraryDescription }
|
||||
validatorsManager.registerValidator(validator)
|
||||
|
||||
targetPlatformComboBox.addActionListener {
|
||||
validatorsManager.validate()
|
||||
}
|
||||
|
||||
with(configuration.state) {
|
||||
if (targetPlatformKind == null) {
|
||||
targetPlatformKind = getDefaultTargetPlatform()
|
||||
}
|
||||
|
||||
if (languageLevel == null) {
|
||||
languageLevel = getDefaultLanguageLevel()
|
||||
}
|
||||
}
|
||||
|
||||
reset()
|
||||
}
|
||||
|
||||
override fun isModified(): Boolean {
|
||||
return languageVersionComboBox.selectedItem != configuration.state.languageLevel
|
||||
|| targetPlatformComboBox.selectedItem != configuration.state.targetPlatformKind
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
languageVersionComboBox.selectedItem = configuration.state.languageLevel
|
||||
targetPlatformComboBox.selectedItem = configuration.state.targetPlatformKind
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
configuration.state.languageLevel = languageVersionComboBox.selectedItem as KotlinFacetConfiguration.LanguageLevel?
|
||||
configuration.state.targetPlatformKind = targetPlatformComboBox.selectedItem as KotlinFacetConfiguration.TargetPlatform?
|
||||
}
|
||||
|
||||
override fun getDisplayName() = "Kotlin"
|
||||
|
||||
override fun createComponent(): JComponent {
|
||||
val mainPanel = JPanel(BorderLayout())
|
||||
val contentPanel = FormBuilder
|
||||
.createFormBuilder()
|
||||
.addLabeledComponent("&Language version: ", languageVersionComboBox)
|
||||
.addLabeledComponent("&Target platform: ", targetPlatformComboBox)
|
||||
.panel
|
||||
mainPanel.add(contentPanel, BorderLayout.NORTH)
|
||||
return mainPanel
|
||||
}
|
||||
|
||||
override fun disposeUIResources() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.facet.Facet
|
||||
import com.intellij.facet.FacetType
|
||||
import com.intellij.facet.FacetTypeId
|
||||
import com.intellij.facet.FacetTypeRegistry
|
||||
import com.intellij.openapi.module.JavaModuleType
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import javax.swing.Icon
|
||||
|
||||
class KotlinFacetType : FacetType<KotlinFacet, KotlinFacetConfiguration>(TYPE_ID, ID, NAME) {
|
||||
companion object {
|
||||
val TYPE_ID = FacetTypeId<KotlinFacet>("kotlin-language")
|
||||
val ID = "kotlin-language"
|
||||
val NAME = "Kotlin"
|
||||
|
||||
val INSTANCE: KotlinFacetType
|
||||
get() = FacetTypeRegistry.getInstance().findFacetType(TYPE_ID) as KotlinFacetType
|
||||
}
|
||||
|
||||
override fun isSuitableModuleType(moduleType: ModuleType<*>) = moduleType is JavaModuleType
|
||||
|
||||
override fun getIcon(): Icon = KotlinIcons.SMALL_LOGO
|
||||
|
||||
override fun createDefaultConfiguration() = KotlinFacetConfiguration()
|
||||
|
||||
override fun createFacet(
|
||||
module: Module,
|
||||
name: String,
|
||||
configuration: KotlinFacetConfiguration,
|
||||
underlyingFacet: Facet<*>?
|
||||
) = KotlinFacet(module, name, configuration)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.util
|
||||
|
||||
interface DescriptionAware {
|
||||
val description: String
|
||||
}
|
||||
Reference in New Issue
Block a user