Support multi-module configuration in Android plugin

This commit is contained in:
Yan Zhulanow
2014-12-29 14:58:05 +03:00
parent 438d2ee5fa
commit 4f9aba2cdc
48 changed files with 150 additions and 69 deletions
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.psi.JetFile
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.extensions.ExternalDeclarationsProvider import org.jetbrains.jet.extensions.ExternalDeclarationsProvider
import kotlin.platform.platformStatic import kotlin.platform.platformStatic
import com.intellij.openapi.module.Module
public class JvmResolverForModule( public class JvmResolverForModule(
override val lazyResolveSession: ResolveSession, override val lazyResolveSession: ResolveSession,
@@ -60,7 +61,7 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
resolverForProject: ResolverForProject<M, JvmResolverForModule> resolverForProject: ResolverForProject<M, JvmResolverForModule>
): JvmResolverForModule { ): JvmResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent val (syntheticFiles, moduleContentScope) = moduleContent
val filesToAnalyze = getAllFilesToAnalyze(project, syntheticFiles) val filesToAnalyze = getAllFilesToAnalyze(project, moduleInfo, syntheticFiles)
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
project, globalContext.storageManager, filesToAnalyze, project, globalContext.storageManager, filesToAnalyze,
if (moduleInfo.isLibrary) GlobalSearchScope.EMPTY_SCOPE else moduleContentScope if (moduleInfo.isLibrary) GlobalSearchScope.EMPTY_SCOPE else moduleContentScope
@@ -87,10 +88,10 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
override val defaultImports = TopDownAnalyzerFacadeForJVM.DEFAULT_IMPORTS override val defaultImports = TopDownAnalyzerFacadeForJVM.DEFAULT_IMPORTS
override val platformToKotlinClassMap = JavaToKotlinClassMap.INSTANCE override val platformToKotlinClassMap = JavaToKotlinClassMap.INSTANCE
public platformStatic fun getAllFilesToAnalyze(project: Project, baseFiles: Collection<JetFile>): List<JetFile> { public platformStatic fun getAllFilesToAnalyze(project: Project, moduleInfo: ModuleInfo?, baseFiles: Collection<JetFile>): List<JetFile> {
val allFiles = ArrayList(baseFiles) val allFiles = ArrayList(baseFiles)
for (externalDeclarationsProvider in ExternalDeclarationsProvider.getInstances(project)) { for (externalDeclarationsProvider in ExternalDeclarationsProvider.getInstances(project)) {
allFiles.addAll(externalDeclarationsProvider.getExternalDeclarations()) allFiles.addAll(externalDeclarationsProvider.getExternalDeclarations(moduleInfo))
} }
return allFiles return allFiles
} }
@@ -116,7 +116,7 @@ public enum TopDownAnalyzerFacadeForJVM {
@Nullable List<String> moduleIds, @Nullable List<String> moduleIds,
@Nullable IncrementalCacheProvider incrementalCacheProvider @Nullable IncrementalCacheProvider incrementalCacheProvider
) { ) {
List<JetFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, files); List<JetFile> allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, null, files);
FileBasedDeclarationProviderFactory providerFactory = FileBasedDeclarationProviderFactory providerFactory =
new FileBasedDeclarationProviderFactory(topDownAnalysisParameters.getStorageManager(), allFiles); new FileBasedDeclarationProviderFactory(topDownAnalysisParameters.getStorageManager(), allFiles);
@@ -17,6 +17,7 @@
package org.jetbrains.jet.extensions package org.jetbrains.jet.extensions
import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.analyzer.ModuleInfo
public trait ExternalDeclarationsProvider { public trait ExternalDeclarationsProvider {
class object : ProjectExtensionDescriptor<ExternalDeclarationsProvider>( class object : ProjectExtensionDescriptor<ExternalDeclarationsProvider>(
@@ -24,5 +25,5 @@ public trait ExternalDeclarationsProvider {
javaClass<ExternalDeclarationsProvider>() javaClass<ExternalDeclarationsProvider>()
) )
public fun getExternalDeclarations(): Collection<JetFile> public fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile>
} }
@@ -32,12 +32,14 @@ import java.io.StringWriter
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.PsiComment import com.intellij.psi.PsiComment
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.jet.analyzer.ModuleInfo
public fun JetPsiFactory(project: Project?): JetPsiFactory = JetPsiFactory(project!!) public fun JetPsiFactory(project: Project?): JetPsiFactory = JetPsiFactory(project!!)
public fun JetPsiFactory(contextElement: JetElement): JetPsiFactory = JetPsiFactory(contextElement.getProject()) public fun JetPsiFactory(contextElement: JetElement): JetPsiFactory = JetPsiFactory(contextElement.getProject())
public var JetFile.doNotAnalyze: String? by UserDataProperty(Key.create("DO_NOT_ANALYZE")) public var JetFile.doNotAnalyze: String? by UserDataProperty(Key.create("DO_NOT_ANALYZE"))
public var JetFile.analysisContext: PsiElement? by UserDataProperty(Key.create("ANALYSIS_CONTEXT")) public var JetFile.analysisContext: PsiElement? by UserDataProperty(Key.create("ANALYSIS_CONTEXT"))
public var JetFile.moduleInfo: ModuleInfo? by UserDataProperty(Key.create("MODULE_INFO"))
public class JetPsiFactory(private val project: Project) { public class JetPsiFactory(private val project: Project) {
@@ -50,6 +50,7 @@ import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor
import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaClassDescriptor
import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.analyzer.ModuleInfo
public object AndroidConfigurationKeys { public object AndroidConfigurationKeys {
@@ -79,8 +80,8 @@ public class AndroidCommandLineProcessor : CommandLineProcessor {
} }
} }
public class AndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider { public class CliAndroidDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
override fun getExternalDeclarations(): Collection<JetFile> { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
val parser = ServiceManager.getService<AndroidUIXmlProcessor>(project, javaClass<AndroidUIXmlProcessor>()) val parser = ServiceManager.getService<AndroidUIXmlProcessor>(project, javaClass<AndroidUIXmlProcessor>())
return emptyOrSingletonList(parser?.parseToPsi(project)) return emptyOrSingletonList(parser?.parseToPsi(project))
} }
@@ -219,7 +220,7 @@ public class AndroidComponentRegistrar : ComponentRegistrar {
val androidManifest = configuration.get(AndroidConfigurationKeys.ANDROID_MANIFEST) val androidManifest = configuration.get(AndroidConfigurationKeys.ANDROID_MANIFEST)
project.registerService(javaClass<AndroidUIXmlProcessor>(), CliAndroidUIXmlProcessor(project, androidResPath, androidManifest)) project.registerService(javaClass<AndroidUIXmlProcessor>(), CliAndroidUIXmlProcessor(project, androidResPath, androidManifest))
ExternalDeclarationsProvider.registerExtension(project, AndroidDeclarationsProvider(project)) ExternalDeclarationsProvider.registerExtension(project, CliAndroidDeclarationsProvider(project))
ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegen()) ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegen())
} }
} }
@@ -47,6 +47,8 @@ import java.util.Queue
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.resolve.android.AndroidConst.* import org.jetbrains.jet.lang.resolve.android.AndroidConst.*
import org.jetbrains.jet.analyzer.ModuleInfo
import com.intellij.openapi.module.Module
public abstract class AndroidUIXmlProcessor(protected val project: Project) { public abstract class AndroidUIXmlProcessor(protected val project: Project) {
@@ -1,4 +1,4 @@
package com.myapp package kotlinx.android.synthetic.layout
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
@@ -1,4 +1,4 @@
package com.myapp package kotlinx.android.synthetic.layout
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
@@ -1,4 +1,4 @@
package com.myapp package kotlinx.android.synthetic.layout
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
@@ -16,15 +16,3 @@ val Activity.password: EditText
val Activity.login: Button val Activity.login: Button
get() = findViewById(0) as Button get() = findViewById(0) as Button
val Activity.frameLayout: FrameLayout
get() = findViewById(0) as FrameLayout
val Activity.passwordField: TextView
get() = findViewById(0) as TextView
val Activity.passwordCaption: EditText
get() = findViewById(0) as EditText
val Activity.loginButton: Button
get() = findViewById(0) as Button
@@ -1,4 +1,4 @@
package com.myapp package kotlinx.android.synthetic.layout
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
@@ -1,4 +1,4 @@
package com.myapp package kotlinx.android.synthetic.layout
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
@@ -4,6 +4,7 @@ import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import org.my.cool.MyButton import org.my.cool.MyButton
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -4,6 +4,7 @@ import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import org.my.cool.MyButton import org.my.cool.MyButton
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -4,6 +4,7 @@ import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import org.my.cool.MyButton import org.my.cool.MyButton
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -4,6 +4,7 @@ import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import org.my.cool.MyButton import org.my.cool.MyButton
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -3,6 +3,8 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import kotlinx.android.synthetic.layout.*
import kotlinx.android.synthetic.layout1.*
class R { class R {
class id { class id {
@@ -3,6 +3,8 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import kotlinx.android.synthetic.layout.*
import kotlinx.android.synthetic.layout1.*
class R { class R {
class id { class id {
@@ -3,6 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -3,6 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import kotlinx.android.synthetic.layout.*
class R { class R {
class id { class id {
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton val button = this.MyButton
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton val button = this.MyButton
@@ -1,6 +1,8 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
import kotlinx.android.synthetic.layout1.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.login val button = this.login
@@ -3,7 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import java.io.File import java.io.File
import kotlinx.android.synthetic.layout.*
public class MyActivity : Activity() { public class MyActivity : Activity() {
{login} {login}
@@ -28,13 +28,14 @@ import org.jetbrains.kotlin.android.AndroidExpressionCodegen
import org.jetbrains.jet.config.CompilerConfiguration import org.jetbrains.jet.config.CompilerConfiguration
import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.jet.lang.resolve.android.CliAndroidUIXmlProcessor import org.jetbrains.jet.lang.resolve.android.CliAndroidUIXmlProcessor
import org.jetbrains.jet.analyzer.ModuleInfo
private class AndroidTestDeclarationsProvider( private class AndroidTestExternalDeclarationsProvider(
val project: Project, val project: Project,
val resPath: String, val resPath: String,
val manifestPath: String val manifestPath: String
) : ExternalDeclarationsProvider { ) : ExternalDeclarationsProvider {
override fun getExternalDeclarations(): Collection<JetFile> { override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
val parser = CliAndroidUIXmlProcessor(project, resPath, manifestPath) val parser = CliAndroidUIXmlProcessor(project, resPath, manifestPath)
return emptyOrSingletonList(parser.parseToPsi(project)) return emptyOrSingletonList(parser.parseToPsi(project))
} }
@@ -49,7 +50,7 @@ fun UsefulTestCase.createAndroidTestEnvironment(
configuration.put(AndroidConfigurationKeys.ANDROID_MANIFEST, manifestPath) configuration.put(AndroidConfigurationKeys.ANDROID_MANIFEST, manifestPath)
val myEnvironment = JetCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) val myEnvironment = JetCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
val project = myEnvironment.getProject() val project = myEnvironment.getProject()
ExternalDeclarationsProvider.registerExtension(project, AndroidTestDeclarationsProvider(project, resPath, manifestPath)) ExternalDeclarationsProvider.registerExtension(project, AndroidTestExternalDeclarationsProvider(project, resPath, manifestPath))
ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegen()) ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegen())
return myEnvironment return myEnvironment
} }
@@ -12,7 +12,7 @@
<depends optional="false">org.jetbrains.android</depends> <depends optional="false">org.jetbrains.android</depends>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<projectService serviceInterface="org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor" <moduleService serviceInterface="org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor"
serviceImplementation="org.jetbrains.jet.plugin.android.IDEAndroidUIXmlProcessor"/> serviceImplementation="org.jetbrains.jet.plugin.android.IDEAndroidUIXmlProcessor"/>
<compileServer.plugin classpath="jps/kotlin-android-extensions-jps.jar;android-compiler-plugin.jar"/> <compileServer.plugin classpath="jps/kotlin-android-extensions-jps.jar;android-compiler-plugin.jar"/>
<gotoDeclarationHandler implementation="org.jetbrains.jet.plugin.android.AndroidGotoDeclarationHandler"/> <gotoDeclarationHandler implementation="org.jetbrains.jet.plugin.android.AndroidGotoDeclarationHandler"/>
@@ -22,7 +22,7 @@
</extensions> </extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin"> <extensions defaultExtensionNs="org.jetbrains.kotlin">
<externalDeclarationsProvider implementation="org.jetbrains.kotlin.android.AndroidDeclarationsProvider"/> <externalDeclarationsProvider implementation="org.jetbrains.jet.plugin.android.IDEAndroidExternalDeclarationsProvider"/>
<expressionCodegenExtension implementation="org.jetbrains.kotlin.android.AndroidExpressionCodegen"/> <expressionCodegenExtension implementation="org.jetbrains.kotlin.android.AndroidExpressionCodegen"/>
<findUsagesHandlerDecorator implementation="org.jetbrains.jet.plugin.android.AndroidFindUsageHandlerDecorator"/> <findUsagesHandlerDecorator implementation="org.jetbrains.jet.plugin.android.AndroidFindUsageHandlerDecorator"/>
<simpleNameReferenceExtension implementation="org.jetbrains.jet.plugin.android.AndroidSimpleNameReferenceExtension"/> <simpleNameReferenceExtension implementation="org.jetbrains.jet.plugin.android.AndroidSimpleNameReferenceExtension"/>
@@ -30,6 +30,9 @@ import com.intellij.psi.impl.light.LightElement
import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.xml.XmlAttribute
import org.jetbrains.jet.lang.resolve.android.isRClassField import org.jetbrains.jet.lang.resolve.android.isRClassField
import com.intellij.psi.PsiField import com.intellij.psi.PsiField
import com.intellij.openapi.module.ModuleServiceManager
import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo
public class AndroidGotoDeclarationHandler : GotoDeclarationHandler { public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? { override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
@@ -41,10 +44,13 @@ public class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
} }
else null else null
if (name != null) { if (name != null) {
val parser = ServiceManager.getService(sourceElement.getProject(), javaClass<AndroidUIXmlProcessor>()) val moduleInfo = sourceElement.getModuleInfo()
val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute if (moduleInfo !is ModuleSourceInfo) return null
val parser = ModuleServiceManager.getService(moduleInfo.module, javaClass<AndroidUIXmlProcessor>())
val psiElement = parser.resourceManager.idToXmlAttribute(name) as? XmlAttribute
if (psiElement != null) { if (psiElement != null) {
return array(psiElement.getValueElement()!!) return array(psiElement.getValueElement())
} }
} }
} }
@@ -30,6 +30,12 @@ import org.jetbrains.android.util.AndroidResourceUtil
import com.intellij.psi.xml.XmlAttribute import com.intellij.psi.xml.XmlAttribute
import com.intellij.psi.impl.light.LightElement import com.intellij.psi.impl.light.LightElement
import org.jetbrains.jet.lang.resolve.android.isRClassField import org.jetbrains.jet.lang.resolve.android.isRClassField
import com.intellij.openapi.module.ModuleServiceManager
import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo
import com.intellij.openapi.module.Module
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.moduleInfo
public class AndroidRenameProcessor : RenamePsiElementProcessor() { public class AndroidRenameProcessor : RenamePsiElementProcessor() {
override fun canProcessElement(element: PsiElement): Boolean { override fun canProcessElement(element: PsiElement): Boolean {
@@ -39,9 +45,22 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
isRClassField(element) isRClassField(element)
} }
private fun PsiElement.getModule(): Module? {
val moduleInfo = getModuleInfo()
if (moduleInfo is ModuleSourceInfo) return moduleInfo.module
val file = getContainingFile() as? JetFile
if (file != null) {
val moduleInfo = file.moduleInfo
if (moduleInfo is ModuleSourceInfo) return moduleInfo.module
}
return null
}
override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) { override fun prepareRenaming(element: PsiElement?, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
if (element?.namedUnwrappedElement is JetProperty) { if (element != null && element.namedUnwrappedElement is JetProperty) {
renameSyntheticProperty(element!!.namedUnwrappedElement as JetProperty, newName, allRenames, scope) renameSyntheticProperty(element.namedUnwrappedElement as JetProperty, newName, allRenames, scope)
} }
else if (element is XmlAttributeValue) { else if (element is XmlAttributeValue) {
renameAttributeValue(element, newName, allRenames, scope) renameAttributeValue(element, newName, allRenames, scope)
@@ -52,8 +71,11 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
} }
private fun renameSyntheticProperty(jetProperty: JetProperty, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) { private fun renameSyntheticProperty(jetProperty: JetProperty, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
val oldName = jetProperty.getName()!! val oldName = jetProperty.getName()
val processor = ServiceManager.getService(jetProperty.getProject(), javaClass<AndroidUIXmlProcessor>()) val module = jetProperty.getModule()
if (module == null) return
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())
val resourceManager = processor!!.resourceManager val resourceManager = processor!!.resourceManager
val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute val attr = resourceManager.idToXmlAttribute(oldName) as XmlAttribute
allRenames[XmlAttributeValueWrapper(attr.getValueElement()!!)] = resourceManager.nameToIdDeclaration(newName!!) allRenames[XmlAttributeValueWrapper(attr.getValueElement()!!)] = resourceManager.nameToIdDeclaration(newName!!)
@@ -64,8 +86,11 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
} }
private fun renameAttributeValue(attribute: XmlAttributeValue, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) { private fun renameAttributeValue(attribute: XmlAttributeValue, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
val element1 = LazyValueResourceElementWrapper.computeLazyElement(attribute); val element1 = LazyValueResourceElementWrapper.computeLazyElement(attribute)
val processor = ServiceManager.getService(attribute.getProject(), javaClass<AndroidUIXmlProcessor>()) val module = attribute.getModule()
if (module == null) return
val processor = ModuleServiceManager.getService(module, javaClass<AndroidUIXmlProcessor>())
if (element1 == null) return if (element1 == null) return
val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()!!) val oldPropName = AndroidResourceUtil.getResourceNameByReferenceText(attribute.getValue()!!)
val newPropName = processor!!.resourceManager.idToName(newName!!) val newPropName = processor!!.resourceManager.idToName(newName!!)
@@ -81,7 +106,7 @@ public class AndroidRenameProcessor : RenamePsiElementProcessor() {
} }
private fun renameLightClassField(field: LightElement, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) { private fun renameLightClassField(field: LightElement, newName: String?, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
val oldName = field.getName()!! val oldName = field.getName()
val processor = ServiceManager.getService(field.getProject(), javaClass<AndroidUIXmlProcessor>()) val processor = ServiceManager.getService(field.getProject(), javaClass<AndroidUIXmlProcessor>())
renameSyntheticProperties(allRenames, newName!!, oldName, processor!!) renameSyntheticProperties(allRenames, newName!!, oldName, processor!!)
} }
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2014 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.jet.plugin.android
import com.intellij.openapi.project.Project
import org.jetbrains.jet.extensions.ExternalDeclarationsProvider
import org.jetbrains.jet.analyzer.ModuleInfo
import org.jetbrains.jet.lang.psi.JetFile
import com.intellij.openapi.components.ServiceManager
import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor
import org.jetbrains.jet.plugin.caches.resolve.ModuleSourceInfo
import com.intellij.openapi.module.ModuleServiceManager
import org.jetbrains.jet.lang.psi.moduleInfo
public class IDEAndroidExternalDeclarationsProvider(private val project: Project) : ExternalDeclarationsProvider {
override fun getExternalDeclarations(moduleInfo: ModuleInfo?): Collection<JetFile> {
if (moduleInfo !is ModuleSourceInfo) return listOf()
val module = moduleInfo.module
val parser = ModuleServiceManager.getService<AndroidUIXmlProcessor>(module, javaClass<AndroidUIXmlProcessor>())
val syntheticFile = parser.parseToPsi(project)
syntheticFile?.moduleInfo = moduleInfo
return if (syntheticFile != null) listOf(syntheticFile) else listOf()
}
}
@@ -27,8 +27,9 @@ import org.jetbrains.jet.lang.resolve.android.AndroidManifest
import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.module.ModuleManager
import java.util.ArrayList import java.util.ArrayList
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.module.Module
public class IDEAndroidResourceManager(project: Project, searchPath: String?) : AndroidResourceManagerBase(project, searchPath) { public class IDEAndroidResourceManager(val module: Module, searchPath: String?) : AndroidResourceManagerBase(module.getProject(), searchPath) {
override fun getLayoutXmlFiles(): Collection<PsiFile> { override fun getLayoutXmlFiles(): Collection<PsiFile> {
val directories = getAndroidFacet()?.getAllResourceDirectories() ?: listOf() val directories = getAndroidFacet()?.getAllResourceDirectories() ?: listOf()
@@ -38,17 +39,13 @@ public class IDEAndroidResourceManager(project: Project, searchPath: String?) :
} }
private fun getAndroidFacet(): AndroidFacet? { private fun getAndroidFacet(): AndroidFacet? {
for (module in ModuleManager.getInstance(project).getModules()) { return AndroidFacet.getInstance(module)
val facet = AndroidFacet.getInstance(module)
if (facet != null) return facet
}
return null
} }
override fun readManifest(): AndroidManifest { override fun readManifest(): AndroidManifest {
val facet = getAndroidFacet() val facet = getAndroidFacet()
val attributeValue = facet?.getManifest()!!.getPackage() val attributeValue = facet?.getManifest()!!.getPackage()
return AndroidManifest(attributeValue!!.getRawText()!!) return AndroidManifest(attributeValue.getRawText())
} }
override fun idToXmlAttribute(id: String): PsiElement? { override fun idToXmlAttribute(id: String): PsiElement? {
@@ -25,13 +25,14 @@ import org.jetbrains.jet.lang.resolve.android.KotlinStringWriter
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.jet.lang.resolve.android.CliAndroidResourceManager import org.jetbrains.jet.lang.resolve.android.CliAndroidResourceManager
import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager import org.jetbrains.jet.lang.resolve.android.AndroidResourceManager
import com.intellij.openapi.module.Module
class IDEAndroidUIXmlProcessor(project: Project) : AndroidUIXmlProcessor(project) { class IDEAndroidUIXmlProcessor(val module: Module) : AndroidUIXmlProcessor(module.getProject()) {
override val searchPath: String? = project.getBasePath() + "/res/layout/" override val searchPath: String? = project.getBasePath() + "/res/layout/"
override var androidAppPackage: String = "" override var androidAppPackage: String = ""
get() = resourceManager.readManifest()._package get() = resourceManager.readManifest()._package
override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(project, searchPath) override val resourceManager: IDEAndroidResourceManager = IDEAndroidResourceManager(module, searchPath)
override fun parseSingleFileImpl(file: PsiFile): String { override fun parseSingleFileImpl(file: PsiFile): String {
val ids: MutableCollection<AndroidWidget> = ArrayList() val ids: MutableCollection<AndroidWidget> = ArrayList()
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyBu<caret> val button = this.MyBu<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyBu<caret> val button = this.MyBu<caret>
@@ -1,7 +1,8 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
import kotlinx.android.synthetic.layout1.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = log<caret> val button = log<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.login<caret> val button = this.login<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.login<caret> val button = this.login<caret>
@@ -3,7 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import java.io.File import java.io.File
import kotlinx.android.synthetic.layout.*
public class MyActivity : Activity() { public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {} override fun onCreate(savedInstanceState: Bundle?) {}
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.login<caret> val button = this.login<caret>
@@ -3,7 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import java.io.File import java.io.File
import kotlinx.android.synthetic.layout.*
public class MyActivity : Activity() { public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {} override fun onCreate(savedInstanceState: Bundle?) {}
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.MyButton<caret> val button = this.MyButton<caret>
@@ -1,7 +1,7 @@
package com.myapp package com.myapp
import android.app.Activity import android.app.Activity
import kotlinx.android.synthetic.layout.*
class MyActivity: Activity() { class MyActivity: Activity() {
val button = this.login<caret> val button = this.login<caret>
@@ -3,7 +3,7 @@ package com.myapp
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import java.io.File import java.io.File
import kotlinx.android.synthetic.layout.*
public class MyActivity : Activity() { public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {} override fun onCreate(savedInstanceState: Bundle?) {}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.plugin.android.TestConst
import org.jetbrains.jet.plugin.PluginTestCaseBase import org.jetbrains.jet.plugin.PluginTestCaseBase
import org.jetbrains.kotlin.android.AndroidConfigurationKeys import org.jetbrains.kotlin.android.AndroidConfigurationKeys
import org.jetbrains.jet.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.jet.cli.jvm.compiler.EnvironmentConfigFiles
import com.intellij.openapi.module.ModuleManager
public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() { public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() {
public fun doTest(path: String) { public fun doTest(path: String) {
@@ -35,7 +36,7 @@ public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase()
project.putUserData(TestConst.TESTDATA_PATH, path) project.putUserData(TestConst.TESTDATA_PATH, path)
myFixture!!.copyDirectoryToProject(getResDir()!!, "res") myFixture!!.copyDirectoryToProject(getResDir()!!, "res")
val cliParser = CliAndroidUIXmlProcessor(project, path + getResDir() + "/layout/", path + "../AndroidManifest.xml") val cliParser = CliAndroidUIXmlProcessor(project, path + getResDir() + "/layout/", path + "../AndroidManifest.xml")
val ideParser = IDEAndroidUIXmlProcessor(project) val ideParser = IDEAndroidUIXmlProcessor(ModuleManager.getInstance(project).getModules()[0])
val cliResult = cliParser.parseToPsi(project)!!.getText() val cliResult = cliParser.parseToPsi(project)!!.getText()
val ideResult = ideParser.parseToPsi(project)!!.getText() val ideResult = ideParser.parseToPsi(project)!!.getText()
@@ -3,6 +3,8 @@ package com.example.myapp
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import kotlinx.android.synthetic.main.*
public class MyActivity : Activity() { public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)