Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

尝试修复了一个使用泛型的bug;临时增加了import的实现 #203

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
luahelper-lsp/log.txt
luahelper-vscode/log.txt
luahelper-lsp/luahelper-lsp.exe
luahelper-lsp/__debug_bin.exe
luahelper-lsp/.idea/luahelper-lsp.iml
luahelper-lsp/.idea/modules.xml
luahelper-lsp/.idea/vcs.xml
luahelper-lsp/__debug_bin
luahelper-lsp/pkg/
luahelper-lsp/bin/
pkg/
bin/
.DS_Store
__debug_bin*
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ type AnnotateGenericState struct {
CommentLoc lexer.Location // 注释内容的位置信息
}

// AnnotateGenericVarState 泛型变量的结构
type AnnotateGenericVarState struct {
NormalStr string // 可能的字符串
IsBacktick bool // 是否字符串表达式变量
IsArrayType bool // 是否为数组类型
}

// AnnotateVarargState 可变参数的结构
type AnnotateVarargState struct {
VarargType Type // 定义的类型
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,50 @@ func GetAllNormalStrList(astType Type) (strList []string) {
return
}

// GetAllGenericVarList 获取泛型变量的所有结构
func GetAllGenericVarList(astType Type) (varList []AnnotateGenericVarState) {
switch subAst := astType.(type) {
case *MultiType:
if len(subAst.TypeList) == 0 {
return
}

// 有多种类型,是或者的关系,因此获取多个
for _, oneType := range subAst.TypeList {
tmpList := GetAllGenericVarList(oneType)
varList = append(varList, tmpList...)
}

return varList

case *NormalType:
varList = append(varList, AnnotateGenericVarState{
NormalStr: subAst.StrName,
})
return varList

case *TableType:
varList = append(varList, AnnotateGenericVarState{
NormalStr: "table",
})
return varList

case *FuncType:
varList = append(varList, AnnotateGenericVarState{
NormalStr: "function",
})
return varList

case *ArrayType:
varList = append(varList, AnnotateGenericVarState{
NormalStr: TypeConvertStr(subAst.ItemType),
IsArrayType: true,
})
return varList
}
return
}

// GetAllFuncType 判断是否指向的是一个函数的类型
func GetAllFuncType(astType Type) (funcType Type) {
switch subAst := astType.(type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (l *AnnotateLexer) NextTokenStruct() {
}

c := l.chunk[0]
if c == '_' || isLetter(c) || isDigit(c) {
if c == '_' || isLetter(c) || isDigit(c) || isBacktick(c) {
token := l.scanIdentifier()
if kind, found := keywords[token]; found {
l.setNowToken(kind, token)
Expand Down Expand Up @@ -296,7 +296,7 @@ func (l *AnnotateLexer) scanIdentifier() string {
i := 1
for ; i < len(l.chunk); i++ {
c := l.chunk[i]
if isLetter(c) || isDigit(c) || c == '_' || c == '.' {
if isLetter(c) || isDigit(c) || isBacktick(c) || c == '_' || c == '.' {
continue
}

Expand Down Expand Up @@ -456,3 +456,7 @@ func isLetter(c byte) bool {
func isDigit(c byte) bool {
return c >= '0' && c <= '9'
}

func isBacktick(c byte) bool {
return c == '`'
}
2 changes: 1 addition & 1 deletion luahelper-lsp/langserver/check/check_find_var_refer.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ func (a *AllProject) getFuncRelateSymbol(luaInFile string, node *ast.FuncCallExp
if nameExp, ok := node.PrefixExp.(*ast.NameExp); ok && node.NameExp == nil {
strName := nameExp.Name
// 这两个函数,在变量的referInfo里面已经存在了
if strName == "require" || common.GConfig.IsFrameReferOtherFile(strName) {
if (strName == "require" || strName == "import") || common.GConfig.IsFrameReferOtherFile(strName) {
//return nil
referSymbol := a.getImportReferSymbol(luaInFile, node, comParam, findExpList)
return referSymbol
Expand Down
165 changes: 158 additions & 7 deletions luahelper-lsp/langserver/check/check_lsp_annotate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package check

import (
"fmt"
"luahelper-lsp/langserver/check/annotation/annotateast"
"luahelper-lsp/langserver/check/common"
"luahelper-lsp/langserver/check/compiler/ast"
Expand All @@ -21,6 +22,7 @@ func (a *AllProject) checkOneFileType(annotateFile *common.AnnotateFile, fragemn
if fragemnet.GenericInfo != nil {
for _, oneGeneric := range fragemnet.GenericInfo.GenericInfoList {
genericMap[oneGeneric.Name] = struct{}{}
genericMap[fmt.Sprintf("`%s`", oneGeneric.Name)] = struct{}{}
}
}

Expand Down Expand Up @@ -772,8 +774,9 @@ func (a *AllProject) getFuncGenericVarInfo(oldSymbol *common.Symbol, fragment *c
return
}

normalStrList := annotateast.GetAllNormalStrList(funcAnnotateType)
for _, oneStr := range normalStrList {
normalVarList := annotateast.GetAllGenericVarList(funcAnnotateType)
for _, oneVar := range normalVarList {
var oneStr = oneVar.NormalStr
// 判断这个字符串是否有关联到泛型
flag := false
for _, genericInfo := range fragment.GenericInfo.GenericInfoList {
Expand Down Expand Up @@ -803,11 +806,18 @@ func (a *AllProject) getFuncGenericVarInfo(oldSymbol *common.Symbol, fragment *c
var findIndex int = -1
for _, oneParam := range fragment.ParamInfo.ParamList {
strParamNormalType := annotateast.TraverseOneType(oneParam.ParamType)
if strParamNormalType != oneStr {
oneVar.IsBacktick = strParamNormalType[0] == '`'

if strParamNormalType != oneStr && strParamNormalType != fmt.Sprintf("`%s`", oneStr) {
continue
}

for index, strParam := range funcInfo.ParamList {
var paramList = funcInfo.ParamList
if len(funcInfo.ParamList) > 0 && funcInfo.ParamList[0] == "self" {
paramList = funcInfo.ParamList[1:]
}

for index, strParam := range paramList {
if strParam == oneParam.Name {
findIndex = index
break
Expand All @@ -829,10 +839,151 @@ func (a *AllProject) getFuncGenericVarInfo(oldSymbol *common.Symbol, fragment *c
break
}

tempFindVarReferSymbol := func(luaInFile string, node ast.Exp, comParam *CommonFuncParam, findExpList *[]common.FindExpFile, varIndex uint8) *common.Symbol {
tempSymbol := a.FindVarReferSymbol(luaInFile, node, comParam, findExpList, varIndex)
// 当使用有 ---@generic V 标注的方法时,如果传入的变量声明于使用的文件时,会出现找不到定义的问题
//
// 例如:在 hover_generic_define.lua 中有个全局方法 clone
// ---@generic V
// ---@param obj V
// ---@return V
// function clone(obj)
// end
//
// 然后在 hover_generic.lua 中,有如下语句:
// local classLocal = require('hover_generic_class')
// local cloneGoods2 = clone(classLocal)
// 此时,cloneGoods2 的提示会返回 'local cloneGoods2 : V'
//
// 因为当解析完 clone 之后,luaInFile 会变为 hover_generic_define.lua
// 上面的求导语句会变为仅从 hover_generic_define.lua 中寻找 classLocal 类型定义
//
// 所以下面补充逻辑:当上方定义找不到后,这里尝试从代码的源头位置 findExpList[0] 额外搜寻一次,也就是 hover_generic.lua 中尝试寻找
if tempSymbol == nil && len(*findExpList) > 0 {
tempSymbol = a.FindVarReferSymbol((*findExpList)[0].FileName, node, comParam, findExpList, varIndex)
}
return tempSymbol
}

paramExp := node.Args[findIndex]
paramVarFile := a.FindVarReferSymbol(oldSymbol.FileName, paramExp, comParam, findExpList, 1)
if paramVarFile != nil {
return paramVarFile
// 是否为字符串表达式类型的参数 ---@param V `T`
if oneVar.IsBacktick {
multiType := &annotateast.MultiType{}

// 如果参数是字符串,则直接返回字面表达的类型
// 例如:GoodsBuildByName('GoodsModule'),则返回 GoodsModule 类型进行查找定义
if exp, ok := paramExp.(*ast.StringExp); ok {
multiType.Loc = lexer.GetRangeLoc(&exp.Loc, &exp.Loc)
multiType.TypeList = append(multiType.TypeList, &annotateast.NormalType{
StrName: exp.Str,
NameLoc: exp.Loc,
ShowColor: false,
})

} else {
// 传入的是常量定义,先获取常量定义的值结果
paramVarFile := tempFindVarReferSymbol(oldSymbol.FileName, paramExp, comParam, findExpList, 1)
if paramVarFile != nil {
// 如果定义类型为引用,例如:
// local nameGlobal = GoodsDefine.BaseGoods
// 则额外获取一次 GoodsDefine.BaseGoods 的值结果:'GoodsModule'
referExp := paramVarFile.VarInfo.ReferExp
if _, ok := referExp.(*ast.TableAccessExp); ok {
if tempSymbol := a.FindVarReferSymbol(oldSymbol.FileName, referExp, comParam, findExpList, 1); tempSymbol != nil {
paramVarFile = tempSymbol
}
}
}
if paramVarFile != nil {
// 根据字符串值,求导对应的声明定义
referExp := paramVarFile.VarInfo.ReferExp
multiType.Loc = common.GetExpLoc(referExp)
multiType.TypeList = append(multiType.TypeList, &annotateast.NormalType{
StrName: common.GetExpName(referExp),
NameLoc: common.GetExpLoc(referExp),
ShowColor: false,
})
}
}

// 解析结果额外套一层数组类型
if oneVar.IsArrayType {
multiType = &annotateast.MultiType{
Loc: common.GetExpLoc(funcAnnotateType),
TypeList: []annotateast.Type{
&annotateast.ArrayType{
Loc: common.GetExpLoc(funcAnnotateType),
ItemType: multiType,
},
},
}
}

findSymbol = &common.Symbol{
FileName: oldSymbol.FileName, // todo这里的文件名不太准确
VarInfo: nil,
AnnotateType: multiType,
VarFlag: common.FirstVarFlag, // 默认还是先获取的变量
AnnotateLine: oldSymbol.VarInfo.Loc.StartLine - 1, // todo这里的行号不太准确
}
return findSymbol

} else {
paramVarFile := tempFindVarReferSymbol(oldSymbol.FileName, paramExp, comParam, findExpList, 1)
if paramVarFile != nil {
// 如果定义类型为引用,例如:
// local classGlobal = GoodsClass.BaseClass
// 则额外获取一次最终的值结果:'GoodsModule'
referExp := paramVarFile.VarInfo.ReferExp
if _, ok := referExp.(*ast.TableAccessExp); ok {
if tempSymbol := a.FindVarReferSymbol(oldSymbol.FileName, referExp, comParam, findExpList, 1); tempSymbol != nil {
paramVarFile = tempSymbol
}
}
}
if paramVarFile != nil {
// 如果是 require 求导类型,可能会遇到 findExpList 中存在查找记录,从而返回 nil 的情况。例如:
// local classLocal = require('hover_generic_class')
// local goodsIns12 = Instances.GoodsIns.CloneGoods(classLocal)
// 从左向右会先求导 Instances.GoodsIns 的结果,文件 hover_generic_config.lua 中定义的 require('hover_generic_class') 的查找位置就会被记录进 findExpList
// 继续执行到后面 classLocal 类型的求导时,会因为 a.FindVarReferSymbol 中的 isHasFindExpFile 方法,验证为同一位置的重复的检索,从而返回 nil结果,不能正确的推导出结果
// 所以,这里尝试传入空的查找记录,让 a.FindVarReferSymbol 新去检索推导结果
referExp := paramVarFile.VarInfo.ReferExp
if _, ok := referExp.(*ast.FuncCallExp); ok {
subFindExpList := []common.FindExpFile{}
if tempSymbol := a.FindVarReferSymbol(oldSymbol.FileName, referExp, comParam, &subFindExpList, 1); tempSymbol != nil {
paramVarFile = tempSymbol
}
}
}
if paramVarFile != nil {
if oneVar.IsArrayType {

// 如果是需要推导的类型,就先推导出结果,再让下面套上数据结构
if paramVarFile.AnnotateType == nil {
if tempVarFile := a.FindVarReferSymbol(paramVarFile.FileName, paramVarFile.VarInfo.ReferExp, comParam, findExpList, 1); tempVarFile != nil {
paramVarFile = tempVarFile
}
}

// 解析结果额外套一层数组类型
paramVarFile.AnnotateType = &annotateast.MultiType{
Loc: common.GetExpLoc(funcAnnotateType),
TypeList: []annotateast.Type{
&annotateast.ArrayType{
Loc: common.GetExpLoc(funcAnnotateType),
ItemType: paramVarFile.AnnotateType,
},
},
}

return paramVarFile

} else {

return paramVarFile
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion luahelper-lsp/langserver/check/check_lsp_define.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ func (a *AllProject) FindVarDefine(strFile string, varStruct *common.DefineVarSt
return
}

if varStruct.StrVec[0] == "require" && varStruct.IsFuncVec[0] && varStruct.Exp != nil {
if (varStruct.StrVec[0] == "require" || varStruct.StrVec[0] == "import") && varStruct.IsFuncVec[0] && varStruct.Exp != nil {
findExpList := []common.FindExpFile{}
oldSymbol = a.FindVarReferSymbol(comParam.fileResult.Name, varStruct.Exp, comParam, &findExpList, 1)

Expand Down
2 changes: 1 addition & 1 deletion luahelper-lsp/langserver/check/check_lsp_hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ func (a *AllProject) findVarDefineForHover(strFile string, varStruct *common.Def
return
}

if varStruct.StrVec[0] == "require" && varStruct.IsFuncVec[0] && varStruct.Exp != nil {
if (varStruct.StrVec[0] == "require" || varStruct.StrVec[0] == "import") && varStruct.IsFuncVec[0] && varStruct.Exp != nil {
findExpList := []common.FindExpFile{}
oldSymbol = a.FindVarReferSymbol(comParam.fileResult.Name, varStruct.Exp, comParam, &findExpList, 1)

Expand Down
4 changes: 2 additions & 2 deletions luahelper-lsp/langserver/check/check_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,7 @@ func recurseExpToDefine(exp ast.Exp, defineVar *common.DefineVarStruct) {
defineVar.IsFuncVec = append(defineVar.IsFuncVec, false)
case *ast.FuncCallExp:
if subExp, flag := expV.PrefixExp.(*ast.NameExp); flag {
if subExp.Name == "require" {
if subExp.Name == "require" || subExp.Name == "import" {
defineVar.Exp = exp
}
}
Expand Down Expand Up @@ -791,7 +791,7 @@ func ExpToDefineVarStruct(exp ast.Exp) (defineVar common.DefineVarStruct) {
case *ast.FuncCallExp:
defineVar.ValidFlag = true
if subExp, flag := expV.PrefixExp.(*ast.NameExp); flag {
if subExp.Name == "require" {
if subExp.Name == "require" || subExp.Name == "import" {
defineVar.Exp = exp
}
}
Expand Down
4 changes: 3 additions & 1 deletion luahelper-lsp/langserver/check/common/global_conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ func (g *GlobalConfig) setSysNotUseMap() {
g.ignoreSysNoUseMap["rawlen"] = true
g.ignoreSysNoUseMap["rawset"] = true
g.ignoreSysNoUseMap["require"] = true
g.ignoreSysNoUseMap["import"] = true
g.ignoreSysNoUseMap["select"] = true
g.ignoreSysNoUseMap["setmetatable"] = true
g.ignoreSysNoUseMap["tonumber"] = true
Expand Down Expand Up @@ -821,7 +822,7 @@ func (g *GlobalConfig) InsertIngoreSystemModule() {
g.IgnoreVarMap["warn"] = "function"
g.IgnoreVarMap["xpcall"] = "function"
g.IgnoreVarMap["unpack"] = "function"
g.IgnoreVarMap["require"] = "function"
g.IgnoreVarMap["import"] = "function"
}

// InsertIngoreSystemAnnotateType 当为本地运行时,忽略系统的注解类型type。批量插入
Expand Down Expand Up @@ -1241,6 +1242,7 @@ func (g *GlobalConfig) GetAllReferFileTypes() (strArray []string) {
strArray = append(strArray, "dofile")
strArray = append(strArray, "loadfile")
strArray = append(strArray, "require")
strArray = append(strArray, "import")
for _, oneReferFrame := range GConfig.ReferFrameFiles {
strArray = append(strArray, oneReferFrame.Name)
}
Expand Down
2 changes: 2 additions & 0 deletions luahelper-lsp/langserver/check/common/refer_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func StrToReferType(referTypeStr string) (referType ReferType) {
referType = ReferTypeLoadfile
} else if referTypeStr == "require" {
referType = ReferTypeRequire
} else if referTypeStr == "import" {
referType = ReferTypeRequire
} else {
if GConfig.IsFrameReferOtherFile(referTypeStr) {
referType = ReferTypeFrame
Expand Down
Loading