Fix "unresolved widget fqname" bug in Gradle
This commit is contained in:
@@ -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
|
||||
|
||||
+7
-3
@@ -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<JetFile> {
|
||||
val parser = ServiceManager.getService(project, javaClass<SyntheticFileGenerator>()) 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<SyntheticFileGenerator>(), xmlProcessor)
|
||||
project.registerService(javaClass<AndroidLayoutXmlFileManager>(), 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())
|
||||
}
|
||||
}
|
||||
|
||||
+2
-17
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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 <F : CallableDescriptor> check(resolvedCall: ResolvedCall<F>, 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))
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -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)
|
||||
}
|
||||
|
||||
+11
-2
@@ -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<AndroidResource>): List<AndroidResource> {
|
||||
|
||||
Vendored
+2
-2
@@ -3,8 +3,8 @@ package kotlinx.android.synthetic.test
|
||||
import kotlin.internal.flexible.ft
|
||||
|
||||
val android.app.Activity.button: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
val android.app.Fragment.button: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
|
||||
+2
-2
@@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test
|
||||
import kotlin.internal.flexible.ft
|
||||
|
||||
val android.app.Activity.textView1: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
val android.app.Fragment.textView1: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
val android.app.Activity.textView2: ft<android.widget.TextView, android.widget.TextView?>
|
||||
get() = findViewById(0) as? android.widget.TextView
|
||||
|
||||
Vendored
+2
-2
@@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test
|
||||
import kotlin.internal.flexible.ft
|
||||
|
||||
val android.app.Activity.button: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
val android.app.Fragment.button: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
val android.app.Activity.button2: ft<android.widget.Button, android.widget.Button?>
|
||||
get() = findViewById(0) as? android.widget.Button
|
||||
|
||||
Vendored
+2
-2
@@ -3,10 +3,10 @@ package kotlinx.android.synthetic.test
|
||||
import kotlin.internal.flexible.ft
|
||||
|
||||
val android.app.Activity.includeTag: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
val android.app.Fragment.includeTag: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
val android.app.Activity.fragmentTag: ft<android.app.Fragment, android.app.Fragment?>
|
||||
get() = getFragmentManager().findFragmentById(0) as? android.app.Fragment
|
||||
|
||||
Vendored
+3
-3
@@ -3,13 +3,13 @@ package kotlinx.android.synthetic.test
|
||||
import kotlin.internal.flexible.ft
|
||||
|
||||
val android.app.Activity.includeTag: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
val android.app.Fragment.includeTag: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
val android.support.v4.app.Fragment.includeTag: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
val android.app.Activity.fragmentTag: ft<android.app.Fragment, android.app.Fragment?>
|
||||
get() = getFragmentManager().findFragmentById(0) as? android.app.Fragment
|
||||
|
||||
Vendored
+4
-4
@@ -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<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
val android.app.Activity.MyView: ft<a.b.c, a.b.c?>
|
||||
get() = findViewById(0) as? a.b.c
|
||||
|
||||
@kotlin.internal.flexible.InvalidWidgetType("a.b.c")
|
||||
val android.app.Fragment.MyView: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
val android.app.Fragment.MyView: ft<a.b.c, a.b.c?>
|
||||
get() = getView().findViewById(0) as? a.b.c
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -4,9 +4,9 @@ import kotlin.internal.flexible.ft
|
||||
|
||||
@kotlin.internal.flexible.InvalidWidgetType("KeyboardView")
|
||||
val android.app.Activity.MyKeyboardView: ft<android.view.View, android.view.View?>
|
||||
get() = findViewById(0) as? android.view.View
|
||||
get() = findViewById(0)
|
||||
|
||||
@kotlin.internal.flexible.InvalidWidgetType("KeyboardView")
|
||||
val android.app.Fragment.MyKeyboardView: ft<android.view.View, android.view.View?>
|
||||
get() = getView().findViewById(0) as? android.view.View
|
||||
get() = getView().findViewById(0)
|
||||
|
||||
|
||||
+7
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user