Support Android variants in IDE
This commit is contained in:
+11
-6
@@ -76,10 +76,10 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl
|
||||
|
||||
if (module != null) {
|
||||
val resourceManager = AndroidLayoutXmlFileManager.getInstance(module) ?: return false
|
||||
val resDirectories = resourceManager.getModuleResDirectories()
|
||||
val resDirectories = resourceManager.getAllModuleResDirectories()
|
||||
val baseDirectory = xmlFile.parent?.parent?.virtualFile
|
||||
|
||||
if (baseDirectory in resDirectories && xmlFile.isLayoutXmlFile()) {
|
||||
if (baseDirectory != null && baseDirectory in resDirectories && xmlFile.isLayoutXmlFile()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -95,11 +95,16 @@ public class AndroidPsiTreeChangePreprocessor : PsiTreeChangePreprocessor, Simpl
|
||||
}
|
||||
}
|
||||
|
||||
private fun AndroidLayoutXmlFileManager.getModuleResDirectories(): List<VirtualFile> {
|
||||
val info = androidModuleInfo ?: return listOf()
|
||||
|
||||
private fun AndroidLayoutXmlFileManager.getAllModuleResDirectories(): List<VirtualFile> {
|
||||
val module = androidModule ?: return listOf()
|
||||
val fileManager = VirtualFileManager.getInstance()
|
||||
return info.resDirectories.map { fileManager.findFileByUrl("file://$it") }.filterNotNull()
|
||||
|
||||
return module.variants.fold(arrayListOf<VirtualFile>()) { list, variant ->
|
||||
for (dir in variant.resDirectories) {
|
||||
fileManager.findFileByUrl("file://$dir")?.let { list += it }
|
||||
}
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiFile.isLayoutXmlFile(): Boolean {
|
||||
|
||||
+38
-16
@@ -16,47 +16,69 @@
|
||||
|
||||
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 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.AndroidModuleInfo
|
||||
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
|
||||
|
||||
public class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.project) {
|
||||
|
||||
override val androidModuleInfo: AndroidModuleInfo? by lazy { module.androidFacet?.toAndroidModuleInfo() }
|
||||
override val androidModule: AndroidModule? by lazy { module.androidFacet?.toAndroidModuleInfo() }
|
||||
|
||||
override fun propertyToXmlAttributes(property: KtProperty): List<PsiElement> {
|
||||
val fqPath = property.fqName?.pathSegments() ?: return listOf()
|
||||
if (fqPath.size() <= AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH) return listOf()
|
||||
if (fqPath.size <= SYNTHETIC_PACKAGE_PATH_LENGTH) return listOf()
|
||||
|
||||
val layoutPackageName = fqPath[AndroidConst.SYNTHETIC_PACKAGE_PATH_LENGTH].asString()
|
||||
val layoutFiles = getLayoutXmlFiles()[layoutPackageName]
|
||||
if (layoutFiles == null || layoutFiles.isEmpty()) return listOf()
|
||||
fun handle(variantData: AndroidVariantData, defaultVariant: Boolean = false): List<PsiElement>? {
|
||||
val layoutNamePosition = SYNTHETIC_PACKAGE_PATH_LENGTH + (if (defaultVariant) 0 else 1)
|
||||
val layoutName = fqPath[layoutNamePosition].asString()
|
||||
|
||||
val propertyName = property.name
|
||||
val layoutFiles = variantData[layoutName] ?: return null
|
||||
if (layoutFiles.isEmpty()) return null
|
||||
|
||||
val attributes = arrayListOf<PsiElement>()
|
||||
val visitor = AndroidXmlVisitor { retId, wClass, valueElement ->
|
||||
if (retId == propertyName) attributes.add(valueElement)
|
||||
val propertyName = property.name
|
||||
|
||||
val attributes = arrayListOf<PsiElement>()
|
||||
val visitor = AndroidXmlVisitor { retId, wClass, valueElement ->
|
||||
if (retId == propertyName) attributes.add(valueElement)
|
||||
}
|
||||
|
||||
layoutFiles.forEach { it.accept(visitor) }
|
||||
return attributes
|
||||
}
|
||||
|
||||
layoutFiles.forEach { it.accept(visitor) }
|
||||
return attributes
|
||||
for (variantData in getLayoutXmlFiles()) {
|
||||
if (variantData.variant.isMainVariant && fqPath.size == SYNTHETIC_PACKAGE_PATH_LENGTH + 2) {
|
||||
handle(variantData, true)?.let { return it }
|
||||
}
|
||||
else if (fqPath[SYNTHETIC_PACKAGE_PATH_LENGTH].asString() == variantData.variant.name) {
|
||||
handle(variantData)?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
return listOf()
|
||||
}
|
||||
|
||||
private val Module.androidFacet: AndroidFacet?
|
||||
get() = AndroidFacet.getInstance(this)
|
||||
|
||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModuleInfo? {
|
||||
val applicationPackage = manifest?.getPackage()?.toString()
|
||||
val mainResDirectories = allResourceDirectories.map { it.path }
|
||||
private fun SourceProvider.toVariant() = AndroidVariant(name, resDirectories.map { it.absolutePath })
|
||||
|
||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModule? {
|
||||
val applicationPackage = manifest?.`package`?.toString()
|
||||
|
||||
return if (applicationPackage != null) {
|
||||
AndroidModuleInfo(applicationPackage, mainResDirectories)
|
||||
val mainVariant = mainSourceProvider.toVariant()
|
||||
val flavorVariants = flavorSourceProviders?.map { it.toVariant() } ?: listOf()
|
||||
AndroidModule(applicationPackage, listOf(mainVariant) + flavorVariants)
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyBu<caret>
|
||||
|
||||
plugins/android-idea-plugin/testData/android/completion/fqNameInAttrFragment/fqNameInAttrFragment.kt
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyBu<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyBu<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyBu<caret>
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.layout1.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
import kotlinx.android.synthetic.main.layout1.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = log<caret>
|
||||
|
||||
Vendored
+2
-2
@@ -1,8 +1,8 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.layout1.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
import kotlinx.android.synthetic.main.layout1.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = log<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.login<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.login<caret>
|
||||
|
||||
plugins/android-idea-plugin/testData/android/completion/propertiesSimpleView/propertiesSimpleView.kt
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.layout.view.*
|
||||
import kotlinx.android.synthetic.main.layout.view.*
|
||||
|
||||
fun View.a() {
|
||||
val button = this.login<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
plugins/android-idea-plugin/testData/android/findUsages/fqNameInAttrFragment/fqNameInAttrFragment.kt
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.login<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.login<caret>
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.myapp
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyFragemnt : Fragment() {
|
||||
override fun onResume() {}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.layout.view.*
|
||||
import kotlinx.android.synthetic.main.layout.view.*
|
||||
|
||||
fun View.a() {
|
||||
val button = login<caret>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package com.myapp
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.login<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.login<caret>
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.myapp
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyFragment : Fragment() {
|
||||
override fun onResume() {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.layout.view.*
|
||||
import kotlinx.android.synthetic.main.layout.view.*
|
||||
|
||||
fun View.a() {
|
||||
val button = login<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.MyButton<caret>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Activity
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity: Activity() {
|
||||
val button = this.login<caret>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyFragment: Fragment() {
|
||||
val button = this.login<caret>
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.myapp
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyActivity : Activity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package com.myapp
|
||||
|
||||
import android.app.Fragment
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.layout.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
public class MyFragment : Fragment() {
|
||||
override fun onResume() {}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.myapp
|
||||
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.layout.view.*
|
||||
import kotlinx.android.synthetic.main.layout.view.*
|
||||
|
||||
fun View.a() {
|
||||
val button = login<caret>
|
||||
|
||||
+5
-4
@@ -19,20 +19,21 @@ package org.jetbrains.kotlin.android
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import org.jetbrains.kotlin.android.synthetic.idea.TestConst
|
||||
import org.jetbrains.kotlin.android.synthetic.idea.res.IDESyntheticFileGenerator
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidVariant
|
||||
import org.jetbrains.kotlin.android.synthetic.res.CliSyntheticFileGenerator
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
public abstract class AbstractParserResultEqualityTest : KotlinAndroidTestCase() {
|
||||
public fun doTest(path: String) {
|
||||
val project = myFixture.getProject()
|
||||
val project = myFixture.project
|
||||
project.putUserData(TestConst.TESTDATA_PATH, path)
|
||||
val resDirs = getResourceDirs(path).map {
|
||||
myFixture.copyDirectoryToProject(it.name, it.name)
|
||||
"$path${it.name}/"
|
||||
}
|
||||
|
||||
val cliParser = CliSyntheticFileGenerator(project, "$path../AndroidManifest.xml", resDirs)
|
||||
val ideParser = IDESyntheticFileGenerator(ModuleManager.getInstance(project).getModules()[0])
|
||||
val variants = listOf(AndroidVariant.createMainVariant(resDirs))
|
||||
val cliParser = CliSyntheticFileGenerator(project, "$path../AndroidManifest.xml", variants)
|
||||
val ideParser = IDESyntheticFileGenerator(ModuleManager.getInstance(project).modules[0])
|
||||
|
||||
val cliResult = cliParser.getSyntheticFiles().joinToString("\n\n")
|
||||
val ideResult = ideParser.getSyntheticFiles().joinToString("\n\n")
|
||||
|
||||
Reference in New Issue
Block a user