From c7f1fd74a1f184056a55e46bf621c7eac219a7fc Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Fri, 6 Nov 2015 18:35:29 +0300 Subject: [PATCH] Create descriptors directly in Android Extensions (IDEA plugin) --- idea/src/META-INF/android.xml | 16 + idea/src/META-INF/extensions/common.xml | 3 + .../kotlin/android/synthetic/AndroidConst.kt | 13 +- .../android/synthetic/AndroidXmlHandler.kt | 2 +- .../src/META-INF/plugin.xml | 38 -- .../idea/AndroidFindMemberUsagesHandler.kt | 112 ----- .../idea/AndroidGotoDeclarationHandler.kt | 33 +- .../synthetic/idea/AndroidRenameProcessor.kt | 152 ------ .../AndroidSimpleNameReferenceExtension.kt | 27 +- .../synthetic/idea/AndroidXmlVisitor.kt | 4 +- .../IDEAndroidExternalDeclarationsProvider.kt | 40 -- .../android/synthetic/idea/TestConst.java | 23 - .../idea/XmlAttributeValueWrapper.java | 459 ------------------ .../res/IDEAndroidLayoutXmlFileManager.kt | 47 +- ...AndroidPackageFragmentProviderExtension.kt | 35 ++ .../idea/res/IDESyntheticFileGenerator.kt | 75 --- 16 files changed, 131 insertions(+), 948 deletions(-) delete mode 100644 plugins/android-idea-plugin/src/META-INF/plugin.xml delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java create mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt delete mode 100644 plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt diff --git a/idea/src/META-INF/android.xml b/idea/src/META-INF/android.xml index e3c1428c2bf..58747fe0e1c 100644 --- a/idea/src/META-INF/android.xml +++ b/idea/src/META-INF/android.xml @@ -1,5 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/idea/src/META-INF/extensions/common.xml b/idea/src/META-INF/extensions/common.xml index 2ac1a18c52a..eb53cd13743 100644 --- a/idea/src/META-INF/extensions/common.xml +++ b/idea/src/META-INF/extensions/common.xml @@ -23,6 +23,9 @@ + List.forEachUntilLast(operation: (T) -> Unit) { val lastIndex = lastIndex forEachIndexed { i, t -> diff --git a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt index 85f0208226c..1d3569b19f2 100644 --- a/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt +++ b/plugins/android-compiler-plugin/src/org/jetbrains/kotlin/android/synthetic/AndroidXmlHandler.kt @@ -35,7 +35,7 @@ class AndroidXmlHandler(private val elementCallback: (String, String) -> Unit) : val attributesMap = attributes.toMap() val idAttribute = attributesMap[AndroidConst.ID_ATTRIBUTE_NO_NAMESPACE] val widgetType = attributesMap[AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE] ?: localName - val name = idAttribute?.let { idToName(idAttribute) } + val name = idAttribute?.let { androidIdToName(idAttribute) } if (name != null) elementCallback(name, widgetType) } diff --git a/plugins/android-idea-plugin/src/META-INF/plugin.xml b/plugins/android-idea-plugin/src/META-INF/plugin.xml deleted file mode 100644 index 05d4ec77869..00000000000 --- a/plugins/android-idea-plugin/src/META-INF/plugin.xml +++ /dev/null @@ -1,38 +0,0 @@ - - org.jetbrains.kotlin.android - - Kotlin Extensions For Android - Various extensions facilitating Android development in Kotlin - @snapshot@ - JetBrains s.r.o. - - - - org.jetbrains.kotlin - org.jetbrains.android - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt deleted file mode 100644 index 10485fc35ee..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidFindMemberUsagesHandler.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea - -import com.intellij.find.findUsages.FindUsagesHandler -import com.intellij.find.findUsages.FindUsagesOptions -import com.intellij.find.findUsages.JavaVariableFindUsagesOptions -import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.module.ModuleServiceManager -import com.intellij.psi.PsiElement -import com.intellij.psi.xml.XmlAttribute -import com.intellij.usageView.UsageInfo -import com.intellij.util.Processor -import org.jetbrains.android.util.AndroidResourceUtil -import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement -import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo -import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo -import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtProperty -import java.util.ArrayList - -class AndroidFindUsageHandlerDecorator : KotlinFindUsagesHandlerDecorator { - override fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler { - if (element !is KtNamedDeclaration) return delegate - if (!isAndroidSyntheticElement(element)) return delegate - - return AndroidFindMemberUsagesHandler(element, delegate) - } -} - -class AndroidFindMemberUsagesHandler( - private val declaration: KtNamedDeclaration, - private val delegate: FindUsagesHandler? = null -) : FindUsagesHandler(declaration) { - - override fun getPrimaryElements(): Array { - assert(isAndroidSyntheticElement(declaration)) - - val property = declaration as KtProperty - val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements() - val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) - - val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property) - val valueElements = psiElements?.map { (it as? XmlAttribute)?.getValueElement() as? PsiElement }?.filterNotNull() - if (valueElements != null && valueElements.isNotEmpty()) return valueElements.toTypedArray() - - return super.getPrimaryElements() - } - - override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions { - return delegate?.getFindUsagesOptions(dataContext) ?: super.getFindUsagesOptions(dataContext) - } - - override fun getSecondaryElements(): Array { - assert(isAndroidSyntheticElement(declaration)) - - val property = declaration as KtProperty - val moduleInfo = declaration.getModuleInfo() as? ModuleSourceInfo ?: return super.getPrimaryElements() - val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass()) - - val psiElements = parser?.layoutXmlFileManager?.propertyToXmlAttributes(property) ?: listOf() - - val res = ArrayList() - for (psiElement in psiElements) { - if (psiElement is XmlAttribute) { - val fields = AndroidResourceUtil.findIdFields(psiElement) - for (field in fields) { - res.add(field) - } - res.add(declaration) - } - } - - if (res.isNotEmpty()) return res.toTypedArray() - - return super.getSecondaryElements() - } - - override fun processElementUsages(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { - assert(isAndroidSyntheticElement(declaration)) - - val findUsagesOptions = JavaVariableFindUsagesOptions(runReadAction { element.project }) - findUsagesOptions.isSearchForTextOccurrences = false - findUsagesOptions.isSkipImportStatements = true - findUsagesOptions.isUsages = true - findUsagesOptions.isReadAccess = true - findUsagesOptions.isWriteAccess = true - return super.processElementUsages(element, processor, findUsagesOptions) - } - - // Android extensions plugin has it's own runtime -> different function classes - private fun runReadAction(action: () -> T): T { - return ApplicationManager.getApplication().runReadAction(action) - } -} diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt index 002a55b17b7..18c9358a7b5 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidGotoDeclarationHandler.kt @@ -23,31 +23,44 @@ import com.intellij.openapi.module.ModuleServiceManager import com.intellij.psi.PsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.xml.XmlAttribute -import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator +import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo -import org.jetbrains.kotlin.idea.references.KtSimpleNameReference -import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array? { if (sourceElement is LeafPsiElement && sourceElement.parent is KtSimpleNameExpression) { - val resolved = KtSimpleNameReference(sourceElement.parent as KtSimpleNameExpression).resolve() - val property = resolved as? KtProperty ?: return null + val simpleNameExpression = sourceElement.parent as? KtSimpleNameExpression ?: return null + val layoutManager = getLayoutManager(sourceElement) ?: return null + val propertyDescriptor = resolvePropertyDescriptor(simpleNameExpression) ?: return null - val moduleInfo = sourceElement.getModuleInfo() - if (moduleInfo !is ModuleSourceInfo) return null - - val parser = ModuleServiceManager.getService(moduleInfo.module, SyntheticFileGenerator::class.java)!! - val psiElements = parser.layoutXmlFileManager.propertyToXmlAttributes(property) + val psiElements = layoutManager.propertyToXmlAttributes(propertyDescriptor) val valueElements = psiElements.map { (it as? XmlAttribute)?.valueElement as? PsiElement }.filterNotNull() if (valueElements.isNotEmpty()) return valueElements.toTypedArray() } + return null } + private fun resolvePropertyDescriptor(simpleNameExpression: KtSimpleNameExpression): PropertyDescriptor? { + val bindingContext = simpleNameExpression.analyze(BodyResolveMode.PARTIAL) + val call = bindingContext[BindingContext.CALL, simpleNameExpression] + val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] + return resolvedCall?.resultingDescriptor as? PropertyDescriptor + } + + private fun getLayoutManager(sourceElement: PsiElement): AndroidLayoutXmlFileManager? { + val moduleInfo = sourceElement.getModuleInfo() + if (moduleInfo !is ModuleSourceInfo) return null + return ModuleServiceManager.getService(moduleInfo.module, AndroidLayoutXmlFileManager::class.java) + } + override fun getActionText(context: DataContext?): String? { return null } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt deleted file mode 100644 index e04cb0496b1..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidRenameProcessor.kt +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea - -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleServiceManager -import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiField -import com.intellij.psi.impl.light.LightElement -import com.intellij.psi.search.SearchScope -import com.intellij.psi.xml.XmlAttribute -import com.intellij.psi.xml.XmlAttributeValue -import com.intellij.refactoring.rename.RenamePsiElementProcessor -import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper -import org.jetbrains.android.util.AndroidResourceUtil -import org.jetbrains.kotlin.android.synthetic.AndroidConst -import org.jetbrains.kotlin.android.synthetic.idToName -import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement -import org.jetbrains.kotlin.android.synthetic.nameToIdDeclaration -import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo -import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo -import org.jetbrains.kotlin.psi.KtProperty - -public class AndroidRenameProcessor : RenamePsiElementProcessor() { - - override fun canProcessElement(element: PsiElement): Boolean { - // Either renaming synthetic property, or value in layout xml, or R class field - return (element.namedUnwrappedElement is KtProperty && - isAndroidSyntheticElement(element.namedUnwrappedElement)) || element is XmlAttributeValue || - isRClassField(element) - } - - private fun isRClassField(element: PsiElement): Boolean { - return if (element is PsiField) { - val outerClass = element.getParent()?.getParent() - if (outerClass !is PsiClass) return false - - if (outerClass.getQualifiedName()?.startsWith(AndroidConst.SYNTHETIC_PACKAGE) ?: false) - true else false - } - else false - } - - - private fun PsiElement.getModule(): Module? { - val moduleInfo = getModuleInfo() - return if (moduleInfo is ModuleSourceInfo) moduleInfo.module else null - } - - override fun prepareRenaming( - element: PsiElement?, - newName: String, - allRenames: MutableMap, - scope: SearchScope - ) { - if (element != null && element.namedUnwrappedElement is KtProperty) { - renameSyntheticProperty(element.namedUnwrappedElement as KtProperty, newName, allRenames) - } - else if (element is XmlAttributeValue) { - renameAttributeValue(element, newName, allRenames) - } - else if (element is LightElement) { - renameLightClassField(element, newName, allRenames) - } - } - - private fun renameSyntheticProperty( - jetProperty: KtProperty, - newName: String, - allRenames: MutableMap - ) { - val module = jetProperty.getModule() ?: return - - val processor = ModuleServiceManager.getService(module, javaClass())!! - val resourceManager = processor.layoutXmlFileManager - - val psiElements = resourceManager.propertyToXmlAttributes(jetProperty).map { it as? XmlAttribute }.filterNotNull() - - for (psiElement in psiElements) { - val valueElement = psiElement.getValueElement() - - if (valueElement != null) { - allRenames[XmlAttributeValueWrapper(valueElement)] = nameToIdDeclaration(newName) - val name = AndroidResourceUtil.getResourceNameByReferenceText(newName) ?: return - for (resField in AndroidResourceUtil.findIdFields(psiElement)) { - allRenames.put(resField, AndroidResourceUtil.getFieldNameByResourceName(name)) - } - } - } - } - - private fun renameAttributeValue( - attribute: XmlAttributeValue, - newName: String, - allRenames: MutableMap - ) { - val element = LazyValueResourceElementWrapper.computeLazyElement(attribute) - val module = attribute.getModule() ?: ModuleUtilCore.findModuleForFile( - attribute.getContainingFile().getVirtualFile(), attribute.getProject()) ?: return - - val processor = ModuleServiceManager.getService(module, javaClass())!! - if (element == null) return - val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()) - val newPropName = idToName(newName) - if (oldPropName != null && newPropName != null) { - renameSyntheticProperties(allRenames, newPropName, oldPropName, processor) - } - } - - private fun renameSyntheticProperties( - allRenames: MutableMap, - newPropName: String, - oldPropName: String, - processor: SyntheticFileGenerator - ) { - val props = processor.getSyntheticFiles().flatMap { it.findChildrenByClass(javaClass()).toList() } - val matchedProps = props.filter { it.getName() == oldPropName } ?: listOf() - for (prop in matchedProps) { - allRenames[prop] = newPropName - } - } - - private fun renameLightClassField( - field: LightElement, - newName: String, - allRenames: MutableMap - ) { - val oldName = field.getName()!! - val processor = ServiceManager.getService(field.getProject(), javaClass()) - renameSyntheticProperties(allRenames, newName, oldName, processor) - } - -} diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt index afee4912d14..91fcf1b2a36 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidSimpleNameReferenceExtension.kt @@ -17,30 +17,25 @@ package org.jetbrains.kotlin.android.synthetic.idea import com.intellij.psi.PsiElement +import com.intellij.psi.xml.XmlAttributeValue import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper -import org.jetbrains.kotlin.android.synthetic.isAndroidSyntheticElement +import org.jetbrains.android.util.AndroidResourceUtil +import org.jetbrains.kotlin.android.synthetic.androidIdToName import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.plugin.references.SimpleNameReferenceExtension -import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtPsiFactory -public class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { - override fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean? { - val resolvedElement = reference.resolve() as? KtProperty ?: return null +class AndroidSimpleNameReferenceExtension : SimpleNameReferenceExtension { - if (isAndroidSyntheticElement(resolvedElement)) { - if (element is ValueResourceElementWrapper) { - val resource = element.value - return resolvedElement.name == resource.substring(resource.indexOf('/') + 1) - } - } - return null + override fun isReferenceTo(reference: KtSimpleNameReference, element: PsiElement): Boolean { + return element is ValueResourceElementWrapper && AndroidResourceUtil.isIdDeclaration(element) } override fun handleElementRename(reference: KtSimpleNameReference, psiFactory: KtPsiFactory, newElementName: String): PsiElement? { - return if (newElementName.startsWith("@+id/")) - psiFactory.createNameIdentifier(newElementName.substring(newElementName.indexOf('/') + 1)) - else - null + val resolvedElement = reference.resolve() + if (resolvedElement !is XmlAttributeValue || !AndroidResourceUtil.isIdDeclaration(resolvedElement)) return null + val newSyntheticPropertyName = androidIdToName(newElementName) ?: return null + + return psiFactory.createNameIdentifier(newSyntheticPropertyName) } } \ No newline at end of file diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt index c99994d97e6..39436c13647 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/AndroidXmlVisitor.kt @@ -22,7 +22,7 @@ import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.xml.XmlElement import com.intellij.psi.xml.XmlTag import org.jetbrains.kotlin.android.synthetic.AndroidConst -import org.jetbrains.kotlin.android.synthetic.idToName +import org.jetbrains.kotlin.android.synthetic.androidIdToName import org.jetbrains.kotlin.android.synthetic.isWidgetTypeIgnored class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> Unit) : XmlElementVisitor() { @@ -47,7 +47,7 @@ class AndroidXmlVisitor(val elementCallback: (String, String, XmlAttribute) -> U val idAttributeValue = idAttribute.value if (idAttributeValue != null) { val xmlType = tag?.getAttribute(AndroidConst.CLASS_ATTRIBUTE_NO_NAMESPACE)?.value ?: localName - val name = idToName(idAttributeValue) + val name = androidIdToName(idAttributeValue) if (name != null) elementCallback(name, xmlType, idAttribute) } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt deleted file mode 100644 index 737ff4453ea..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/IDEAndroidExternalDeclarationsProvider.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea - -import com.intellij.openapi.module.ModuleServiceManager -import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.android.synthetic.idea.res.IDESyntheticFileGenerator -import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator -import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider -import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.moduleInfo - -public class IDEAndroidExternalDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider { - override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection { - if (moduleInfo !is ModuleSourceInfo) return listOf() - - val module = moduleInfo.module - val parser = ModuleServiceManager.getService(module, SyntheticFileGenerator::class.java) as? IDESyntheticFileGenerator - val syntheticFiles = parser?.getSyntheticFiles() - syntheticFiles?.forEach { it.moduleInfo = moduleInfo } - - return syntheticFiles ?: listOf() - } -} \ No newline at end of file diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java deleted file mode 100644 index fb4591a534c..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/TestConst.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea; - -import com.intellij.openapi.util.Key; - -public class TestConst { - public static final Key TESTDATA_PATH = Key.create(""); -} diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java deleted file mode 100644 index 29283be78ed..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/XmlAttributeValueWrapper.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea; - -import com.intellij.lang.ASTNode; -import com.intellij.lang.Language; -import com.intellij.navigation.ItemPresentation; -import com.intellij.navigation.NavigationItem; -import com.intellij.navigation.PsiElementNavigationItem; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; -import com.intellij.psi.meta.PsiMetaOwner; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PsiElementProcessor; -import com.intellij.psi.search.SearchScope; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.io.File; - -/** - * Created by IntelliJ IDEA. - * User: Eugene.Kudelevsky - * Date: Aug 6, 2009 - * Time: 7:08:02 PM - * To change this template use File | Settings | File Templates. - */ - -public class XmlAttributeValueWrapper implements XmlAttributeValue, PsiNamedElement, PsiElementNavigationItem { - private final XmlAttributeValue myWrappee; - private final String myFileName; - private final String myDirName; - - public XmlAttributeValueWrapper(@NotNull XmlAttributeValue wrappeeElement) { - if (!(wrappeeElement instanceof NavigationItem)) { - throw new IllegalArgumentException(); - } - if (!(wrappeeElement instanceof PsiMetaOwner)) { - throw new IllegalArgumentException(); - } - myWrappee = wrappeeElement; - final PsiFile file = getContainingFile(); - myFileName = file != null ? file.getName() : null; - final PsiDirectory dir = file != null ? file.getContainingDirectory() : null; - myDirName = dir != null ? dir.getName() : null; - } - - @Override - @NotNull - public Project getProject() throws PsiInvalidElementAccessException { - return myWrappee.getProject(); - } - - @Override - @NotNull - public Language getLanguage() { - return myWrappee.getLanguage(); - } - - @Override - public PsiManager getManager() { - return myWrappee.getManager(); - } - - @Override - @NotNull - public PsiElement[] getChildren() { - return myWrappee.getChildren(); - } - - @Override - public PsiElement getParent() { - return myWrappee.getParent(); - } - - @Override - @Nullable - public PsiElement getFirstChild() { - return myWrappee.getFirstChild(); - } - - @Override - @Nullable - public PsiElement getLastChild() { - return myWrappee.getLastChild(); - } - - @Override - @Nullable - public PsiElement getNextSibling() { - return myWrappee.getNextSibling(); - } - - @Override - @Nullable - public PsiElement getPrevSibling() { - return myWrappee.getPrevSibling(); - } - - @Override - public PsiFile getContainingFile() throws PsiInvalidElementAccessException { - return myWrappee.getContainingFile(); - } - - @Override - public TextRange getTextRange() { - return myWrappee.getTextRange(); - } - - @Override - public int getStartOffsetInParent() { - return myWrappee.getStartOffsetInParent(); - } - - @Override - public int getTextLength() { - return myWrappee.getTextLength(); - } - - @Override - @Nullable - public PsiElement findElementAt(int offset) { - return myWrappee.findElementAt(offset); - } - - @Override - @Nullable - public PsiReference findReferenceAt(int offset) { - return myWrappee.findReferenceAt(offset); - } - - @Override - public int getTextOffset() { - return myWrappee.getTextOffset(); - } - - @Override - @NonNls - public String getText() { - return myWrappee.getText(); - } - - @Override - @NotNull - public char[] textToCharArray() { - return myWrappee.textToCharArray(); - } - - @Override - public PsiElement getNavigationElement() { - return myWrappee.getNavigationElement(); - } - - @Override - public PsiElement getOriginalElement() { - return myWrappee.getOriginalElement(); - } - - @Override - public boolean textMatches(@NotNull @NonNls CharSequence text) { - return myWrappee.textMatches(text); - } - - @Override - public boolean textMatches(@NotNull PsiElement element) { - return myWrappee.textMatches(element); - } - - @Override - public boolean textContains(char c) { - return myWrappee.textContains(c); - } - - @Override - public void accept(@NotNull PsiElementVisitor visitor) { - myWrappee.accept(visitor); - } - - @Override - public void acceptChildren(@NotNull PsiElementVisitor visitor) { - myWrappee.acceptChildren(visitor); - } - - @NotNull - @Override - public PsiElement copy() { - return myWrappee.copy(); - } - - @Override - public PsiElement add(@NotNull PsiElement element) throws IncorrectOperationException { - return myWrappee.add(element); - } - - @Override - public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { - return myWrappee.addBefore(element, anchor); - } - - @Override - public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { - return myWrappee.addAfter(element, anchor); - } - - @Override - public void checkAdd(@NotNull PsiElement element) throws IncorrectOperationException { - //noinspection deprecation - myWrappee.checkAdd(element); - } - - @Override - public PsiElement addRange(PsiElement first, PsiElement last) throws IncorrectOperationException { - return myWrappee.addRange(first, last); - } - - @Override - public PsiElement addRangeBefore(@NotNull PsiElement first, @NotNull PsiElement last, PsiElement anchor) - throws IncorrectOperationException { - return myWrappee.addRangeBefore(first, last, anchor); - } - - @Override - public PsiElement addRangeAfter(PsiElement first, PsiElement last, PsiElement anchor) throws IncorrectOperationException { - return myWrappee.addRangeAfter(first, last, anchor); - } - - @Override - public void delete() throws IncorrectOperationException { - myWrappee.delete(); - } - - @Override - public void checkDelete() throws IncorrectOperationException { - //noinspection deprecation - myWrappee.checkDelete(); - } - - @Override - public void deleteChildRange(PsiElement first, PsiElement last) throws IncorrectOperationException { - myWrappee.deleteChildRange(first, last); - } - - @NotNull - @Override - public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException { - return myWrappee.replace(newElement); - } - - @Override - public boolean isValid() { - return myWrappee.isValid(); - } - - @Override - public boolean isWritable() { - return myWrappee.isWritable(); - } - - @Override - @Nullable - public PsiReference getReference() { - return myWrappee.getReference(); - } - - @Override - @NotNull - public PsiReference[] getReferences() { - return myWrappee.getReferences(); - } - - @Override - @Nullable - public T getCopyableUserData(Key key) { - return myWrappee.getCopyableUserData(key); - } - - @Override - public void putCopyableUserData(Key key, T value) { - myWrappee.putCopyableUserData(key, value); - } - - @Override - public boolean processDeclarations( - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - @Nullable PsiElement lastParent, - @NotNull PsiElement place - ) { - return myWrappee.processDeclarations(processor, state, lastParent, place); - } - - @Override - @Nullable - public PsiElement getContext() { - return myWrappee.getContext(); - } - - @Override - public boolean isPhysical() { - return myWrappee.isPhysical(); - } - - @Override - @NotNull - public GlobalSearchScope getResolveScope() { - return myWrappee.getResolveScope(); - } - - @Override - @NotNull - public SearchScope getUseScope() { - return myWrappee.getUseScope(); - } - - @Override - @Nullable - public ASTNode getNode() { - return myWrappee.getNode(); - } - - @NonNls - public String toString() { - return myWrappee.toString(); - } - - @Override - public boolean isEquivalentTo(PsiElement another) { - return myWrappee == another || myWrappee.isEquivalentTo(another); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - XmlAttributeValueWrapper that = (XmlAttributeValueWrapper) o; - - if (!myWrappee.equals(that.myWrappee)) return false; - - return true; - } - - @Override - public int hashCode() { - return myWrappee.hashCode(); - } - - @Override - public T getUserData(@NotNull Key key) { - return myWrappee.getUserData(key); - } - - @Override - public void putUserData(@NotNull Key key, @Nullable T value) { - myWrappee.putUserData(key, value); - } - - @Override - public Icon getIcon(int flags) { - return myWrappee.getIcon(flags); - } - - @Override - public String getName() { - return ((NavigationItem) myWrappee).getName(); - } - - @Override - @Nullable - public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { - XmlAttribute attribute = (XmlAttribute) myWrappee.getParent(); - attribute.setValue(name); - return null; - } - - @Override - public ItemPresentation getPresentation() { - return new ItemPresentation() { - @Override - @Nullable - public String getPresentableText() { - String name = ((NavigationItem) myWrappee).getName(); - if (myDirName == null || myFileName == null) { - return name; - } - return name + " (..." + File.separatorChar + myDirName + - File.separatorChar + myFileName + ')'; - } - - @Override - public String getLocationString() { - return null; - } - - @Override - public Icon getIcon(boolean open) { - return null; - } - }; - } - - @Override - public void navigate(boolean requestFocus) { - ((NavigationItem) myWrappee).navigate(requestFocus); - } - - @Override - public boolean canNavigate() { - return ((NavigationItem) myWrappee).canNavigate(); - } - - @Override - public boolean canNavigateToSource() { - return ((NavigationItem) myWrappee).canNavigateToSource(); - } - - @Override - public String getValue() { - return myWrappee.getValue(); - } - - @Override - public TextRange getValueTextRange() { - return myWrappee.getValueTextRange(); - } - - @Override - public boolean processElements(PsiElementProcessor processor, PsiElement place) { - return myWrappee.processElements(processor, place); - } - - @Override - public PsiElement getTargetElement() { - return myWrappee; - } -} - diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt index 659bc87d4dd..b26fd1bda55 100644 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidLayoutXmlFileManager.kt @@ -19,22 +19,47 @@ package org.jetbrains.kotlin.android.synthetic.idea.res import com.android.builder.model.SourceProvider import com.intellij.openapi.module.Module import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.impl.PsiTreeChangePreprocessor +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValueProvider import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.android.synthetic.AndroidConst import org.jetbrains.kotlin.android.synthetic.idea.AndroidXmlVisitor -import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager -import org.jetbrains.kotlin.android.synthetic.res.AndroidModule -import org.jetbrains.kotlin.android.synthetic.res.AndroidVariant -import org.jetbrains.kotlin.android.synthetic.res.AndroidVariantData -import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.android.synthetic.AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH +import org.jetbrains.kotlin.android.synthetic.idea.AndroidPsiTreeChangePreprocessor +import org.jetbrains.kotlin.android.synthetic.res.* +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.project) { - override val androidModule: AndroidModule? by lazy { module.androidFacet?.toAndroidModuleInfo() } - override fun propertyToXmlAttributes(property: KtProperty): List { - val fqPath = property.fqName?.pathSegments() ?: return listOf() + private val moduleData: CachedValue by lazy { + cachedValue(project) { + CachedValueProvider.Result.create(super.getModuleData(), getPsiTreeChangePreprocessor()) + } + } + + override fun getModuleData() = moduleData.value + + private fun getPsiTreeChangePreprocessor(): PsiTreeChangePreprocessor { + return project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor } + } + + override fun doExtractResources(files: List, module: ModuleDescriptor): List { + val widgets = arrayListOf() + val visitor = AndroidXmlVisitor { id, widgetType, attribute -> + widgets += parseAndroidResource(id, widgetType, attribute.valueElement) + } + + files.forEach { it.accept(visitor) } + return widgets + } + + + override fun propertyToXmlAttributes(propertyDescriptor: PropertyDescriptor): List { + val fqPath = propertyDescriptor.fqNameUnsafe.pathSegments() if (fqPath.size <= SYNTHETIC_PACKAGE_PATH_LENGTH) return listOf() fun handle(variantData: AndroidVariantData, defaultVariant: Boolean = false): List? { @@ -44,7 +69,7 @@ public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutX val layoutFiles = variantData[layoutName] ?: return null if (layoutFiles.isEmpty()) return null - val propertyName = property.name + val propertyName = propertyDescriptor.name.asString() val attributes = arrayListOf() val visitor = AndroidXmlVisitor { retId, wClass, valueElement -> @@ -55,7 +80,7 @@ public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutX return attributes } - for (variantData in getLayoutXmlFiles()) { + for (variantData in getModuleData()) { if (variantData.variant.isMainVariant && fqPath.size == SYNTHETIC_PACKAGE_PATH_LENGTH + 2) { handle(variantData, true)?.let { return it } } diff --git a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt new file mode 100644 index 00000000000..591e40e8a2b --- /dev/null +++ b/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDEAndroidPackageFragmentProviderExtension.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2015 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.synthetic.idea.res + +import com.intellij.openapi.module.ModuleServiceManager +import com.intellij.openapi.project.Project +import org.jetbrains.android.facet.AndroidFacet +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager +import org.jetbrains.kotlin.android.synthetic.res.AndroidPackageFragmentProviderExtension +import org.jetbrains.kotlin.idea.caches.resolve.ModuleSourceInfo + +class IDEAndroidPackageFragmentProviderExtension : AndroidPackageFragmentProviderExtension() { + + override fun getLayoutXmlFileManager(project: Project, moduleInfo: ModuleInfo?): AndroidLayoutXmlFileManager? { + val moduleSourceInfo = moduleInfo as? ModuleSourceInfo ?: return null + val module = moduleSourceInfo.module + if (AndroidFacet.getInstance(module) == null) return null + return ModuleServiceManager.getService(module, AndroidLayoutXmlFileManager::class.java) + } +} \ No newline at end of file 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 deleted file mode 100644 index 2f62c34129f..00000000000 --- a/plugins/android-idea-plugin/src/org/jetbrains/kotlin/android/synthetic/idea/res/IDESyntheticFileGenerator.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2010-2015 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.synthetic.idea.res - -import com.intellij.openapi.module.Module -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiFile -import com.intellij.psi.impl.PsiTreeChangePreprocessor -import com.intellij.psi.util.CachedValue -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.res.AndroidResource -import org.jetbrains.kotlin.android.synthetic.res.AndroidWidget -import org.jetbrains.kotlin.android.synthetic.res.SyntheticFileGenerator -import org.jetbrains.kotlin.psi.KtFile - -class IDESyntheticFileGenerator(val module: Module) : SyntheticFileGenerator(module.project) { - - private val cachedJetFiles: CachedValue> by lazy { - cachedValue { - val supportV4 = supportV4Available() - Result.create(generateSyntheticJetFiles(generateSyntheticFiles(true, supportV4)), psiTreeChangePreprocessor) - } - } - - override val layoutXmlFileManager: IDEAndroidLayoutXmlFileManager = IDEAndroidLayoutXmlFileManager(module) - - private val psiTreeChangePreprocessor by lazy { - module.project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor } - } - - public override fun getSyntheticFiles(): List { - if (!checkIfClassExist(AndroidConst.VIEW_FQNAME)) return listOf() - return cachedJetFiles.value - } - - override fun extractLayoutResources(files: List): List { - val widgets = arrayListOf() - val visitor = AndroidXmlVisitor { id, widgetType, attribute -> - widgets += parseAndroidResource(id, widgetType) { tag -> - resolveFqClassNameForView(tag) - } - } - - files.forEach { it.accept(visitor) } - 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 - } -} \ No newline at end of file