Skip to content

Commit 4b445e6

Browse files
committed
Fix line marker
1 parent d7113e6 commit 4b445e6

File tree

5 files changed

+138
-138
lines changed

5 files changed

+138
-138
lines changed

harness/tests/src/main/kotlin/godot/tests/Invocation.kt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -177,79 +177,62 @@ class Invocation : Node3D() {
177177
@Export
178178
var packedVector3Array = PackedVector3Array()
179179

180-
@Export
181180
@IntRange(1, 2)
182181
var p1 = 1
183182

184-
@Export
185183
@LongRange(1L, 2L)
186184
var p1_1 = 1L
187185

188-
@Export
189186
@FloatRange(1f, 2f)
190187
var p2 = 1f
191188

192-
@Export
193189
@DoubleRange(1.0, 2.0)
194190
var p3 = 1.0
195191

196-
@Export
197192
@DoubleRange(min = 1.0, max = 2.0, step = 0.1, or = Range.OR_GREATER, hideSlider = true, isDegrees = true, suffix = "MyCoolSuffix")
198193
var p4 = 1.0
199194

200-
@Export
201195
@FloatRange(1f, 2f)
202196
var p5 = 1f
203197

204-
@Export
205198
@EnumTypeHint
206199
var p6 = TestEnum.ENUM_1
207200

208-
@Export
209201
@ExpEasing
210202
var p7 = 1f
211203

212-
@Export
213204
@ExpEasing
214205
var p8 = 1.0
215206

216207
@Export
217208
@EnumFlag
218209
var p9 = setOf(TestEnum.ENUM_1)
219210

220-
@Export
221211
@EnumFlag
222212
var p10 = mutableSetOf(TestEnum.ENUM_1)
223213

224-
@Export
225214
@EnumFlag
226215
var p11 = mutableSetOf<TestEnum>()
227216

228-
@Export
229217
@IntFlag
230218
var p12 = 1 or 2 and 3
231219

232-
@Export
233220
@File
234221
var p13 = "someFile"
235222

236-
@Export
237223
@Dir
238224
var p14 = "someDir"
239225

240-
@Export
241226
@MultilineText
242227
var p15 = """
243228
some
244229
multiline
245230
text
246231
""".trimIndent()
247232

248-
@Export
249233
@PlaceHolderText
250234
var p16 = "some placeholderText"
251235

252-
@Export
253236
@ColorNoAlpha
254237
var p17 = Color()
255238

@@ -306,6 +289,7 @@ class Invocation : Node3D() {
306289
println("CustomName is $customName")
307290
}
308291

292+
309293
override fun _ready() {
310294
val formerName = name
311295
println("Name is: $name")

kt/plugins/godot-intellij-plugin/src/main/kotlin/godot/intellij/plugin/annotator/clazz/RegisterClassAnnotator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class RegisterClassAnnotator : BaseAnnotator {
3232
override fun checkElement(element: PsiElement, holder: AnnotationHolder) {
3333
when(element) {
3434
is PsiClass -> {
35-
if (!element.isRegistered()) {
35+
if (!element.isRegistered() || element.isAnnotationType) {
3636
val errorLocation = element.nameIdentifier ?: element.navigationElement
3737
if (element.getAnnotation(TOOL_ANNOTATION) != null) {
3838
holder.registerProblem(

kt/plugins/godot-intellij-plugin/src/main/kotlin/godot/intellij/plugin/extension/ktPsi.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ fun KtProperty.type(): KotlinType? = (this.resolveToDescriptorIfAny() as? Callab
1616

1717
fun PsiElement.isSignal(): Boolean {
1818
return when(this) {
19-
is KtProperty -> this.type()?.getKotlinTypeFqName(false) == "$godotCorePackage.${GodotKotlinJvmTypes.signal}"
20-
is PsiField -> this.type.canonicalText == "$godotCorePackage.${GodotKotlinJvmTypes.signal}"
19+
is KtProperty -> this.type()?.getKotlinTypeFqName(false)?.startsWith("$godotCorePackage.${GodotKotlinJvmTypes.signal}") == true
20+
is PsiField -> this.type.canonicalText.startsWith("$godotCorePackage.${GodotKotlinJvmTypes.signal}")
2121
else -> false
2222
}
2323
}
Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,142 @@
11
package godot.intellij.plugin.extension
22

33
import com.intellij.psi.PsiAnnotation
4+
import com.intellij.psi.PsiClass
45
import com.intellij.psi.PsiElement
6+
import com.intellij.psi.PsiField
7+
import com.intellij.psi.PsiMethod
58
import com.intellij.psi.PsiModifierListOwner
9+
import godot.intellij.plugin.data.model.GODOT_API_MEMBER_ANNOTATION
10+
import godot.intellij.plugin.data.model.GODOT_MEMBER_ANNOTATION
611
import godot.tools.common.constants.GodotKotlinJvmTypes
712
import godot.tools.common.constants.godotAnnotationPackage
13+
import org.jetbrains.kotlin.descriptors.ClassDescriptor
14+
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
15+
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
16+
import org.jetbrains.kotlin.idea.caches.resolve.analyze
17+
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
18+
import org.jetbrains.kotlin.name.FqName
19+
import org.jetbrains.kotlin.psi.KtAnnotated
20+
import org.jetbrains.kotlin.psi.KtAnnotationEntry
21+
import org.jetbrains.kotlin.psi.KtClass
22+
import org.jetbrains.kotlin.psi.KtElement
23+
import org.jetbrains.kotlin.psi.KtFunction
24+
import org.jetbrains.kotlin.psi.KtProperty
25+
import org.jetbrains.kotlin.resolve.BindingContext
26+
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration
27+
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
828

929

1030
fun PsiElement.isRegistered(): Boolean {
11-
if (this !is PsiModifierListOwner) return false
31+
return when (this) {
32+
is KtAnnotated -> when (this) {
33+
is KtClass -> hasRegistrationAnnotation()
34+
is KtProperty -> hasRegistrationAnnotation() || isSignal() || overridesRegistered()
35+
is KtFunction -> hasRegistrationAnnotation() || overridesGodotApiFunction() || overridesRegistered()
36+
else -> false
37+
}
38+
39+
is PsiModifierListOwner -> when(this) {
40+
is PsiClass -> hasRegistrationAnnotation()
41+
is PsiField -> hasRegistrationAnnotation() || isSignal() || overridesRegistered()
42+
is PsiMethod -> hasRegistrationAnnotation() || overridesGodotApiFunction() || overridesRegistered()
43+
else -> false
44+
}
45+
46+
else -> return false
47+
}
48+
}
49+
50+
private fun KtProperty.overridesRegistered(): Boolean {
51+
return (this.descriptor as? PropertyDescriptor)?.overriddenDescriptors?.any { overriddenDescriptor ->
52+
overriddenDescriptor.annotations.hasAnnotation(FqName(GODOT_API_MEMBER_ANNOTATION))
53+
} ?: false
54+
}
55+
56+
private fun KtFunction.overridesRegistered(): Boolean {
57+
return (this.descriptor as? FunctionDescriptor)?.overriddenDescriptors?.any { overriddenDescriptor ->
58+
overriddenDescriptor.annotations.hasAnnotation(FqName(GODOT_MEMBER_ANNOTATION))
59+
} ?: false
60+
}
61+
62+
private fun KtAnnotated.hasRegistrationAnnotation(): Boolean {
63+
return this.resolveAllAnnotationsRecursively().any {
64+
it.fqName?.asString() == "$godotAnnotationPackage.${GodotKotlinJvmTypes.Annotations.godotMember}"
65+
|| it.fqName?.asString() == "$godotAnnotationPackage.${GodotKotlinJvmTypes.Annotations.godotScript}"
66+
}
67+
}
68+
69+
private fun KtFunction.overridesGodotApiFunction(): Boolean {
70+
return (this.descriptor as? FunctionDescriptor)?.overriddenDescriptors?.any { overriddenDescriptor ->
71+
overriddenDescriptor.annotations.hasAnnotation(FqName(GODOT_API_MEMBER_ANNOTATION))
72+
} ?: false
73+
}
74+
75+
private fun KtAnnotated.resolveAllAnnotationsRecursively(): List<KtClass> {
76+
return annotationEntries.mapNotNull { it.toAnnotationClass()?.first }.flatMap { listOf(it) + it.resolveAllAnnotationsRecursively() }
77+
}
78+
79+
private fun KtAnnotationEntry.toAnnotationClass(): Pair<KtClass, ClassDescriptor>? {
80+
val context = (this as KtElement).analyze(BodyResolveMode.PARTIAL)
81+
val annotationDescriptor = context.get(BindingContext.ANNOTATION, this) ?: return null
82+
83+
val classDescriptor = annotationDescriptor.type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
84+
val ktClass = descriptorToDeclaration(classDescriptor) as? KtClass ?: return null
85+
86+
return if (ktClass.isAnnotation() && ktClass.isWritable) {
87+
ktClass to classDescriptor
88+
} else {
89+
null
90+
}
91+
}
92+
93+
private fun PsiModifierListOwner.hasRegistrationAnnotation(): Boolean {
1294
return this.annotations.any { it.isRegistrationAnnotation() }
1395
}
1496

15-
private fun PsiAnnotation.isRegistrationAnnotation(): Boolean {
97+
private fun PsiAnnotation.isRegistrationAnnotation(alreadyResolvedAnnotations: MutableList<PsiAnnotation> = mutableListOf()): Boolean {
1698
return this.qualifiedName == "$godotAnnotationPackage.${GodotKotlinJvmTypes.Annotations.godotScript}" ||
1799
this.qualifiedName == "$godotAnnotationPackage.${GodotKotlinJvmTypes.Annotations.godotMember}" ||
18-
this.resolveAnnotationType()?.annotations?.any { it.isRegistrationAnnotation() } == true
100+
run {
101+
val annotationsOnAnnotation = this.resolveAnnotationType()?.annotations ?: return false
102+
annotationsOnAnnotation
103+
.filter { it !in alreadyResolvedAnnotations }
104+
.any { it.isRegistrationAnnotation(alreadyResolvedAnnotations.apply { addAll(annotationsOnAnnotation) }) }
105+
}
106+
}
107+
108+
private fun PsiField.getOverriddenFields(): List<PsiField> {
109+
val overriddenFields = mutableListOf<PsiField>()
110+
val containingClass = this.containingClass ?: return overriddenFields
111+
112+
var superClass: PsiClass? = containingClass.superClass
113+
114+
while (superClass != null) {
115+
for (superField in superClass.fields) {
116+
if (this.name == superField.name && this.type.isAssignableFrom(superField.type)) {
117+
overriddenFields.add(superField)
118+
}
119+
}
120+
superClass = superClass.superClass
121+
}
122+
123+
return overriddenFields
124+
}
125+
126+
private fun PsiField.overridesRegistered(): Boolean {
127+
return getOverriddenFields().any { it.isRegistered() }
128+
}
129+
130+
private fun PsiMethod.overridesRegistered(): Boolean {
131+
val superMethods = this.findSuperMethods()
132+
133+
return superMethods.any { it.isRegistered() }
134+
}
135+
136+
private fun PsiMethod.overridesGodotApiFunction(): Boolean {
137+
val superMethods = this.findSuperMethods()
138+
139+
return superMethods.any { superMethod ->
140+
superMethod.annotations.any { superMethodAnnotation -> superMethodAnnotation.qualifiedName == GODOT_API_MEMBER_ANNOTATION }
141+
}
19142
}

0 commit comments

Comments
 (0)