diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 4ccf3c7ab4e..7fd4e95a920 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -29,8 +29,7 @@ import com.intellij.mock.MockApplication import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.extensions.Extensions -import com.intellij.openapi.extensions.ExtensionsArea +import com.intellij.openapi.extensions.* import com.intellij.openapi.fileTypes.FileTypeExtensionPoint import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.project.Project diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt index 81f8d99e3ee..0dedb209181 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt @@ -18,11 +18,13 @@ package org.jetbrains.kotlin.android.synthetic import com.intellij.mock.MockProject import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension import org.jetbrains.kotlin.android.synthetic.codegen.AndroidOnDestroyClassBuilderInterceptorExtension import org.jetbrains.kotlin.android.synthetic.diagnostic.AndroidExtensionPropertiesCallChecker +import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager import org.jetbrains.kotlin.android.synthetic.res.CliAndroidLayoutXmlFileManager import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator @@ -37,6 +39,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useInstance +import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.psi.JetFile @@ -75,7 +78,7 @@ public class AndroidCommandLineProcessor : CommandLineProcessor { public class CliAndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection { - val parser = ServiceManager.getService(project, javaClass()) as? CliSyntheticFileGenerator + val parser = ServiceManager.getService(project, SyntheticFileGenerator::class.java) as? CliSyntheticFileGenerator return parser?.getSyntheticFiles() ?: listOf() } } @@ -89,12 +92,13 @@ public class AndroidComponentRegistrar : ComponentRegistrar { if (androidResPath != null && androidManifest != null) { val xmlProcessor = CliSyntheticFileGenerator(project, androidManifest, androidResPath) - project.registerService(javaClass(), xmlProcessor) - project.registerService(javaClass(), CliAndroidLayoutXmlFileManager(project, androidManifest, androidResPath)) + project.registerService(SyntheticFileGenerator::class.java, xmlProcessor) + project.registerService(AndroidLayoutXmlFileManager::class.java, CliAndroidLayoutXmlFileManager(project, androidManifest, androidResPath)) ExternalDeclarationsProvider.registerExtension(project, CliAndroidDeclarationsProvider(project)) ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegenExtension()) StorageComponentContainerContributor.registerExtension(project, AndroidExtensionPropertiesComponentContainerContributor()) + Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesAndroid()) ClassBuilderInterceptorExtension.registerExtension(project, AndroidOnDestroyClassBuilderInterceptorExtension()) } } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt index 1c46d03b10b..2644a11bdd8 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidConst.kt @@ -17,9 +17,6 @@ package org.jetbrains.kotlin.android.synthetic import com.intellij.openapi.util.Key -import org.jetbrains.kotlin.android.synthetic.res.AndroidFragment -import org.jetbrains.kotlin.android.synthetic.res.AndroidResource -import org.jetbrains.kotlin.android.synthetic.res.AndroidWidget import org.jetbrains.kotlin.lexer.JetKeywordToken import org.jetbrains.kotlin.lexer.JetTokens @@ -53,8 +50,8 @@ public object AndroidConst { val IGNORED_XML_WIDGET_TYPES = setOf("requestFocus", "merge", "tag", "check", "blink") - val ESCAPED_IDENTIFIERS = (JetTokens.KEYWORDS.getTypes() + JetTokens.SOFT_KEYWORDS.getTypes()) - .map { it as? JetKeywordToken }.filterNotNull().map { it.getValue() }.toSet() + val ESCAPED_IDENTIFIERS = (JetTokens.KEYWORDS.types + JetTokens.SOFT_KEYWORDS.types) + .map { it as? JetKeywordToken }.filterNotNull().map { it.value }.toSet() val FQNAME_RESOLVE_PACKAGES = listOf("android.widget", "android.webkit", "android.view") } @@ -74,16 +71,4 @@ public fun isWidgetTypeIgnored(xmlType: String): Boolean { fun escapeAndroidIdentifier(id: String): String { return if (id in AndroidConst.ESCAPED_IDENTIFIERS) "`$id`" else id -} - -public fun parseAndroidResource(id: String, tag: String, fqNameResolver: (String) -> String?): AndroidResource { - return when (tag) { - "fragment" -> AndroidFragment(id) - "include" -> AndroidWidget(id, AndroidConst.VIEW_FQNAME) - else -> { - val fqName = fqNameResolver(tag) - val invalidType = if (fqName != null) null else tag - AndroidWidget(id, fqName ?: AndroidConst.VIEW_FQNAME, invalidType) - } - } } \ No newline at end of file diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecked.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecked.kt index 390d7cd89ab..341534bdc44 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecked.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/AndroidExtensionPropertiesCallChecked.kt @@ -16,7 +16,9 @@ package org.jetbrains.kotlin.android.synthetic.diagnostic +import com.intellij.openapi.project.Project import org.jetbrains.kotlin.android.synthetic.AndroidConst +import org.jetbrains.kotlin.android.synthetic.CliAndroidDeclarationsProvider import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker @@ -24,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid.* +import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider public class AndroidExtensionPropertiesCallChecker : CallChecker { override fun check(resolvedCall: ResolvedCall, context: BasicCallResolutionContext) { @@ -44,5 +47,4 @@ public class AndroidExtensionPropertiesCallChecker : CallChecker { val warning = if (erroneousType.contains('.')) SYNTHETIC_UNRESOLVED_WIDGET_TYPE else SYNTHETIC_INVALID_WIDGET_TYPE context.trace.report(warning.on(expression, erroneousType)) } - } \ No newline at end of file diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt index 853953d8c20..1dd4ce7be4d 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt @@ -29,8 +29,9 @@ public class DefaultErrorMessagesAndroid : DefaultErrorMessages.Extension { MAP.put(ErrorsAndroid.SYNTHETIC_INVALID_WIDGET_TYPE, "Widget has an invalid type ''{0}''. Please specify the fully qualified widget class name in XML", Renderers.TO_STRING) + MAP.put(ErrorsAndroid.SYNTHETIC_UNRESOLVED_WIDGET_TYPE, - "Widget has an unresolved type ''{0}'', and thus it was upcasted to ''android.view.View''.", + "Widget has an unresolved type ''{0}'', and thus it was upcasted to ''android.view.View''", Renderers.TO_STRING) } } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt index fb2ec408607..d5bbd70450a 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/CliSyntheticFileGenerator.kt @@ -23,9 +23,8 @@ import com.intellij.psi.PsiFile import java.io.ByteArrayInputStream import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler -import org.jetbrains.kotlin.android.synthetic.parseAndroidResource -import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.psi.JetFile public open class CliSyntheticFileGenerator( @@ -78,6 +77,13 @@ public open class CliSyntheticFileGenerator( return false } + override fun parseAndroidWidget(id: String, tag: String, fqNameResolver: (String) -> String?): AndroidResource { + val fqName = fqNameResolver(tag) + val invalidType = if (fqName != null) null else tag + val type = fqName ?: (if ('.' in tag) tag else AndroidConst.VIEW_FQNAME) + return AndroidWidget(id, type, invalidType) + } + private companion object { private val LOG: Logger = Logger.getInstance(javaClass) } diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt index a1f07661b80..5f3acc20298 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/res/SyntheticFileGenerator.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.android.synthetic.res import com.intellij.openapi.project.Project -import com.intellij.psi.PsiClass import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import com.intellij.psi.util.CachedValue @@ -123,7 +122,7 @@ public abstract class SyntheticFileGenerator(protected val project: Project) { private fun KotlinStringWriter.writeSyntheticProperty(receiver: String, resource: AndroidResource, stubCall: String) { val className = if (isFromSupportV4Package(receiver)) resource.supportClassName else resource.className - val cast = if (resource.className != "View") " as? $className" else "" + val cast = if (resource.className != AndroidConst.VIEW_FQNAME) " as? $className" else "" val body = arrayListOf("return $stubCall$cast") // Annotation on wrong widget type @@ -165,6 +164,16 @@ public abstract class SyntheticFileGenerator(protected val project: Project) { return null } + protected fun parseAndroidResource(id: String, tag: String, fqNameResolver: (String) -> String?): AndroidResource { + return when (tag) { + "fragment" -> AndroidFragment(id) + "include" -> AndroidWidget(id, AndroidConst.VIEW_FQNAME) + else -> parseAndroidWidget(id, tag, fqNameResolver) + } + } + + protected abstract fun parseAndroidWidget(id: String, tag: String, fqNameResolver: (String) -> String?): AndroidResource + protected fun supportV4Available(): Boolean = checkIfClassExist(AndroidConst.SUPPORT_FRAGMENT_FQNAME) protected fun filterDuplicates(resources: List): List { diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/layoutVariants/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/layoutVariants/test_LAYOUT.kt index b48ab9a1ac6..11283e65d24 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/layoutVariants/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/layoutVariants/test_LAYOUT.kt @@ -3,8 +3,8 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft val android.app.Activity.button: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) val android.app.Fragment.button: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/sameIds/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/sameIds/test_LAYOUT.kt index a02756962bb..35ba2197c3a 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/sameIds/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/sameIds/test_LAYOUT.kt @@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft val android.app.Activity.textView1: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) val android.app.Fragment.textView1: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) val android.app.Activity.textView2: ft get() = findViewById(0) as? android.widget.TextView diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/severalResDirs/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/severalResDirs/test_LAYOUT.kt index 3e3ae0f8488..acdb6f93efb 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/severalResDirs/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/severalResDirs/test_LAYOUT.kt @@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft val android.app.Activity.button: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) val android.app.Fragment.button: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) val android.app.Activity.button2: ft get() = findViewById(0) as? android.widget.Button diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/test_LAYOUT.kt index 575699045d2..1a033f42069 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/specialTags/test_LAYOUT.kt @@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft val android.app.Activity.includeTag: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) val android.app.Fragment.includeTag: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) val android.app.Activity.fragmentTag: ft get() = getFragmentManager().findFragmentById(0) as? android.app.Fragment diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/supportSpecialTags/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/supportSpecialTags/test_LAYOUT.kt index 5d03df61d6c..ab724cfcdb0 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/supportSpecialTags/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/supportSpecialTags/test_LAYOUT.kt @@ -3,13 +3,13 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft val android.app.Activity.includeTag: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) val android.app.Fragment.includeTag: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) val android.support.v4.app.Fragment.includeTag: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) val android.app.Activity.fragmentTag: ft get() = getFragmentManager().findFragmentById(0) as? android.app.Fragment diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedFqName/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedFqName/test_LAYOUT.kt index 0bed27102ce..0d2ac0dac9f 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedFqName/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedFqName/test_LAYOUT.kt @@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test import kotlin.internal.flexible.ft @kotlin.internal.flexible.InvalidWidgetType("a.b.c") -val android.app.Activity.MyView: ft - get() = findViewById(0) as? android.view.View +val android.app.Activity.MyView: ft + get() = findViewById(0) as? a.b.c @kotlin.internal.flexible.InvalidWidgetType("a.b.c") -val android.app.Fragment.MyView: ft - get() = getView().findViewById(0) as? android.view.View +val android.app.Fragment.MyView: ft + get() = getView().findViewById(0) as? a.b.c diff --git a/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedWidget/test_LAYOUT.kt b/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedWidget/test_LAYOUT.kt index 42654c7683d..7aca17cfa00 100644 --- a/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedWidget/test_LAYOUT.kt +++ b/plugins/android-compiler-plugin/testData/android/converter/simple/unresolvedWidget/test_LAYOUT.kt @@ -4,9 +4,9 @@ import kotlin.internal.flexible.ft @kotlin.internal.flexible.InvalidWidgetType("KeyboardView") val android.app.Activity.MyKeyboardView: ft - get() = findViewById(0) as? android.view.View + get() = findViewById(0) @kotlin.internal.flexible.InvalidWidgetType("KeyboardView") val android.app.Fragment.MyKeyboardView: ft - get() = getView().findViewById(0) as? android.view.View + get() = getView().findViewById(0) diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt index 939a92c6a08..842c64b02cb 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt @@ -25,8 +25,8 @@ import com.intellij.psi.util.CachedValueProvider.Result import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor -import org.jetbrains.kotlin.android.synthetic.parseAndroidResource import org.jetbrains.kotlin.android.synthetic.res.AndroidResource +import org.jetbrains.kotlin.android.synthetic.res.AndroidWidget import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator import org.jetbrains.kotlin.psi.JetFile @@ -62,6 +62,12 @@ class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(mod return filterDuplicates(widgets) } + override fun parseAndroidWidget(id: String, tag: String, fqNameResolver: (String) -> String?): AndroidResource { + val fqName = fqNameResolver(tag) + val invalidType = if (fqName != null) null else tag + return AndroidWidget(id, fqName ?: AndroidConst.VIEW_FQNAME, invalidType) + } + override fun checkIfClassExist(fqName: String): Boolean { val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(false) return JavaPsiFacade.getInstance(module.project).findClass(fqName, moduleScope) != null