<commit_before>/*
 * Copyright (c) 2017. tangzx(<EMAIL>)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tang.intellij.lua.psi.impl

import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.lang.ASTNode
import com.intellij.openapi.util.RecursionManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.tree.IElementType
import com.tang.intellij.lua.psi.*
import com.tang.intellij.lua.search.SearchContext
import com.tang.intellij.lua.stubs.LuaNameStub
import com.tang.intellij.lua.ty.ITy
import com.tang.intellij.lua.ty.Ty
import com.tang.intellij.lua.ty.TyClass
import com.tang.intellij.lua.ty.TySerializedClass

/**

 * Created by TangZX on 2017/4/12.
 */
abstract class LuaNameExprMixin : StubBasedPsiElementBase<LuaNameStub>, LuaExpr, LuaClassField {
    internal constructor(stub: LuaNameStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)

    internal constructor(node: ASTNode) : super(node)

    internal constructor(stub: LuaNameStub, nodeType: IElementType, node: ASTNode) : super(stub, nodeType, node)

    override fun getReference(): PsiReference? {
        return references.firstOrNull()
    }

    override fun guessParentType(context: SearchContext): ITy {
        //todo: model type
        return Ty.UNKNOWN
    }

    override fun guessType(context: SearchContext): ITy {
        val set = RecursionManager.doPreventingRecursion(this, true) {
            var type:ITy = Ty.UNKNOWN
            val nameExpr = this as LuaNameExpr

            val multiResolve = multiResolve(nameExpr, context)
            multiResolve.forEach {
                val set = getType(context, it)
                type = type.union(set)
            }

            if (Ty.isInvalid(type)) {
                type = type.union(getType(context, nameExpr))
            }

            type
        }
        return set ?: Ty.UNKNOWN
    }

    private fun getType(context: SearchContext, def: PsiElement): ITy {
        when (def) {
            is LuaNameExpr -> {
                //todo stub.module -> ty
                val stub = def.stub
                stub?.module?.let {
                    return TySerializedClass(it)
                }

                var type: ITy = Ty.UNKNOWN
                val p1 = def.parent // should be VAR_LIST
                val p2 = p1.parent // should be ASSIGN_STAT
                if (p2 is LuaAssignStat) {
                    val comment = p2.comment
                    //guess from comment
                    if (comment != null)
                        type = comment.guessType(context)
                    //guess from value expr
                    if (Ty.isInvalid(type)) {
                        val exprList = p2.valueExprList
                        if (exprList != null) {<commit_msg>bug fix<commit_after>/*
 * Copyright (c) 2017. tangzx(<EMAIL>)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tang.intellij.lua.psi.impl

import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.lang.ASTNode
import com.intellij.openapi.util.RecursionManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.tree.IElementType
import com.tang.intellij.lua.psi.*
import com.tang.intellij.lua.search.SearchContext
import com.tang.intellij.lua.stubs.LuaNameStub
import com.tang.intellij.lua.ty.ITy
import com.tang.intellij.lua.ty.Ty
import com.tang.intellij.lua.ty.TyClass
import com.tang.intellij.lua.ty.TySerializedClass

/**

 * Created by TangZX on 2017/4/12.
 */
abstract class LuaNameExprMixin : StubBasedPsiElementBase<LuaNameStub>, LuaExpr, LuaClassField {
    internal constructor(stub: LuaNameStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)

    internal constructor(node: ASTNode) : super(node)

    internal constructor(stub: LuaNameStub, nodeType: IElementType, node: ASTNode) : super(stub, nodeType, node)

    override fun getReference(): PsiReference? {
        return references.firstOrNull()
    }

    override fun guessParentType(context: SearchContext): ITy {
        //todo: model type
        return Ty.UNKNOWN
    }

    override fun guessType(context: SearchContext): ITy {
        val set = RecursionManager.doPreventingRecursion(this, true) {
            var type:ITy = Ty.UNKNOWN
            val nameExpr = this as LuaNameExpr

            val multiResolve = multiResolve(nameExpr, context)
            multiResolve.forEach {
                val set = getType(context, it)
                type = type.union(set)
            }

            if (Ty.isInvalid(type)) {
                type = type.union(getType(context, nameExpr))
            }

            type
        }
        return set ?: Ty.UNKNOWN
    }

    private fun getType(context: SearchContext, def: PsiElement): ITy {
        when (def) {
            is LuaNameExpr -> {
                //todo stub.module -> ty
                val stub = def.stub
                stub?.module?.let {
                    val memberType = TySerializedClass(it).findMemberType(def.name, context)
                    if (memberType != null) return memberType
                }

                var type: ITy = Ty.UNKNOWN
                val p1 = def.parent // should be VAR_LIST
                val p2 = p1.parent // should be ASSIGN_STAT
                if (p2 is LuaAssignStat) {
                    val comment = p2.comment
                    //guess from comment
                    if (comment != null)
                        type = comment.guessType(context)
                    //guess from value expr
                    if (Ty.isInvalid(type)) {
                        val exprList = p2.valueExprList
                        if (exprList != null) {
{'fraction_non_alphanumeric': 0.08926487747957992, 'fraction_numerical': 0.006126021003500583, 'mean_word_length': 2.2298634008478566, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6987120', 'n_tokens_mistral': 2018, 'n_tokens_neox': 1966, 'n_words': 530}