181: Restore broken android lint quickfixes
This commit is contained in:
committed by
Nikolay Krasko
parent
207247347e
commit
4cf804f30f
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.android.SdkConstants
|
||||||
|
import com.android.tools.lint.checks.ApiDetector.REQUIRES_API_ANNOTATION
|
||||||
|
import com.intellij.codeInsight.FileModificationService
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFix
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidQuickfixContexts
|
||||||
|
import org.jetbrains.android.util.AndroidBundle
|
||||||
|
import org.jetbrains.kotlin.android.hasBackingField
|
||||||
|
import org.jetbrains.kotlin.idea.util.addAnnotation
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
|
|
||||||
|
class AddTargetApiQuickFix(
|
||||||
|
val api: Int,
|
||||||
|
val useRequiresApi: Boolean
|
||||||
|
) : AndroidLintQuickFix {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val FQNAME_TARGET_API = FqName(SdkConstants.FQCN_TARGET_API)
|
||||||
|
val FQNAME_REQUIRES_API = FqName(REQUIRES_API_ANNOTATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean =
|
||||||
|
getAnnotationContainer(startElement, useRequiresApi) != null
|
||||||
|
|
||||||
|
override fun getName(): String = getAnnotationValue(false).let {
|
||||||
|
if (useRequiresApi) {
|
||||||
|
// Not Available in Android plugin 2.0
|
||||||
|
// AndroidBundle.message("android.lint.fix.add.requires.api", it)
|
||||||
|
"Add @RequiresApi($it) Annotation"
|
||||||
|
} else {
|
||||||
|
AndroidBundle.message("android.lint.fix.add.target.api", it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
|
||||||
|
val annotationContainer = getAnnotationContainer(startElement, useRequiresApi) ?: return
|
||||||
|
if (!FileModificationService.getInstance().preparePsiElementForWrite(annotationContainer)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotationContainer is KtModifierListOwner) {
|
||||||
|
annotationContainer.addAnnotation(
|
||||||
|
if (useRequiresApi) FQNAME_REQUIRES_API else FQNAME_TARGET_API,
|
||||||
|
getAnnotationValue(true),
|
||||||
|
whiteSpaceText = if (annotationContainer.isNewLineNeededForAnnotation()) "\n" else " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtElement.isNewLineNeededForAnnotation() = !(this is KtParameter || this is KtTypeParameter || this is KtPropertyAccessor)
|
||||||
|
|
||||||
|
private fun getAnnotationValue(fullyQualified: Boolean) = getVersionField(api, fullyQualified)
|
||||||
|
|
||||||
|
private fun getAnnotationContainer(element: PsiElement, useRequiresApi: Boolean): PsiElement? {
|
||||||
|
return PsiTreeUtil.findFirstParent(element) {
|
||||||
|
if (useRequiresApi)
|
||||||
|
it.isRequiresApiAnnotationValidTarget()
|
||||||
|
else
|
||||||
|
it.isTargetApiAnnotationValidTarget()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.isRequiresApiAnnotationValidTarget(): Boolean {
|
||||||
|
return this is KtClassOrObject ||
|
||||||
|
(this is KtFunction && this !is KtFunctionLiteral) ||
|
||||||
|
(this is KtProperty && !isLocal && hasBackingField()) ||
|
||||||
|
this is KtPropertyAccessor
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.isTargetApiAnnotationValidTarget(): Boolean {
|
||||||
|
return this is KtClassOrObject ||
|
||||||
|
(this is KtFunction && this !is KtFunctionLiteral) ||
|
||||||
|
this is KtPropertyAccessor
|
||||||
|
}
|
||||||
|
}
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.FileModificationService
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFix
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidQuickfixContexts
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.surroundWith.statement.KotlinIfSurrounder
|
||||||
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
|
|
||||||
|
class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix {
|
||||||
|
|
||||||
|
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
|
||||||
|
val targetExpression = getTargetExpression(startElement)
|
||||||
|
val project = targetExpression?.project ?: return
|
||||||
|
val editor = targetExpression.findExistingEditor() ?: return
|
||||||
|
|
||||||
|
val file = targetExpression.containingFile
|
||||||
|
val documentManager = PsiDocumentManager.getInstance(project)
|
||||||
|
val document = documentManager.getDocument(file) ?: return
|
||||||
|
|
||||||
|
if (!FileModificationService.getInstance().prepareFileForWrite(file)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val surrounder = getSurrounder(targetExpression, "\"VERSION.SDK_INT < ${getVersionField(api, false)}\"")
|
||||||
|
val conditionRange = surrounder.surroundElements(project, editor, arrayOf(targetExpression)) ?: return
|
||||||
|
val conditionText = "android.os.Build.VERSION.SDK_INT >= ${getVersionField(api, true)}"
|
||||||
|
document.replaceString(conditionRange.startOffset, conditionRange.endOffset, conditionText)
|
||||||
|
documentManager.commitDocument(document)
|
||||||
|
|
||||||
|
ShortenReferences.DEFAULT.process(documentManager.getPsiFile(document) as KtFile,
|
||||||
|
conditionRange.startOffset,
|
||||||
|
conditionRange.startOffset + conditionText.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean =
|
||||||
|
getTargetExpression(startElement) != null
|
||||||
|
|
||||||
|
override fun getName(): String = "Surround with if (VERSION.SDK_INT >= VERSION_CODES.${getVersionField(api, false)}) { ... }"
|
||||||
|
|
||||||
|
private fun getTargetExpression(element: PsiElement): KtElement? {
|
||||||
|
var current = PsiTreeUtil.getParentOfType(element, KtExpression::class.java)
|
||||||
|
while (current != null) {
|
||||||
|
if (current.parent is KtBlockExpression ||
|
||||||
|
current.parent is KtContainerNode ||
|
||||||
|
current.parent is KtWhenEntry ||
|
||||||
|
current.parent is KtFunction ||
|
||||||
|
current.parent is KtPropertyAccessor ||
|
||||||
|
current.parent is KtProperty ||
|
||||||
|
current.parent is KtReturnExpression ||
|
||||||
|
current.parent is KtDestructuringDeclaration) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
current = PsiTreeUtil.getParentOfType(current, KtExpression::class.java, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSurrounder(element: KtElement, todoText: String?): KotlinIfSurrounder {
|
||||||
|
val used = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.USED_AS_EXPRESSION, element] ?: false
|
||||||
|
return if (used) {
|
||||||
|
object : KotlinIfSurrounder() {
|
||||||
|
override fun getCodeTemplate(): String = "if (a) { \n} else {\nTODO(${todoText ?: ""})\n}"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
KotlinIfSurrounder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.android.sdklib.SdkVersionInfo.*
|
||||||
|
|
||||||
|
|
||||||
|
fun getVersionField(api: Int, fullyQualified: Boolean): String = getBuildCode(api)?.let {
|
||||||
|
if (fullyQualified) "android.os.Build.VERSION_CODES.$it" else it
|
||||||
|
} ?: api.toString()
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.android.SdkConstants.SUPPORT_ANNOTATIONS_PREFIX
|
||||||
|
import com.android.tools.lint.checks.ApiDetector
|
||||||
|
import com.android.tools.lint.checks.CommentDetector
|
||||||
|
import com.android.tools.lint.checks.ParcelDetector
|
||||||
|
import com.android.tools.lint.detector.api.Issue
|
||||||
|
import com.intellij.psi.JavaPsiFacade
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFix
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFixProvider
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
|
class KotlinAndroidQuickFixProvider : AndroidLintQuickFixProvider {
|
||||||
|
override fun getQuickFixes(
|
||||||
|
issue: Issue,
|
||||||
|
startElement: PsiElement,
|
||||||
|
endElement: PsiElement,
|
||||||
|
message: String,
|
||||||
|
data: Any?
|
||||||
|
): Array<AndroidLintQuickFix> {
|
||||||
|
val fixes: Array<AndroidLintQuickFix> = when (issue) {
|
||||||
|
ApiDetector.UNSUPPORTED, ApiDetector.INLINED -> getApiQuickFixes(issue, startElement, message)
|
||||||
|
ParcelDetector.ISSUE -> arrayOf(ParcelableQuickFix())
|
||||||
|
else -> emptyArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (issue != CommentDetector.STOP_SHIP) {
|
||||||
|
return fixes + SuppressLintQuickFix(issue.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fixes
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getApiQuickFixes(issue: Issue, element: PsiElement, message: String): Array<AndroidLintQuickFix> {
|
||||||
|
val api = getRequiredVersion(message)
|
||||||
|
if (api == -1) {
|
||||||
|
return AndroidLintQuickFix.EMPTY_ARRAY
|
||||||
|
}
|
||||||
|
|
||||||
|
val project = element.project
|
||||||
|
if (JavaPsiFacade.getInstance(project).findClass(REQUIRES_API_ANNOTATION, GlobalSearchScope.allScope(project)) != null) {
|
||||||
|
return arrayOf(AddTargetApiQuickFix(api, true), AddTargetApiQuickFix(api, false), AddTargetVersionCheckQuickFix(api))
|
||||||
|
}
|
||||||
|
|
||||||
|
return arrayOf(AddTargetApiQuickFix(api, false), AddTargetVersionCheckQuickFix(api))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRequiredVersion(errorMessage: String): Int {
|
||||||
|
val pattern = Pattern.compile("\\s(\\d+)\\s")
|
||||||
|
val matcher = pattern.matcher(errorMessage)
|
||||||
|
if (matcher.find()) {
|
||||||
|
return Integer.parseInt(matcher.group(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val REQUIRES_API_ANNOTATION = SUPPORT_ANNOTATIONS_PREFIX + "RequiresApi"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFix
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidQuickfixContexts
|
||||||
|
import org.jetbrains.android.util.AndroidBundle
|
||||||
|
import org.jetbrains.kotlin.android.canAddParcelable
|
||||||
|
import org.jetbrains.kotlin.android.implementParcelable
|
||||||
|
import org.jetbrains.kotlin.android.isParcelize
|
||||||
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
|
|
||||||
|
|
||||||
|
class ParcelableQuickFix : AndroidLintQuickFix {
|
||||||
|
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
|
||||||
|
startElement.getTargetClass()?.implementParcelable()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean {
|
||||||
|
val targetClass = startElement.getTargetClass() ?: return false
|
||||||
|
return targetClass.canAddParcelable() && !targetClass.isParcelize()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = AndroidBundle.message("implement.parcelable.intention.text")
|
||||||
|
|
||||||
|
private fun PsiElement.getTargetClass(): KtClass? = PsiTreeUtil.getParentOfType(this, KtClass::class.java, false)
|
||||||
|
}
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.quickfix
|
||||||
|
|
||||||
|
import com.android.SdkConstants
|
||||||
|
import com.intellij.codeInsight.FileModificationService
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidLintQuickFix
|
||||||
|
import org.jetbrains.android.inspections.lint.AndroidQuickfixContexts
|
||||||
|
import org.jetbrains.android.util.AndroidBundle
|
||||||
|
import org.jetbrains.kotlin.android.hasBackingField
|
||||||
|
import org.jetbrains.kotlin.idea.util.addAnnotation
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
|
|
||||||
|
class SuppressLintQuickFix(id: String) : AndroidLintQuickFix {
|
||||||
|
private val lintId = getLintId(id)
|
||||||
|
|
||||||
|
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
|
||||||
|
val annotationContainer = PsiTreeUtil.findFirstParent(startElement, true) { it.isSuppressLintTarget() } ?: return
|
||||||
|
if (!FileModificationService.getInstance().preparePsiElementForWrite(annotationContainer)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val argument = "\"$lintId\""
|
||||||
|
|
||||||
|
when (annotationContainer) {
|
||||||
|
is KtModifierListOwner -> {
|
||||||
|
annotationContainer.addAnnotation(
|
||||||
|
FQNAME_SUPPRESS_LINT,
|
||||||
|
argument,
|
||||||
|
whiteSpaceText = if (annotationContainer.isNewLineNeededForAnnotation()) "\n" else " ",
|
||||||
|
addToExistingAnnotation = { entry -> addArgumentToAnnotation(entry, argument) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = AndroidBundle.message(SUPPRESS_LINT_MESSAGE, lintId)
|
||||||
|
|
||||||
|
override fun isApplicable(
|
||||||
|
startElement: PsiElement,
|
||||||
|
endElement: PsiElement,
|
||||||
|
contextType: AndroidQuickfixContexts.ContextType
|
||||||
|
): Boolean = true
|
||||||
|
|
||||||
|
private fun addArgumentToAnnotation(entry: KtAnnotationEntry, argument: String): Boolean {
|
||||||
|
// add new arguments to an existing entry
|
||||||
|
val args = entry.valueArgumentList
|
||||||
|
val psiFactory = KtPsiFactory(entry)
|
||||||
|
val newArgList = psiFactory.createCallArguments("($argument)")
|
||||||
|
when {
|
||||||
|
args == null -> // new argument list
|
||||||
|
entry.addAfter(newArgList, entry.lastChild)
|
||||||
|
args.arguments.isEmpty() -> // replace '()' with a new argument list
|
||||||
|
args.replace(newArgList)
|
||||||
|
args.arguments.none { it.textMatches(argument) } ->
|
||||||
|
args.addArgument(newArgList.arguments[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLintId(intentionId: String) =
|
||||||
|
if (intentionId.startsWith(INTENTION_NAME_PREFIX)) intentionId.substring(INTENTION_NAME_PREFIX.length) else intentionId
|
||||||
|
|
||||||
|
private fun KtElement.isNewLineNeededForAnnotation(): Boolean {
|
||||||
|
return !(this is KtParameter ||
|
||||||
|
this is KtTypeParameter ||
|
||||||
|
this is KtPropertyAccessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.isSuppressLintTarget(): Boolean {
|
||||||
|
return this is KtDeclaration &&
|
||||||
|
(this as? KtProperty)?.hasBackingField() ?: true &&
|
||||||
|
this !is KtFunctionLiteral &&
|
||||||
|
this !is KtDestructuringDeclaration
|
||||||
|
}
|
||||||
|
private companion object {
|
||||||
|
val INTENTION_NAME_PREFIX = "AndroidLint"
|
||||||
|
val SUPPRESS_LINT_MESSAGE = "android.lint.fix.suppress.lint.api.annotation"
|
||||||
|
val FQNAME_SUPPRESS_LINT = FqName(SdkConstants.FQCN_SUPPRESS_LINT)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
|
<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="org.jetbrains.android">
|
||||||
|
<androidLintQuickFixProvider implementation="org.jetbrains.kotlin.android.quickfix.KotlinAndroidQuickFixProvider" />
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="org.jetbrains.kotlin.android.model">
|
||||||
|
<androidModuleInfoProvider implementation="org.jetbrains.kotlin.android.model.impl.AndroidModuleInfoProviderImpl"/>
|
||||||
|
</extensions>
|
||||||
|
</idea-plugin>
|
||||||
Reference in New Issue
Block a user