mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 19:02:13 +07:00
[gradle] IDEA-197590: make root project reference span over the colon
- in GradleProjectSymbol empty qualified name means root project; - update equals/hashCode in GradleProjectSymbol; - make naming consistent. GitOrigin-RevId: ce249833d126e3fbc353e7d1df17eff71117b250
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cfb368a902
commit
fa8e231994
@@ -13,46 +13,38 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals
|
||||
|
||||
@Internal
|
||||
class GradleProjectReference(
|
||||
private val literal: GrLiteral,
|
||||
private val range: TextRange,
|
||||
private val projectPath: List<String>
|
||||
private val myElement: GrLiteral,
|
||||
private val myRange: TextRange,
|
||||
private val myQualifiedName: List<String>
|
||||
) : SingleTargetReference(), PsiCompletableReference {
|
||||
|
||||
init {
|
||||
require(projectPath.isNotEmpty())
|
||||
}
|
||||
override fun getElement(): PsiElement = myElement
|
||||
|
||||
private val projectPathString = projectPath.joinToString(":")
|
||||
|
||||
override fun getElement(): PsiElement = literal
|
||||
|
||||
override fun getRangeInElement(): TextRange = range
|
||||
override fun getRangeInElement(): TextRange = myRange
|
||||
|
||||
override fun resolveSingleTarget(): Symbol? {
|
||||
val gradleProject = GradleExtensionsSettings.getRootProject(literal) ?: return null
|
||||
val rootProjectPath = GradleExtensionsSettings.getRootProjectPath(literal) ?: return null
|
||||
if (projectPathString in gradleProject.extensions) {
|
||||
return GradleProjectSymbol(projectPath, rootProjectPath)
|
||||
val gradleProject = GradleExtensionsSettings.getRootProject(myElement) ?: return null
|
||||
val rootProjectPath = GradleExtensionsSettings.getRootProjectPath(myElement) ?: return null
|
||||
if (GradleProjectSymbol.qualifiedName(myQualifiedName) in gradleProject.extensions) {
|
||||
return GradleProjectSymbol(myQualifiedName, rootProjectPath)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* This could be much easier if we could query list of sub-projects by project fqn.
|
||||
* This could've been much easier if we could query list of sub-projects by project fqn.
|
||||
*/
|
||||
override fun getCompletionVariants(): Collection<Any> {
|
||||
val gradleProject: GradleProject = GradleExtensionsSettings.getRootProject(literal) ?: return emptyList()
|
||||
val allProjectFqns: Set<String> = gradleProject.extensions.keys
|
||||
val parentProjectFqn: List<String> = projectPath // ["com", "IntellijIdeaRulezzz"]
|
||||
.run { take(size - 1) } // ["com"]
|
||||
val parentProjectPrefix: String = parentProjectFqn.joinToString("") { "$it:" } // "com:"
|
||||
val gradleProject: GradleProject = GradleExtensionsSettings.getRootProject(myElement) ?: return emptyList()
|
||||
val parentProjectFqn: List<String> = myQualifiedName.dropLast(1) // ["com", "foo", "IntellijIdeaRulezzz "] -> ["com", "foo"]
|
||||
val parentProjectPrefix: String = parentProjectFqn.joinToString(separator = "", postfix = ":") { ":$it" } // ":com:foo:"
|
||||
val result = LinkedHashSet<String>()
|
||||
for (projectFqn in allProjectFqns) { // "com:foo:bar"
|
||||
for (projectFqn in gradleProject.extensions.keys) { // let's say there is ":com:foo:bar:baz" among keys
|
||||
if (!projectFqn.startsWith(parentProjectPrefix)) {
|
||||
continue
|
||||
}
|
||||
val relativeFqn = projectFqn.removePrefix(parentProjectPrefix) // "foo:bar"
|
||||
val childProjectName = relativeFqn.split(':').firstOrNull() // "foo"
|
||||
val relativeFqn = projectFqn.removePrefix(parentProjectPrefix) // "bar:baz"
|
||||
val childProjectName = relativeFqn.split(':').firstOrNull() // "bar"
|
||||
if (childProjectName.isNullOrEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.intellij.model.search.SearchRequest
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.ElementManipulators
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral
|
||||
@@ -47,10 +46,22 @@ class GradleProjectReferenceProvider : PsiSymbolReferenceProvider {
|
||||
if (!value.startsWith(":")) {
|
||||
return emptyList()
|
||||
}
|
||||
val path = value.split(":")
|
||||
val result = SmartList<PsiSymbolReference>()
|
||||
if (value.toString() == ":") {
|
||||
// in this special case we want the root project reference to span over the colon symbol
|
||||
return listOf(GradleProjectReference(element, rangeInHost, emptyList()))
|
||||
}
|
||||
|
||||
val path = value.split(":").drop(1) // drop first empty string
|
||||
val result = ArrayList<PsiSymbolReference>(path.size + 1)
|
||||
|
||||
val rootOffsetInHost = escaper.getOffsetInHost(0, rangeInHost)
|
||||
if (rootOffsetInHost >= 0) {
|
||||
// add a root project reference just before the first colon, i.e. it has an empty range
|
||||
result += GradleProjectReference(element, TextRange(rootOffsetInHost, rootOffsetInHost), emptyList())
|
||||
}
|
||||
|
||||
val subPath = ArrayList<String>()
|
||||
var currentOffsetInPath = 0
|
||||
var currentOffsetInPath = 1 // skip first ":"
|
||||
for (part in path) {
|
||||
subPath.add(part)
|
||||
val partStart = escaper.getOffsetInHost(currentOffsetInPath, rangeInHost)
|
||||
|
||||
@@ -17,18 +17,23 @@ import org.jetbrains.plugins.gradle.model.ExternalProject
|
||||
import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataCache
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle
|
||||
|
||||
/**
|
||||
* Empty [myQualifiedName] means root project.
|
||||
*/
|
||||
@Internal
|
||||
class GradleProjectSymbol(private val myQualifiedName: List<String>, private val myRootProjectPath: String) : PresentableSymbol, NavigatableSymbol {
|
||||
class GradleProjectSymbol(
|
||||
private val myQualifiedName: List<String>,
|
||||
private val myRootProjectPath: String
|
||||
) : PresentableSymbol, NavigatableSymbol {
|
||||
|
||||
init {
|
||||
require(myQualifiedName.isNotEmpty())
|
||||
require(myRootProjectPath.isNotBlank())
|
||||
}
|
||||
|
||||
override fun createPointer(): Pointer<GradleProjectSymbol> = Pointer.hardPointer(this)
|
||||
|
||||
val projectName: String get() = myQualifiedName.last()
|
||||
val qualifiedName: String get() = myQualifiedName.joinToString(separator = ":")
|
||||
val projectName: String get() = if (myQualifiedName.isEmpty()) ":" else myQualifiedName.last()
|
||||
val qualifiedName: String get() = qualifiedName(myQualifiedName)
|
||||
|
||||
private val myPresentation = SymbolPresentation.create(
|
||||
GradleIcons.Gradle,
|
||||
@@ -48,23 +53,18 @@ class GradleProjectSymbol(private val myQualifiedName: List<String>, private val
|
||||
}
|
||||
|
||||
private fun findBuildFile(project: Project): PsiElement? {
|
||||
val rootProject = ExternalProjectDataCache.getInstance(project)
|
||||
.getRootExternalProject(myRootProjectPath)
|
||||
?: return null
|
||||
|
||||
val externalProject = if (":" == qualifiedName) {
|
||||
val rootProject = ExternalProjectDataCache.getInstance(project).getRootExternalProject(myRootProjectPath) ?: return null
|
||||
val externalProject = if (myQualifiedName.isEmpty()) {
|
||||
rootProject
|
||||
} else {
|
||||
myQualifiedName
|
||||
.drop(1)
|
||||
.fold(rootProject as ExternalProject?) { extProject, name ->
|
||||
extProject?.childProjects?.get(name)
|
||||
} ?: return null
|
||||
}
|
||||
else {
|
||||
myQualifiedName.fold(rootProject as ExternalProject?) { extProject, name ->
|
||||
extProject?.childProjects?.get(name)
|
||||
} ?: return null
|
||||
}
|
||||
|
||||
val buildFile = externalProject.buildFile ?: return null
|
||||
val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(buildFile) ?: return null
|
||||
|
||||
return PsiManager.getInstance(project).findFile(virtualFile)
|
||||
}
|
||||
|
||||
@@ -75,11 +75,26 @@ class GradleProjectSymbol(private val myQualifiedName: List<String>, private val
|
||||
other as GradleProjectSymbol
|
||||
|
||||
if (myQualifiedName != other.myQualifiedName) return false
|
||||
if (myRootProjectPath != other.myRootProjectPath) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return myQualifiedName.hashCode()
|
||||
var result = myQualifiedName.hashCode()
|
||||
result = 31 * result + myRootProjectPath.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun qualifiedName(qualifiedNameParts: List<String>): String {
|
||||
return if (qualifiedNameParts.isEmpty()) {
|
||||
":"
|
||||
}
|
||||
else {
|
||||
qualifiedNameParts.joinToString("") { ":$it" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user