From 992268bccd097b44a2b483e555e0ec637d50841e Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov <654232+AlexeyTsvetkov@users.noreply.github.com> Date: Fri, 16 Jul 2021 17:23:52 +0300 Subject: [PATCH] Suppress naming style inspection for composable functions (#889) This change suppresses a diagnostic, which complaints, when a function starts with an upper case letter --- .../desktop/ide/preview/locationUtils.kt | 21 ++++++++++ .../compose/inspections/ComposeSuppressor.kt | 40 +++++++++++++++++++ .../src/main/resources/META-INF/plugin.xml | 2 + 3 files changed, 63 insertions(+) create mode 100644 idea-plugin/src/main/kotlin/org/jetbrains/compose/inspections/ComposeSuppressor.kt diff --git a/idea-plugin/src/main/kotlin/org/jetbrains/compose/desktop/ide/preview/locationUtils.kt b/idea-plugin/src/main/kotlin/org/jetbrains/compose/desktop/ide/preview/locationUtils.kt index c2f40c676f..31d42c52ec 100644 --- a/idea-plugin/src/main/kotlin/org/jetbrains/compose/desktop/ide/preview/locationUtils.kt +++ b/idea-plugin/src/main/kotlin/org/jetbrains/compose/desktop/ide/preview/locationUtils.kt @@ -16,6 +16,10 @@ package org.jetbrains.compose.desktop.ide.preview +import com.intellij.openapi.roots.ProjectRootModificationTracker +import com.intellij.psi.PsiElement +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.parentOfType import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -28,6 +32,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode internal const val DESKTOP_PREVIEW_ANNOTATION_FQN = "androidx.compose.desktop.ui.tooling.preview.Preview" +internal const val COMPOSABLE_FQ_NAME = "androidx.compose.runtime.Composable" /** * Utils based on functions from AOSP, taken from @@ -50,6 +55,7 @@ internal fun KtNamedFunction.isValidComposePreview() = */ internal fun KtNamedFunction.isValidPreviewLocation(): Boolean { if (valueParameters.size > 0) return false + if (receiverTypeReference != null) return false if (isTopLevel) return true @@ -111,4 +117,19 @@ private fun KtAnnotationEntry.getQualifiedName(): String? = internal fun KtNamedFunction.composePreviewFunctionFqn() = "${getClassName()}.${name}" +// based on AndroidComposePsiUtils.kt from AOSP +internal fun PsiElement.isComposableFunction(): Boolean { + if (this !is KtNamedFunction) return false + return CachedValuesManager.getCachedValue(this) { + val hasComposableAnnotation = annotationEntries.any { it.fqNameMatches(COMPOSABLE_FQ_NAME) } + val containingKtFile = this.containingKtFile + + CachedValueProvider.Result.create( + // TODO: see if we can handle alias imports without ruining performance. + hasComposableAnnotation, + containingKtFile, + ProjectRootModificationTracker.getInstance(project) + ) + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/org/jetbrains/compose/inspections/ComposeSuppressor.kt b/idea-plugin/src/main/kotlin/org/jetbrains/compose/inspections/ComposeSuppressor.kt new file mode 100644 index 0000000000..13fef5f0f7 --- /dev/null +++ b/idea-plugin/src/main/kotlin/org/jetbrains/compose/inspections/ComposeSuppressor.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * 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.compose.inspections + +import com.intellij.codeInspection.InspectionSuppressor +import com.intellij.codeInspection.SuppressQuickFix +import com.intellij.psi.PsiElement +import org.jetbrains.compose.desktop.ide.preview.isComposableFunction +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.lexer.KtTokens + +/** + * Suppress inspection that require composable function names to start with a lower case letter. + */ +class ComposeSuppressor : InspectionSuppressor { + override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean { + return toolId == "FunctionName" && + element.language == KotlinLanguage.INSTANCE && + element.node.elementType == KtTokens.IDENTIFIER && + element.parent.isComposableFunction() + } + + override fun getSuppressActions(element: PsiElement?, toolId: String): Array { + return SuppressQuickFix.EMPTY_ARRAY + } +} + diff --git a/idea-plugin/src/main/resources/META-INF/plugin.xml b/idea-plugin/src/main/resources/META-INF/plugin.xml index 44f5323ab3..a48550bd36 100644 --- a/idea-plugin/src/main/resources/META-INF/plugin.xml +++ b/idea-plugin/src/main/resources/META-INF/plugin.xml @@ -36,5 +36,7 @@ factoryClass="org.jetbrains.compose.desktop.ide.preview.PreviewToolWindow" id="Desktop Preview" doNotActivateOnStart="true" anchor="right" /> + +