Change deprecation rules for annotations in brackets

Also adjust quickfix for deprecated syntax
This commit is contained in:
Denis Zharkov
2015-05-15 13:47:14 +03:00
parent e4f54b5d2e
commit 89337ff51e
12 changed files with 45 additions and 27 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub; import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
@@ -40,13 +41,15 @@ public class JetAnnotation extends JetElementImplStub<KotlinPlaceHolderStub<JetA
} }
public boolean isDeprecated() { public boolean isDeprecated() {
PsiElement parent = getParentByStub(); if (getStub() != null) return false;
if (parent instanceof JetFileAnnotationList) return false; return findChildByType(JetTokens.AT) == null;
if (!(parent instanceof JetModifierList)) return true;
return !(((JetModifierList) parent).getOwner() instanceof JetPrimaryConstructor);
} }
public List<JetAnnotationEntry> getEntries() { public List<JetAnnotationEntry> getEntries() {
return getStubOrPsiChildrenAsList(JetStubElementTypes.ANNOTATION_ENTRY); return getStubOrPsiChildrenAsList(JetStubElementTypes.ANNOTATION_ENTRY);
} }
public boolean hasFileKeyword() {
return findChildByType(JetTokens.FILE_KEYWORD) != null;
}
} }
@@ -53,6 +53,7 @@ public class DeclarationResolver {
public fun resolveAnnotationsOnFiles(c: TopDownAnalysisContext, scopeProvider: FileScopeProvider) { public fun resolveAnnotationsOnFiles(c: TopDownAnalysisContext, scopeProvider: FileScopeProvider) {
val filesToScope = c.getFiles().keysToMap { scopeProvider.getFileScope(it) } val filesToScope = c.getFiles().keysToMap { scopeProvider.getFileScope(it) }
for ((file, fileScope) in filesToScope) { for ((file, fileScope) in filesToScope) {
AnnotationResolver.reportDeprecatedAnnotationSyntax(file.getAnnotations(), _trace)
_annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getAnnotationEntries(), _trace) _annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getAnnotationEntries(), _trace)
_annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getDanglingAnnotations(), _trace) _annotationResolver.resolveAnnotationsWithArguments(fileScope, file.getDanglingAnnotations(), _trace)
} }
@@ -1,7 +1,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
annotation class Ann(val x: Int = 6) annotation class Ann(val x: Int = 6)
@Ann(1) @Ann(2) @Ann(3) @private class A [Ann] constructor() { @Ann(1) @Ann(2) @Ann(3) @private class A @Ann constructor() {
@Ann(x = 5) fun foo() { @Ann(x = 5) fun foo() {
1 + @Ann(1) 1 * @Ann(<!TYPE_MISMATCH!>""<!>) 6 1 + @Ann(1) 1 * @Ann(<!TYPE_MISMATCH!>""<!>) 6
@@ -1,5 +1,6 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
[file: Ann] <!DEPRECATED_ANNOTATION_SYNTAX!>[file: Ann]<!>
@file:[Ann]
annotation class Ann(val arg: Int = 1) annotation class Ann(val arg: Int = 1)
fun bar(block: () -> Int) = block() fun bar(block: () -> Int) = block()
@@ -8,7 +9,7 @@ data class Q(val x: Int, val y: Int)
fun bar2(): Array<Q> = null!! fun bar2(): Array<Q> = null!!
<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann Ann]<!> class A [Ann] constructor(<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> val prop: Int) { <!DEPRECATED_ANNOTATION_SYNTAX!>[Ann Ann]<!> class A <!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> constructor(<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> val prop: Int) {
<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> val x = 1 <!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> val x = 1
<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> fun foo(<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> x: Int) { <!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> fun foo(<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> x: Int) {
<!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> class B <!DEPRECATED_ANNOTATION_SYNTAX!>[Ann]<!> class B
@@ -4,7 +4,7 @@ open class Obsolete {
} }
deprecated("Class") deprecated("Class")
open class Obsolete2 [deprecated("Constructor")] constructor() { open class Obsolete2 deprecated("Constructor") constructor() {
fun use() {} fun use() {}
} }
@@ -32,7 +32,7 @@ var vardef: Int = 1
set set
<!INAPPLICABLE_ANNOTATION!>@platformName("C")<!> <!INAPPLICABLE_ANNOTATION!>@platformName("C")<!>
class C [<!INAPPLICABLE_ANNOTATION!>platformName("primary")<!>] constructor() { class C <!INAPPLICABLE_ANNOTATION!>platformName("primary")<!> constructor() {
<!INAPPLICABLE_ANNOTATION!>platformName("ctr")<!> constructor(x: Int): this() {} <!INAPPLICABLE_ANNOTATION!>platformName("ctr")<!> constructor(x: Int): this() {}
<!INAPPLICABLE_ANNOTATION!>@platformName("a")<!> <!INAPPLICABLE_ANNOTATION!>@platformName("a")<!>
fun foo() {} fun foo() {}
@@ -6,4 +6,4 @@ class A {
} }
} }
class C <!PLATFORM_STATIC_ILLEGAL_USAGE!>[platformStatic] constructor()<!> class C <!PLATFORM_STATIC_ILLEGAL_USAGE!>platformStatic constructor()<!>
@@ -7,4 +7,4 @@ class A {
<!INAPPLICABLE_ANNOTATION!>native constructor(<!UNUSED_PARAMETER!>x<!>: Int) <!INAPPLICABLE_ANNOTATION!>native constructor(<!UNUSED_PARAMETER!>x<!>: Int)
<!>} <!>}
class C <!INAPPLICABLE_ANNOTATION!>[native] constructor()<!> class C <!INAPPLICABLE_ANNOTATION!>native constructor()<!>
@@ -22,10 +22,12 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.addConstructorKeyword
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionFactory import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionFactory
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
import org.jetbrains.kotlin.psi.JetAnnotation import org.jetbrains.kotlin.psi.JetAnnotation
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetPrimaryConstructor
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
public class DeprecatedAnnotationSyntaxFix(element: JetAnnotation) : JetIntentionAction<JetAnnotation>(element) { public class DeprecatedAnnotationSyntaxFix(element: JetAnnotation) : JetIntentionAction<JetAnnotation>(element) {
@@ -51,11 +53,15 @@ public class DeprecatedAnnotationSyntaxFix(element: JetAnnotation) : JetIntentio
private fun replaceWithAtAnnotationEntries(annotation: JetAnnotation) { private fun replaceWithAtAnnotationEntries(annotation: JetAnnotation) {
val psiFactory = JetPsiFactory(annotation) val psiFactory = JetPsiFactory(annotation)
val hasFileKeyword = annotation.hasFileKeyword()
val parent = annotation.getParent() val parent = annotation.getParent()
val owner = parent.getParent()
var prevElement: PsiElement = annotation var prevElement: PsiElement = annotation
for (entry in annotation.getEntries()) { for (entry in annotation.getEntries()) {
val newEntry = psiFactory.createAnnotationEntry("@" + entry.getText()) val newEntry = if (hasFileKeyword) createFileAnnotationEntry(psiFactory, entry.getText())
else psiFactory.createAnnotationEntry("@" + entry.getText())
val added = parent.addAfter(newEntry, prevElement) val added = parent.addAfter(newEntry, prevElement)
if (prevElement != annotation) { if (prevElement != annotation) {
@@ -65,7 +71,14 @@ public class DeprecatedAnnotationSyntaxFix(element: JetAnnotation) : JetIntentio
prevElement = added prevElement = added
} }
if (owner is JetPrimaryConstructor) {
owner.addConstructorKeyword()
}
annotation.delete() annotation.delete()
} }
private fun createFileAnnotationEntry(psiFactory: JetPsiFactory, text: String) =
psiFactory.createFile("@file:$text").getAnnotationEntries().first()
} }
} }
+12 -12
View File
@@ -1,18 +1,18 @@
[file: kotlin.deprecated("message")] @file:kotlin.deprecated("message")
[file: suppress(<error>BAR</error>)] @file:suppress(<error>BAR</error>)
[file: suppress(BAZ)] @file:suppress(BAZ)
[<error>k</error>otlin.deprecated("message")] @<error>k</error>otlin.deprecated("message")
[<error>s</error>uppress(<error>BAR</error>)] @<error>s</error>uppress(<error>BAR</error>)
[<error>s</error>uppress(BAZ)] @<error>s</error>uppress(BAZ)
[file: myAnnotation(1, "string")] @file:myAnnotation(1, "string")
[file: boo.myAnnotation(1, <error>BAR</error>)] @file:boo.myAnnotation(1, <error>BAR</error>)
[file: myAnnotation(N, BAZ)] @file:myAnnotation(N, BAZ)
[<error>m</error>yAnnotation(1, "string")] @<error>m</error>yAnnotation(1, "string")
[<error>b</error>oo.myAnnotation(1, "string")] @<error>b</error>oo.myAnnotation(1, "string")
[<error>m</error>yAnnotation(N, BAZ)] @<error>m</error>yAnnotation(N, BAZ)
package boo package boo
@@ -15,7 +15,7 @@ fun testVisibility() {
<error descr="[UNRESOLVED_REFERENCE] Unresolved reference: ClassInM2">ClassInM2</error>() <error descr="[UNRESOLVED_REFERENCE] Unresolved reference: ClassInM2">ClassInM2</error>()
} }
public open class A internal () { public open class A internal constructor() {
private fun pri() { private fun pri() {
} }
fun int() { fun int() {
@@ -1,3 +1,3 @@
[file: Ann] @file:Ann
@Ann class B [Ann(1)]() @Ann class B @Ann(1) constructor()