Add intentions for registering Android components in manifest

Activity, Service, BroadcastReceiver

#KT-17389 Fixed
This commit is contained in:
Vyacheslav Gerasimov
2017-04-18 19:02:54 +03:00
parent 5b58a6f9e8
commit 06c8de02b5
57 changed files with 912 additions and 2 deletions
+1
View File
@@ -23,5 +23,6 @@
<orderEntry type="module" module-name="lint-idea" scope="TEST" />
<orderEntry type="library" name="uast-java" level="project" />
<orderEntry type="library" name="kotlin-reflect" level="project" />
<orderEntry type="module" module-name="light-classes" />
</component>
</module>
@@ -0,0 +1,54 @@
/*
* 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.intention
import com.intellij.openapi.editor.Editor
import org.jetbrains.android.dom.manifest.Manifest
import org.jetbrains.android.facet.AndroidFacet
import org.jetbrains.kotlin.android.insideBody
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.psiUtil.isAbstract
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
import org.jetbrains.kotlin.psi.psiUtil.isProtected
abstract class AbstractRegisterComponentAction(text: String) : SelfTargetingIntention<KtClass>(KtClass::class.java, text) {
abstract fun isApplicableTo(element: KtClass, manifest: Manifest): Boolean
abstract fun applyTo(element: KtClass, manifest: Manifest)
final override fun isApplicableTo(element: KtClass, caretOffset: Int): Boolean {
val androidFacet = AndroidFacet.getInstance(element.containingFile) ?: return false
val manifest = androidFacet.manifest ?: return false
return !element.isLocal &&
!element.isAbstract() &&
!element.isPrivate() &&
!element.isProtected() &&
!element.isInner() &&
!element.name.isNullOrEmpty() &&
!element.insideBody(caretOffset) &&
isApplicableTo(element, manifest)
}
final override fun applyTo(element: KtClass, editor: Editor?) {
AndroidFacet.getInstance(element.containingFile)?.manifest?.let {
applyTo(element, it)
}
}
}
@@ -0,0 +1,45 @@
/*
* 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.intention
import com.android.SdkConstants
import org.jetbrains.android.dom.manifest.Manifest
import org.jetbrains.kotlin.android.isSubclassOf
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.asJava.toLightClass
class AddActivityToManifest : AbstractRegisterComponentAction("Add activity to manifest") {
override fun isApplicableTo(element: KtClass, manifest: Manifest): Boolean =
element.isSubclassOfActivity() && !element.isRegisteredActivity(manifest)
override fun applyTo(element: KtClass, manifest: Manifest) = runWriteAction {
val psiClass = element.toLightClass() ?: return@runWriteAction
manifest.application.addActivity().activityClass.value = psiClass
}
private fun KtClass.isRegisteredActivity(manifest: Manifest) = manifest.application.activities.any {
it.activityClass.value?.qualifiedName == fqName?.asString()
}
private fun KtClass.isSubclassOfActivity() =
(descriptor as? ClassDescriptor)?.defaultType?.isSubclassOf(FqName(SdkConstants.CLASS_ACTIVITY), true) ?: false
}
@@ -0,0 +1,45 @@
/*
* 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.intention
import com.android.SdkConstants
import org.jetbrains.android.dom.manifest.Manifest
import org.jetbrains.kotlin.android.isSubclassOf
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClass
class AddBroadcastReceiverToManifest : AbstractRegisterComponentAction("Add broadcast receiver to manifest") {
override fun isApplicableTo(element: KtClass, manifest: Manifest): Boolean =
element.isSubclassOfBroadcastReceiver() && !element.isRegisteredBroadcastReceiver(manifest)
override fun applyTo(element: KtClass, manifest: Manifest) = runWriteAction {
val psiClass = element.toLightClass() ?: return@runWriteAction
manifest.application.addReceiver().receiverClass.value = psiClass
}
private fun KtClass.isRegisteredBroadcastReceiver(manifest: Manifest) = manifest.application.receivers.any {
it.receiverClass.value?.qualifiedName == fqName?.asString()
}
private fun KtClass.isSubclassOfBroadcastReceiver() =
(descriptor as? ClassDescriptor)?.defaultType?.isSubclassOf(FqName(SdkConstants.CLASS_BROADCASTRECEIVER), true) ?: false
}
@@ -0,0 +1,45 @@
/*
* 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.intention
import com.android.SdkConstants
import org.jetbrains.android.dom.manifest.Manifest
import org.jetbrains.kotlin.android.isSubclassOf
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClass
class AddServiceToManifest : AbstractRegisterComponentAction("Add service to manifest") {
override fun isApplicableTo(element: KtClass, manifest: Manifest): Boolean =
element.isSubclassOfService() && !element.isRegisteredService(manifest)
override fun applyTo(element: KtClass, manifest: Manifest) = runWriteAction {
val psiClass = element.toLightClass() ?: return@runWriteAction
manifest.application.addService().serviceClass.value = psiClass
}
private fun KtClass.isRegisteredService(manifest: Manifest) = manifest.application.services.any {
it.serviceClass.value?.qualifiedName == fqName?.asString()
}
private fun KtClass.isSubclassOfService() =
(descriptor as? ClassDescriptor)?.defaultType?.isSubclassOf(FqName(SdkConstants.CLASS_SERVICE), true) ?: false
}
@@ -37,12 +37,19 @@ abstract class AbstractAndroidIntentionTest : KotlinAndroidTestCase() {
val notAvailable = InTextDirectivesUtils.isDirectiveDefined(testFileText, "// NOT_AVAILABLE")
val withRuntime = InTextDirectivesUtils.isDirectiveDefined(testFileText, "// WITH_RUNTIME")
val checkManifest = InTextDirectivesUtils.isDirectiveDefined(testFileText, "// CHECK_MANIFEST")
try {
if (withRuntime) {
ConfigLibraryUtil.configureKotlinRuntime(myFixture.module)
}
val customManifestPath = "${testFile.path}.AndroidManifest.xml"
if (FileUtil.exists("$testDataPath/$customManifestPath")) {
deleteManifest()
myFixture.copyFileToProject(customManifestPath, SdkConstants.FN_ANDROID_MANIFEST_XML)
}
val sourceFile = myFixture.copyFileToProject(path, "src/${PathUtil.getFileName(path)}")
myFixture.configureFromExistingVirtualFile(sourceFile)
@@ -55,8 +62,18 @@ abstract class AbstractAndroidIntentionTest : KotlinAndroidTestCase() {
error("Intention is not available!")
}
if (notAvailable) {
error("Intention should not be available!")
}
myFixture.launchAction(intention)
myFixture.checkResultByFile("$path.expected")
if (checkManifest) {
myFixture.checkResultByFile("AndroidManifest.xml", "$customManifestPath.expected", true)
}
else {
myFixture.checkResultByFile("$path.expected")
}
}
finally {
if (withRuntime) {
@@ -36,6 +36,213 @@ public class AndroidIntentionTestGenerated extends AbstractAndroidIntentionTest
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("idea/testData/android/intention/addActivityToManifest")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddActivityToManifest extends AbstractAndroidIntentionTest {
@TestMetadata("abstract.kt")
public void testAbstract() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/abstract.kt");
doTest(fileName);
}
public void testAllFilesPresentInAddActivityToManifest() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/addActivityToManifest"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("alreadyExists.kt")
public void testAlreadyExists() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/alreadyExists.kt");
doTest(fileName);
}
@TestMetadata("inner.kt")
public void testInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/inner.kt");
doTest(fileName);
}
@TestMetadata("insideBody.kt")
public void testInsideBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/insideBody.kt");
doTest(fileName);
}
@TestMetadata("local.kt")
public void testLocal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/local.kt");
doTest(fileName);
}
@TestMetadata("nested.kt")
public void testNested() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/nested.kt");
doTest(fileName);
}
@TestMetadata("notActivity.kt")
public void testNotActivity() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/notActivity.kt");
doTest(fileName);
}
@TestMetadata("private.kt")
public void testPrivate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/private.kt");
doTest(fileName);
}
@TestMetadata("protected.kt")
public void testProtected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/protected.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addActivityToManifest/simple.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddBroadcastReceiverToManifest extends AbstractAndroidIntentionTest {
@TestMetadata("abstract.kt")
public void testAbstract() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/abstract.kt");
doTest(fileName);
}
public void testAllFilesPresentInAddBroadcastReceiverToManifest() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/addBroadcastReceiverToManifest"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("alreadyExists.kt")
public void testAlreadyExists() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/alreadyExists.kt");
doTest(fileName);
}
@TestMetadata("inner.kt")
public void testInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/inner.kt");
doTest(fileName);
}
@TestMetadata("insideBody.kt")
public void testInsideBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/insideBody.kt");
doTest(fileName);
}
@TestMetadata("local.kt")
public void testLocal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/local.kt");
doTest(fileName);
}
@TestMetadata("nested.kt")
public void testNested() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/nested.kt");
doTest(fileName);
}
@TestMetadata("notReceiver.kt")
public void testNotReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/notReceiver.kt");
doTest(fileName);
}
@TestMetadata("private.kt")
public void testPrivate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/private.kt");
doTest(fileName);
}
@TestMetadata("protected.kt")
public void testProtected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/protected.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addBroadcastReceiverToManifest/simple.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/android/intention/addServiceToManifest")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddServiceToManifest extends AbstractAndroidIntentionTest {
@TestMetadata("abstract.kt")
public void testAbstract() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/abstract.kt");
doTest(fileName);
}
public void testAllFilesPresentInAddServiceToManifest() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/addServiceToManifest"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("alreadyExists.kt")
public void testAlreadyExists() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/alreadyExists.kt");
doTest(fileName);
}
@TestMetadata("inner.kt")
public void testInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/inner.kt");
doTest(fileName);
}
@TestMetadata("insideBody.kt")
public void testInsideBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/insideBody.kt");
doTest(fileName);
}
@TestMetadata("local.kt")
public void testLocal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/local.kt");
doTest(fileName);
}
@TestMetadata("nested.kt")
public void testNested() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/nested.kt");
doTest(fileName);
}
@TestMetadata("notService.kt")
public void testNotService() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/notService.kt");
doTest(fileName);
}
@TestMetadata("private.kt")
public void testPrivate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/private.kt");
doTest(fileName);
}
@TestMetadata("protected.kt")
public void testProtected() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/protected.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/addServiceToManifest/simple.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/android/intention/implementParcelable")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -0,0 +1,3 @@
<application>
<activity android:name=".MyActivity"/>
</application>
@@ -0,0 +1,2 @@
<application>
</application>
@@ -0,0 +1,5 @@
<html>
<body>
Add an activity class to AndroidManifest.xml
</body>
</html>
@@ -0,0 +1,3 @@
<application>
<receiver android:name=".MyReceiver"/>
</application>
@@ -0,0 +1,2 @@
<application>
</application>
@@ -0,0 +1,5 @@
<html>
<body>
Add a subclass of BroadcastReceiver to AndroidManifest.xml
</body>
</html>
@@ -0,0 +1,3 @@
<application>
<service android:name=".MyService"/>
</application>
@@ -0,0 +1,2 @@
<application>
</application>
@@ -0,0 +1,5 @@
<html>
<body>
Add a service subclass to AndroidManifest.xml
</body>
</html>
+14
View File
@@ -23,6 +23,20 @@
<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>
@@ -0,0 +1,8 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
abstract class <caret>MyActivity : Activity()
@@ -0,0 +1,8 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
class <caret>MyActivity : Activity()
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<activity android:name=".MyActivity"/>
</application>
</manifest>
@@ -0,0 +1,10 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
class Test {
inner class <caret>MyActivity : Activity()
}
@@ -0,0 +1,10 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
class MyActivity : Activity() {
<caret>
}
@@ -0,0 +1,10 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
fun test() {
class <caret>MyActivity : Activity()
}
@@ -0,0 +1,9 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// CHECK_MANIFEST
package com.myapp
import android.app.Activity
class Test {
class <caret>MyActivity : Activity()
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<activity android:name=".Test$MyActivity"/>
</application>
</manifest>
@@ -0,0 +1,6 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
class <caret>MyActivity
@@ -0,0 +1,8 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
private class <caret>MyActivity : Activity()
@@ -0,0 +1,10 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Activity
class Test {
protected class <caret>MyActivity : Activity()
}
@@ -0,0 +1,8 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddActivityToManifest
// CHECK_MANIFEST
package com.myapp
import android.app.Activity
class <caret>MyActivity : Activity()
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<activity android:name=".MyActivity"/>
</application>
</manifest>
@@ -0,0 +1,12 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
abstract class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
@@ -0,0 +1,12 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<receiver android:name=".MyReceiver"/>
</application>
</manifest>
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class Test {
inner class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
}
@@ -0,0 +1,13 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
<caret>
}
}
@@ -0,0 +1,15 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
fun test() {
class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
}
@@ -0,0 +1,15 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// CHECK_MANIFEST
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class Test {
class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<receiver android:name=".Test$MyReceiver"/>
</application>
</manifest>
@@ -0,0 +1,6 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
class <caret>MyReceiver
@@ -0,0 +1,12 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
private class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// NOT_AVAILABLE
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class Test {
protected class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
}
@@ -0,0 +1,12 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest
// CHECK_MANIFEST
package com.myapp
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class <caret>MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<receiver android:name=".MyReceiver"/>
</application>
</manifest>
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
abstract class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<service android:name=".MyService"/>
</application>
</manifest>
@@ -0,0 +1,16 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class Test {
inner class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
}
@@ -0,0 +1,15 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
<caret>
TODO("not implemented")
}
}
@@ -0,0 +1,16 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
fun test() {
class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
}
@@ -0,0 +1,16 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// CHECK_MANIFEST
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class Test {
class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<service android:name=".Test$MyService"/>
</application>
</manifest>
@@ -0,0 +1,6 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
class <caret>MyService
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
private class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
@@ -0,0 +1,16 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// NOT_AVAILABLE
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class Test {
protected class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
}
@@ -0,0 +1,14 @@
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.AddServiceToManifest
// CHECK_MANIFEST
package com.myapp
import android.app.Service
import android.content.Intent
import android.os.IBinder
class <caret>MyService : Service() {
override fun onBind(intent: Intent?): IBinder {
TODO("not implemented")
}
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp"
android:versionCode="1"
android:versionName="1.0" >
<application>
<service android:name=".MyService"/>
</application>
</manifest>
@@ -27,6 +27,7 @@ import java.io.File
class IntentionDescriptionTest : LightPlatformTestCase() {
val necessaryNormalNames = listOf("description.html", "before.kt.template", "after.kt.template")
val necessaryXmlNames = listOf("description.html", "before.xml.template", "after.xml.template")
val necessaryMavenNames = listOf("description.html")
fun testDescriptionsAndShortNames() {
@@ -40,7 +41,11 @@ class IntentionDescriptionTest : LightPlatformTestCase() {
errors.append("No description directory for intention '").append(className).append("'\n")
}
else {
val necessaryNames = if (shortName.startsWith("MavenPlugin")) necessaryMavenNames else necessaryNormalNames
val necessaryNames = when {
shortName.isMavenIntentionName() -> necessaryMavenNames
shortName.isXmlIntentionName() -> necessaryXmlNames
else -> necessaryNormalNames
}
for (fileName in necessaryNames) {
val file = directory.resolve(fileName)
if (!file.exists() || !file.isFile) {
@@ -52,6 +57,10 @@ class IntentionDescriptionTest : LightPlatformTestCase() {
UsefulTestCase.assertEmpty(errors.toString())
}
private fun String.isMavenIntentionName() = startsWith("MavenPlugin")
private fun String.isXmlIntentionName() = startsWith("Add") && endsWith("ToManifest")
private fun loadKotlinIntentions(): List<IntentionActionBean> {
val extensionPoint = Extensions.getArea(null).getExtensionPoint(IntentionManager.EP_INTENTION_ACTIONS)
return extensionPoint.extensions.toList().filter {