diff --git a/idea/resources/inspectionDescriptions/RemoveAtFromAnnotationArgument.html b/idea/resources/inspectionDescriptions/RemoveAtFromAnnotationArgument.html
new file mode 100644
index 00000000000..05643eb457c
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/RemoveAtFromAnnotationArgument.html
@@ -0,0 +1,5 @@
+
+
+This inspection detects unnecessary '@' at annotations which are annotation arguments themselves.
+
+
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/after.kt.template b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/after.kt.template
new file mode 100644
index 00000000000..7fa1dd227a7
--- /dev/null
+++ b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/after.kt.template
@@ -0,0 +1,6 @@
+annotation class X(val value: Y)
+annotation class Y()
+
+@X(Y())
+fun foo() {}
+
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/before.kt.template b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/before.kt.template
new file mode 100644
index 00000000000..8428269659b
--- /dev/null
+++ b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/before.kt.template
@@ -0,0 +1,5 @@
+annotation class X(val value: Y)
+annotation class Y()
+
+@X(@Y())
+fun foo() {}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/description.html b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/description.html
new file mode 100644
index 00000000000..52753fa911c
--- /dev/null
+++ b/idea/resources/intentionDescriptions/RemoveAtFromAnnotationArgumentIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention removes unnecessary '@' from annotations which are annotation arguments themselves.
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index d63993bca6e..4e33e1213ec 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1255,6 +1255,11 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.RemoveAtFromAnnotationArgumentIntention
+ Kotlin
+
+
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt
new file mode 100644
index 00000000000..93c5ba458d7
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.intentions
+
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
+import org.jetbrains.kotlin.psi.KtAnnotatedExpression
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.kotlin.psi.KtPsiFactory
+
+class RemoveAtFromAnnotationArgumentInspection : IntentionBasedInspection(RemoveAtFromAnnotationArgumentIntention())
+
+class RemoveAtFromAnnotationArgumentIntention : SelfTargetingOffsetIndependentIntention(
+ KtAnnotatedExpression::class.java,
+ "Remove @ from annotation argument"
+) {
+ override fun isApplicableTo(element: KtAnnotatedExpression): Boolean {
+ var parent = element.parent
+ while (parent != null) {
+ if (parent is KtAnnotationEntry) return true
+ parent = parent.parent
+ }
+ return false
+ }
+
+ override fun applyTo(element: KtAnnotatedExpression, editor: Editor?) {
+ val noAt = KtPsiFactory(element.project).createExpression(element.text.replaceFirst("@", ""))
+ element.replace(noAt)
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/.intention b/idea/testData/intentions/removeAtFromAnnotationArgument/.intention
new file mode 100644
index 00000000000..295b958b15b
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.RemoveAtFromAnnotationArgumentIntention
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt
new file mode 100644
index 00000000000..4ad94e185b8
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt
@@ -0,0 +1,8 @@
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Y)
+annotation class Y()
+
+@X(@Y())
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt.after b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt.after
new file mode 100644
index 00000000000..d3dd56223f9
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt.after
@@ -0,0 +1,8 @@
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Y)
+annotation class Y()
+
+@X(Y())
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt
new file mode 100644
index 00000000000..fe5ea37d602
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Array)
+annotation class Y()
+
+@X(arrayOf(Y(), @Y()))
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt.after b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt.after
new file mode 100644
index 00000000000..73e663ffcbf
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt.after
@@ -0,0 +1,9 @@
+// WITH_RUNTIME
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Array)
+annotation class Y()
+
+@X(arrayOf(Y(), Y()))
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt b/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt
new file mode 100644
index 00000000000..30d0547b295
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt
@@ -0,0 +1,8 @@
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Y, val y: Y)
+annotation class Y()
+
+@X(@Y(), y = @Y())
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt.after b/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt.after
new file mode 100644
index 00000000000..5667186b6de
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt.after
@@ -0,0 +1,8 @@
+// INTENTION_TEXT: Remove @ from annotation argument
+
+annotation class X(val value: Y, val y: Y)
+annotation class Y()
+
+@X(@Y(), y = Y())
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/removeAtFromAnnotationArgument/stringAtmark.kt b/idea/testData/intentions/removeAtFromAnnotationArgument/stringAtmark.kt
new file mode 100644
index 00000000000..5d0e550b3b7
--- /dev/null
+++ b/idea/testData/intentions/removeAtFromAnnotationArgument/stringAtmark.kt
@@ -0,0 +1,7 @@
+// IS_APPLICABLE: false
+
+annotation class X(val s: String)
+
+@X("@@@")
+fun foo() {
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
index 65c08891acf..4d68d2d2911 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -7653,6 +7653,39 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/removeAtFromAnnotationArgument")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class RemoveAtFromAnnotationArgument extends AbstractIntentionTest {
+ public void testAllFilesPresentInRemoveAtFromAnnotationArgument() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/removeAtFromAnnotationArgument"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
+ }
+
+ @TestMetadata("atmarkArgument.kt")
+ public void testAtmarkArgument() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArgument.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("atmarkArrayArguments.kt")
+ public void testAtmarkArrayArguments() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeAtFromAnnotationArgument/atmarkArrayArguments.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("multipleAtmarkArguments.kt")
+ public void testMultipleAtmarkArguments() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeAtFromAnnotationArgument/multipleAtmarkArguments.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("stringAtmark.kt")
+ public void testStringAtmark() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/removeAtFromAnnotationArgument/stringAtmark.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/intentions/removeBraces")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)