fun listClassMemberDeclarations()

in gdscript/src/main/kotlin/gdscript/psi/utils/GdClassMemberUtil.kt [518:627]


    fun listClassMemberDeclarations(
        element: PsiElement,
        static: Boolean? = false,
        search: String? = null,
        constructors: Boolean = false,
        isRecursive: Boolean = false,
    ): MutableList<PsiElement> {
        val classElement = when (element) {
            is GdFile, is GdClassDeclTl -> element
            else -> GdClassUtil.getOwningClassElement(element)
        }

        val members = mutableListOf<PsiElement>()

        if (search != null) {
            val project = element.project
            val scope = GlobalSearchScope.fileScope(element.containingFile)

            GdMethodDeclIndex.INSTANCE.getScoped(search, project, scope).firstOrNull()?.let {
                if ((static == null || it.isStatic == static)) {
                    if (constructors || !it.isConstructor) {
                        if (GdClassUtil.getOwningClassElement(it) == classElement) {
                            return mutableListOf(it)
                        }
                    }
                }
            }
            GdConstDeclIndex.INSTANCE.getScoped(search, project, scope).firstOrNull()
                ?.let { if (GdClassUtil.getOwningClassElement(it) == classElement) it else null }?.let { return mutableListOf(it) }
            GdEnumDeclIndex.INSTANCE.getScoped(search, project, scope).firstOrNull()
                ?.let { if (GdClassUtil.getOwningClassElement(it) == classElement) it else null }?.let { return mutableListOf(it) }
            GdSignalDeclIndex.INSTANCE.getScoped(search, project, scope).firstOrNull()
                ?.let { if (GdClassUtil.getOwningClassElement(it) == classElement) it else null }?.let { return mutableListOf(it) }
            GdClassVarDeclIndex.INSTANCE.getScoped(search, project, scope).firstOrNull()
                ?.let { if (GdClassUtil.getOwningClassElement(it) == classElement) it else null }
                ?.let { if (static != true || it.isStatic) return mutableListOf(it) }

            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdClassDeclTl::class.java).forEach {
                if (it.name == search) return mutableListOf(it)
                if (isRecursive) {
                    members.addAll(listClassMemberDeclarations(it, static, search))
                    if (members.size > 0) return members
                }
            }
            if (classElement is GdClassDeclTl && !isRecursive) {
                PsiTreeUtil.getStubChildrenOfTypeAsList(classElement.parent, GdClassDeclTl::class.java).forEach {
                    if (it.name == search) return mutableListOf(it)
                    members.addAll(listClassMemberDeclarations(it, static, search, false, true))
                    if (members.size > 0) return members
                }
            }

            // TODO Create stub for unnamed enums
            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdEnumDeclTl::class.java).forEach {
                if (it.name.isBlank()) {
                    it.enumValueList.forEach { value ->
                        if (value.enumValueNmi.name == search) return mutableListOf(value)
                    }
                }
            }
        } else {
            // When completing with a qualifier (static or instance), avoid mixing in file-level declarations,
            // which would otherwise expose unrelated top-level classes like the qualifier's ancestors.
            if (classElement is PsiFile && static != null) {
                return mutableListOf()
            }
            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdConstDeclTl::class.java).forEach {
                members.add(it)
            }
            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdEnumDeclTl::class.java).forEach {
                if (it.name.isNotBlank()) {
                    members.add(it)
                } else {
                    it.enumValueList.forEach { value ->
                        members.add(value)
                    }
                }
            }
            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdSignalDeclTl::class.java).forEach {
                members.add(it)
            }
            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdClassDeclTl::class.java).forEach {
                // For completion and general member listing, include only direct inner classes,
                // not members of their inner trees. Deeper members are reachable after further qualification.
                members.add(it)
            }
            if (classElement is GdClassDeclTl && !isRecursive) {
                PsiTreeUtil.getStubChildrenOfTypeAsList(classElement.parent, GdClassDeclTl::class.java).forEach {
                    members.addAll(listClassMemberDeclarations(it, static, null, false, true))
                }
            }

            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdClassVarDeclTl::class.java).forEach {
                if (static != true || it.isStatic) {
                    members.add(it)
                }
            }

            PsiTreeUtil.getStubChildrenOfTypeAsList(classElement, GdMethodDeclTl::class.java).forEach {
                if ((static == null || it.isStatic == static)) {
                    if (constructors || !it.isConstructor) {
                        members.add(it)
                    }
                }
            }
        }
        if (search != null) return mutableListOf()

        return members
    }