Skip to content

Commit 150f756

Browse files
Nurullokhon Gulomkodirovintellij-monorepo-bot
authored andcommitted
[terraform] IJPL-185785 Refactoring, simplified hcl psi util methods
GitOrigin-RevId: e555060970d33e11c7e293bc9574ff3ab765d5e0
1 parent 4567266 commit 150f756

File tree

11 files changed

+128
-141
lines changed

11 files changed

+128
-141
lines changed

terraform/src/org/intellij/terraform/config/model/extensions.kt

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
1+
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
22
package org.intellij.terraform.config.model
33

44
import com.fasterxml.jackson.databind.node.ArrayNode
@@ -16,13 +16,13 @@ import org.intellij.terraform.hil.psi.ILExpression
1616
import org.intellij.terraform.hil.psi.TypeCachedValueProvider
1717
import org.intellij.terraform.hil.psi.impl.getHCLHost
1818

19-
fun HCLElement.getTerraformModule(): Module {
19+
internal fun HCLElement.getTerraformModule(): Module {
2020
val file = this.containingFile.originalFile
2121
assert(file is HCLFile)
2222
return Module.getModule(file)
2323
}
2424

25-
fun PsiElement.getTerraformSearchScope(): GlobalSearchScope {
25+
internal fun PsiElement.getTerraformSearchScope(): GlobalSearchScope {
2626
val file = this.containingFile.originalFile
2727
var directory = file.containingDirectory
2828
if (directory == null) {
@@ -40,11 +40,7 @@ fun PsiElement.getTerraformSearchScope(): GlobalSearchScope {
4040
}
4141
}
4242

43-
fun HCLProperty.toProperty(type: PropertyType): Property {
44-
return Property(type, this.value)
45-
}
46-
47-
fun HCLBlock.getProviderFQName(): String? {
43+
internal fun HCLBlock.getProviderFQName(): String? {
4844
val tp = this.getNameElementUnquoted(1) ?: return null
4945
val als = when (val value = this.`object`?.findProperty("alias")?.value) {
5046
is HCLStringLiteral -> value.value
@@ -58,42 +54,39 @@ fun HCLBlock.getProviderFQName(): String? {
5854
}
5955
}
6056

61-
fun BaseExpression?.getType(): Type? {
57+
internal fun BaseExpression?.getType(): Type? {
6258
if (this == null) return null
6359
return TypeCachedValueProvider.getType(this)
6460
}
6561

66-
fun BaseExpression.isInTerraformFile(): Boolean {
62+
internal fun BaseExpression.isInTerraformFile(): Boolean {
6763
return TfPsiPatterns.TerraformFile.accepts(this.getHCLHost()?.containingFile)
6864
}
6965

70-
fun String.ensureHavePrefix(prefix: String) = if (this.startsWith(prefix)) this else (prefix + this)
71-
fun String.ensureHaveSuffix(suffix: String) = if (this.endsWith(suffix)) this else (this + suffix)
66+
internal fun String.ensureHavePrefix(prefix: String): String = if (this.startsWith(prefix)) this else (prefix + this)
7267

73-
74-
fun ObjectNode.isNotEmpty(): Boolean {
68+
internal fun ObjectNode.isNotEmpty(): Boolean {
7569
return size() > 0
7670
}
7771

78-
fun ObjectNode.obj(name: String): ObjectNode? {
72+
internal fun ObjectNode.obj(name: String): ObjectNode? {
7973
return this.get(name) as? ObjectNode
8074
}
8175

82-
fun ObjectNode.array(name: String): ArrayNode? {
76+
internal fun ObjectNode.array(name: String): ArrayNode? {
8377
return this.get(name) as? ArrayNode
8478
}
8579

86-
fun ObjectNode.string(name: String): String? {
80+
internal fun ObjectNode.string(name: String): String? {
8781
return this.get(name)?.textValue()
8882
}
8983

90-
fun ObjectNode.number(name: String): Number? {
84+
internal fun ObjectNode.number(name: String): Number? {
9185
return this.get(name)?.numberValue()
9286
}
9387

94-
fun ObjectNode.boolean(name: String): Boolean? {
88+
internal fun ObjectNode.boolean(name: String): Boolean? {
9589
val node = this.get(name) ?: return null
9690
if (!node.isBoolean) return null
9791
return node.booleanValue()
9892
}
99-

terraform/src/org/intellij/terraform/config/model/loader/loaders_v1.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
1+
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
22
package org.intellij.terraform.config.model.loader
33

44
import com.fasterxml.jackson.databind.node.ArrayNode
55
import com.fasterxml.jackson.databind.node.ObjectNode
66
import com.fasterxml.jackson.databind.node.TextNode
77
import org.intellij.terraform.config.Constants
8+
import org.intellij.terraform.config.Constants.HCL_PROVISIONER_IDENTIFIER
89
import org.intellij.terraform.config.model.*
910
import org.intellij.terraform.config.model.loader.TfMetadataLoader.Companion.LOG
1011

@@ -226,7 +227,7 @@ abstract class ProviderLoader(protected val base: BaseLoader) : VersionedMetadat
226227
}
227228

228229
abstract class ProvisionerLoader(protected val base: BaseLoader) : VersionedMetadataLoader {
229-
override fun isSupportedType(type: String): Boolean = type == "provisioner"
230+
override fun isSupportedType(type: String): Boolean = type == HCL_PROVISIONER_IDENTIFIER
230231
override fun load(context: LoadContext, json: ObjectNode, fileName: String) {
231232
val model = context.model
232233
val provisioner_schema = json.obj("schemas") ?: json

terraform/src/org/intellij/terraform/hcl/psi/HCLPsiUtil.kt

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,19 @@ import com.intellij.psi.PsiElement
77
import com.intellij.psi.PsiReference
88
import com.intellij.psi.PsiWhiteSpace
99
import com.intellij.psi.util.PsiTreeUtil
10+
import com.intellij.psi.util.parentOfType
1011
import com.intellij.psi.util.siblings
12+
import org.intellij.terraform.config.Constants.HCL_CONNECTION_IDENTIFIER
13+
import org.intellij.terraform.config.Constants.HCL_PROVISIONER_IDENTIFIER
14+
import org.intellij.terraform.config.model.Module
15+
import org.intellij.terraform.config.model.Variable
16+
import org.intellij.terraform.config.model.getTerraformModule
1117
import org.intellij.terraform.config.patterns.TfPsiPatterns
18+
import org.intellij.terraform.hcl.psi.common.BaseExpression
1219
import org.intellij.terraform.hcl.psi.common.Identifier
1320
import org.intellij.terraform.hcl.psi.common.IndexSelectExpression
1421
import org.intellij.terraform.hcl.psi.common.SelectExpression
22+
import org.intellij.terraform.hil.psi.impl.getHCLHost
1523

1624
/**
1725
* Various helper methods for working with PSI of JSON language.
@@ -186,9 +194,9 @@ internal object HCLPsiUtil {
186194
}
187195

188196
fun PsiElement.getRequiredProviderProperty(): HCLProperty? {
189-
val providerProperty = when {
190-
this is HCLProperty -> this
191-
this is Identifier && this.parent is HCLProperty -> this.parent as HCLProperty
197+
val providerProperty = when (this) {
198+
is HCLProperty -> this
199+
is Identifier if this.parent is HCLProperty -> this.parent as HCLProperty
192200
else -> return null
193201
}
194202

@@ -208,3 +216,73 @@ internal object HCLPsiUtil {
208216
fun PsiElement.getNextSiblingNonWhiteSpace(): PsiElement? =
209217
this.siblings(forward = true, withSelf = false).firstOrNull { it !is PsiWhiteSpace }
210218
}
219+
220+
internal fun getTerraformModule(element: BaseExpression): Module? {
221+
val host = element.getHCLHost() ?: return null
222+
return host.getTerraformModule()
223+
}
224+
225+
internal fun getLocalDefinedVariables(element: BaseExpression): List<Variable> {
226+
return getTerraformModule(element)?.getAllVariables() ?: emptyList()
227+
}
228+
229+
internal fun getDefinedLocalsInModule(element: BaseExpression): List<String> {
230+
return getTerraformModule(element)?.getAllLocals()?.map { it.first } ?: emptyList()
231+
}
232+
233+
internal fun getHclBlockForSelfContext(position: BaseExpression): HCLBlock? {
234+
val host = position.getHCLHost() ?: return null
235+
return getProvisionerOfResource(host) ?: getConnectionOfResource(host)
236+
}
237+
238+
internal fun getProvisionerOfResource(host: HCLElement): HCLBlock? {
239+
val provisioner = host.parentOfType<HCLBlock>() ?: return null
240+
241+
return when (provisioner.getNameElementUnquoted(0)) {
242+
HCL_CONNECTION_IDENTIFIER -> getProvisionerOfResource(provisioner)
243+
HCL_PROVISIONER_IDENTIFIER -> getParentResourceBlock(provisioner)
244+
else -> null
245+
}
246+
}
247+
248+
internal fun getConnectionOfResource(host: HCLElement): HCLBlock? {
249+
val connection = host.parentOfType<HCLBlock>() ?: return null
250+
251+
return when (connection.getNameElementUnquoted(0)) {
252+
HCL_CONNECTION_IDENTIFIER -> getParentResourceBlock(connection)
253+
else -> null
254+
}
255+
}
256+
257+
internal fun getParentResourceBlock(element: HCLElement): HCLBlock? {
258+
val resource = element.parentOfType<HCLBlock>()
259+
return if (TfPsiPatterns.ResourceRootBlock.accepts(resource)) resource else null
260+
}
261+
262+
internal fun getResource(position: BaseExpression): HCLBlock? {
263+
val host = position.getHCLHost() ?: return null
264+
return getParentResourceBlock(host)
265+
}
266+
267+
internal fun getDataSource(position: BaseExpression): HCLBlock? {
268+
val host = position.getHCLHost() ?: return null
269+
val dataSource = host.parentOfType<HCLBlock>()
270+
return if (TfPsiPatterns.DataSourceRootBlock.accepts(dataSource)) dataSource else null
271+
}
272+
273+
internal fun getContainingResourceOrDataSource(element: HCLElement?): HCLBlock? {
274+
if (element == null) return null
275+
return PsiTreeUtil.findFirstParent(element, true) {
276+
TfPsiPatterns.DataSourceRootBlock.accepts(it) ||
277+
TfPsiPatterns.ResourceRootBlock.accepts(it)
278+
} as? HCLBlock
279+
}
280+
281+
internal fun getContainingResourceOrDataSourceOrModule(element: HCLElement?): HCLBlock? {
282+
if (element == null) return null
283+
return PsiTreeUtil.findFirstParent(element, true) {
284+
TfPsiPatterns.DataSourceRootBlock.accepts(it) ||
285+
TfPsiPatterns.ResourceRootBlock.accepts(it) ||
286+
TfPsiPatterns.ModuleRootBlock.accepts(it)
287+
} as? HCLBlock
288+
}

terraform/src/org/intellij/terraform/hil/codeinsight/HILCompletionContributor.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ import org.intellij.terraform.hil.patterns.HILPatterns.IlseNotFromKnownScope
4343
import org.intellij.terraform.hil.patterns.HILPatterns.InsideForExpressionBody
4444
import org.intellij.terraform.hil.patterns.HILPatterns.MethodPosition
4545
import org.intellij.terraform.hil.patterns.HILPatterns.VariableTypePosition
46-
import org.intellij.terraform.hil.psi.*
46+
import org.intellij.terraform.hil.psi.FakeTypeProperty
47+
import org.intellij.terraform.hil.psi.ForVariableCompletion
48+
import org.intellij.terraform.hil.psi.getGoodLeftElement
4749
import org.intellij.terraform.hil.psi.impl.getHCLHost
50+
import org.intellij.terraform.hil.psi.resolve
4851
import org.intellij.terraform.opentofu.codeinsight.EncryptionMethodsCompletionProvider
4952
import org.intellij.terraform.opentofu.codeinsight.KeyProvidersCompletionProvider
5053
import org.intellij.terraform.opentofu.codeinsight.findEncryptionBlocksIdsByType
@@ -127,7 +130,7 @@ open class HILCompletionContributor : CompletionContributor(), DumbAware {
127130
result: CompletionResultSet) {
128131
// For now 'self' allowed only for provisioners inside resources
129132

130-
val resource = getProvisionerOrConnectionResource(variable) ?: return
133+
val resource = getHclBlockForSelfContext(variable) ?: return
131134
val properties = TfModelHelper.getBlockProperties(resource)
132135
// TODO: Filter already defined or computed properties (?)
133136
// TODO: Add type filtration
@@ -175,7 +178,7 @@ open class HILCompletionContributor : CompletionContributor(), DumbAware {
175178
parameters: CompletionParameters,
176179
context: ProcessingContext,
177180
result: CompletionResultSet) {
178-
val variables: List<String> = getLocalDefinedLocals(variable)
181+
val variables: List<String> = getDefinedLocalsInModule(variable)
179182
for (v in variables) {
180183
result.addElement(create(v))
181184
}
@@ -270,7 +273,7 @@ open class HILCompletionContributor : CompletionContributor(), DumbAware {
270273
result.addAllElements(model.providerDefinedFunctions.map { createFunction(it) })
271274

272275
result.addAllElements(GlobalScopes.map { createScope(it) })
273-
if (getProvisionerOrConnectionResource(parent) != null) result.addElement(createScope("self"))
276+
if (getHclBlockForSelfContext(parent) != null) result.addElement(createScope("self"))
274277

275278
val host = parent.getHCLHost() ?: return
276279
val resourceOrDataSource = getContainingResourceOrDataSourceOrModule(host)

terraform/src/org/intellij/terraform/hil/inspection/HILMissingSelfInContextInspection.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
1+
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
22
package org.intellij.terraform.hil.inspection
33

44
import com.intellij.codeInspection.LocalInspectionTool
@@ -9,7 +9,11 @@ import com.intellij.openapi.progress.ProgressIndicatorProvider
99
import com.intellij.psi.PsiElementVisitor
1010
import com.intellij.psi.PsiFile
1111
import org.intellij.terraform.hcl.HCLBundle
12-
import org.intellij.terraform.hil.psi.*
12+
import org.intellij.terraform.hcl.psi.getConnectionOfResource
13+
import org.intellij.terraform.hcl.psi.getProvisionerOfResource
14+
import org.intellij.terraform.hil.psi.ILElementVisitor
15+
import org.intellij.terraform.hil.psi.ILSelectExpression
16+
import org.intellij.terraform.hil.psi.ILVariable
1317
import org.intellij.terraform.hil.psi.impl.getHCLHost
1418
import org.intellij.terraform.isTerraformCompatiblePsiFile
1519

@@ -34,8 +38,8 @@ class HILMissingSelfInContextInspection : LocalInspectionTool() {
3438
val parent = element.parent as? ILSelectExpression ?: return
3539
if (parent.from !== element) return
3640

37-
if (getProvisionerResource(host) != null) return
38-
if (getConnectionResource(host) != null) return
41+
if (getProvisionerOfResource(host) != null) return
42+
if (getConnectionOfResource(host) != null) return
3943

4044
holder.registerProblem(element, HCLBundle.message("hil.scope.not.available.in.context.inspection.illegal.self.use.message"), ProblemHighlightType.GENERIC_ERROR)
4145
}

terraform/src/org/intellij/terraform/hil/psi/ILScopeReferenceProvider.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
1+
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
22
package org.intellij.terraform.hil.psi
33

44
import com.intellij.psi.PsiElement
@@ -7,6 +7,9 @@ import com.intellij.psi.PsiReferenceProvider
77
import com.intellij.util.ProcessingContext
88
import org.intellij.terraform.hcl.psi.common.Identifier
99
import org.intellij.terraform.hcl.psi.common.SelectExpression
10+
import org.intellij.terraform.hcl.psi.getDataSource
11+
import org.intellij.terraform.hcl.psi.getHclBlockForSelfContext
12+
import org.intellij.terraform.hcl.psi.getResource
1013
import org.intellij.terraform.hil.psi.impl.getHCLHost
1114

1215
object ILScopeReferenceProvider : PsiReferenceProvider() {
@@ -26,7 +29,7 @@ object ILScopeReferenceProvider : PsiReferenceProvider() {
2629
when (element.name) {
2730
"self" -> {
2831
return arrayOf(HCLElementLazyReference(element, false) { _, _ ->
29-
val resource = getProvisionerOrConnectionResource(this.element) ?: return@HCLElementLazyReference emptyList()
32+
val resource = getHclBlockForSelfContext(this.element) ?: return@HCLElementLazyReference emptyList()
3033
listOf(resource)
3134
})
3235
}

terraform/src/org/intellij/terraform/hil/psi/ILSelectFromScopeReferenceProvider.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import org.intellij.terraform.config.model.getTerraformModule
1313
import org.intellij.terraform.hcl.psi.HCLElement
1414
import org.intellij.terraform.hcl.psi.common.Identifier
1515
import org.intellij.terraform.hcl.psi.common.SelectExpression
16+
import org.intellij.terraform.hcl.psi.getHclBlockForSelfContext
1617
import org.intellij.terraform.hil.codeinsight.AddVariableFix
1718
import org.intellij.terraform.hil.psi.impl.getHCLHost
1819

@@ -68,7 +69,7 @@ object ILSelectFromScopeReferenceProvider : PsiReferenceProvider() {
6869
class SelfResourceReference(element: Identifier) : HCLElementLazyReferenceBase<Identifier>(element, false) {
6970
override fun resolve(incompleteCode: Boolean, includeFake: Boolean): List<HCLElement> {
7071
val name = this.element.name ?: return emptyList()
71-
val resource = getProvisionerOrConnectionResource(this.element) ?: return emptyList()
72+
val resource = getHclBlockForSelfContext(this.element) ?: return emptyList()
7273

7374
val prop = resource.`object`?.findProperty(name)
7475
if (prop != null) return listOf(prop)

terraform/src/org/intellij/terraform/hil/psi/ResourceEachVariableReferenceProvider.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
1+
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
22
package org.intellij.terraform.hil.psi
33

44
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider
@@ -13,6 +13,7 @@ import org.intellij.terraform.hcl.psi.HCLElement
1313
import org.intellij.terraform.hcl.psi.common.BaseExpression
1414
import org.intellij.terraform.hcl.psi.common.Identifier
1515
import org.intellij.terraform.hcl.psi.common.SelectExpression
16+
import org.intellij.terraform.hcl.psi.getContainingResourceOrDataSourceOrModule
1617
import org.intellij.terraform.hil.psi.impl.getHCLHost
1718

1819
object ResourceEachVariableReferenceProvider : PsiReferenceProvider() {

0 commit comments

Comments
 (0)