diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 8a6a66f..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 3cab335..f2cb9cc 100644 --- a/.gitignore +++ b/.gitignore @@ -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* diff --git a/luahelper-lsp/langserver/check/annotation/annotateast/annotate_state.go b/luahelper-lsp/langserver/check/annotation/annotateast/annotate_state.go index 411bc6f..812d434 100644 --- a/luahelper-lsp/langserver/check/annotation/annotateast/annotate_state.go +++ b/luahelper-lsp/langserver/check/annotation/annotateast/annotate_state.go @@ -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 // 定义的类型 diff --git a/luahelper-lsp/langserver/check/annotation/annotateast/annotate_util.go b/luahelper-lsp/langserver/check/annotation/annotateast/annotate_util.go index e60a6ef..6afa01c 100644 --- a/luahelper-lsp/langserver/check/annotation/annotateast/annotate_util.go +++ b/luahelper-lsp/langserver/check/annotation/annotateast/annotate_util.go @@ -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) { diff --git a/luahelper-lsp/langserver/check/annotation/annotatelexer/annotate_lexer.go b/luahelper-lsp/langserver/check/annotation/annotatelexer/annotate_lexer.go index 651fb65..9ca594d 100644 --- a/luahelper-lsp/langserver/check/annotation/annotatelexer/annotate_lexer.go +++ b/luahelper-lsp/langserver/check/annotation/annotatelexer/annotate_lexer.go @@ -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) @@ -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 } @@ -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 == '`' +} diff --git a/luahelper-lsp/langserver/check/check_find_var_refer.go b/luahelper-lsp/langserver/check/check_find_var_refer.go index b35e3d7..aef4c36 100644 --- a/luahelper-lsp/langserver/check/check_find_var_refer.go +++ b/luahelper-lsp/langserver/check/check_find_var_refer.go @@ -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 diff --git a/luahelper-lsp/langserver/check/check_lsp_annotate.go b/luahelper-lsp/langserver/check/check_lsp_annotate.go index 27dadf9..8008c96 100644 --- a/luahelper-lsp/langserver/check/check_lsp_annotate.go +++ b/luahelper-lsp/langserver/check/check_lsp_annotate.go @@ -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" @@ -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{}{} } } @@ -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 { @@ -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 @@ -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 + } + } } } diff --git a/luahelper-lsp/langserver/check/check_lsp_define.go b/luahelper-lsp/langserver/check/check_lsp_define.go index 6ed5350..449672f 100644 --- a/luahelper-lsp/langserver/check/check_lsp_define.go +++ b/luahelper-lsp/langserver/check/check_lsp_define.go @@ -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) diff --git a/luahelper-lsp/langserver/check/check_lsp_hover.go b/luahelper-lsp/langserver/check/check_lsp_hover.go index bfb861c..b80e2aa 100644 --- a/luahelper-lsp/langserver/check/check_lsp_hover.go +++ b/luahelper-lsp/langserver/check/check_lsp_hover.go @@ -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) diff --git a/luahelper-lsp/langserver/check/check_util.go b/luahelper-lsp/langserver/check/check_util.go index b621879..4d17ff0 100644 --- a/luahelper-lsp/langserver/check/check_util.go +++ b/luahelper-lsp/langserver/check/check_util.go @@ -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 } } @@ -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 } } diff --git a/luahelper-lsp/langserver/check/common/global_conf.go b/luahelper-lsp/langserver/check/common/global_conf.go index a091d2d..54d4ca5 100644 --- a/luahelper-lsp/langserver/check/common/global_conf.go +++ b/luahelper-lsp/langserver/check/common/global_conf.go @@ -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 @@ -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。批量插入 @@ -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) } diff --git a/luahelper-lsp/langserver/check/common/refer_info.go b/luahelper-lsp/langserver/check/common/refer_info.go index 4c8e981..0c76bde 100644 --- a/luahelper-lsp/langserver/check/common/refer_info.go +++ b/luahelper-lsp/langserver/check/common/refer_info.go @@ -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 diff --git a/luahelper-lsp/langserver/check/common/system_tips.go b/luahelper-lsp/langserver/check/common/system_tips.go index 5a26f96..96b4933 100644 --- a/luahelper-lsp/langserver/check/common/system_tips.go +++ b/luahelper-lsp/langserver/check/common/system_tips.go @@ -239,6 +239,14 @@ func (g *GlobalConfig) InitSystemTips() { g.SystemTipsMap["require"] = requireNoticeInfo g.insertSysVarInfo("require", &requireNoticeInfo, nil) + importNoticeInfo := SystemNoticeInfo{ + Detail: "[_G] import(modname)", + Documentation: "Loads the given module", + FuncParamVec: []FuncParamInfo{{"modname", "modname : string"}}, + } + g.SystemTipsMap["import"] = importNoticeInfo + g.insertSysVarInfo("import", &importNoticeInfo, nil) + selectNoticeInfo := SystemNoticeInfo{ Detail: "[_G] select(index, ...)", Documentation: "If `index` is a number, returns all arguments after argument number, `index`. a negative number indexes from the end (-1 is the last argument).", diff --git a/luahelper-lsp/langserver/textdocument_hover_test.go b/luahelper-lsp/langserver/textdocument_hover_test.go index 92fc636..83d072c 100644 --- a/luahelper-lsp/langserver/textdocument_hover_test.go +++ b/luahelper-lsp/langserver/textdocument_hover_test.go @@ -1175,6 +1175,142 @@ func TestHover13(t *testing.T) { } } +// 泛型类型 +func TestHover14(t *testing.T) { + _, filename, _, _ := runtime.Caller(0) + paths, _ := filepath.Split(filename) + + strRootPath := paths + "../testdata/hover" + strRootPath, _ = filepath.Abs(strRootPath) + + strRootURI := "file://" + strRootPath + lspServer := createLspTest(strRootPath, strRootURI) + context := context.Background() + + fileName := strRootPath + "/" + "hover_generic.lua" + data, err := ioutil.ReadFile(fileName) + + if err != nil { + t.Fatalf("read file:%s err=%s", fileName, err.Error()) + } + openParams := lsp.DidOpenTextDocumentParams{ + TextDocument: lsp.TextDocumentItem{ + URI: lsp.DocumentURI(fileName), + Text: string(data), + }, + } + err1 := lspServer.TextDocumentDidOpen(context, openParams) + if err1 != nil { + t.Fatalf("didopen file:%s err=%s", fileName, err1.Error()) + } + + var resultList []string = []string{} + var positionList []lsp.Position = []lsp.Position{} + // 全局方法定义测试 + positionList = append(positionList, lsp.Position{Line: 46, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 47, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 48, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 49, Character: 8}) + resultList = append(resultList, "local cloneGoods1 : EmptyObject") + resultList = append(resultList, "local cloneGoods2 : GoodsModule") + resultList = append(resultList, "local cloneGoods3 : GoodsModule") + resultList = append(resultList, "local cloneGoods4 : GoodsModule") + // 局部方法定义测试 + positionList = append(positionList, lsp.Position{Line: 51, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 52, Character: 8}) + resultList = append(resultList, "local classGoods1 : GoodsModule") + resultList = append(resultList, "local classGoods2 : GoodsModule") + // 字符串泛型定义测试 + positionList = append(positionList, lsp.Position{Line: 54, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 55, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 56, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 57, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 58, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 59, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 60, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 61, Character: 8}) + resultList = append(resultList, "local nameGoods1 : GoodsModule") + resultList = append(resultList, "local nameGoods2 : GoodsModule") + resultList = append(resultList, "local nameGoods3 : GoodsModule") + resultList = append(resultList, "local nameGoods4 : GoodsModule") + resultList = append(resultList, "local nameGoods5 : GoodsModule") + resultList = append(resultList, "local nameGoods6 : GoodsModule") + resultList = append(resultList, "local nameGoods7 : GoodsModule") + resultList = append(resultList, "local nameGoods8 : GoodsModule") + // 数组泛型定义测试 + positionList = append(positionList, lsp.Position{Line: 63, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 64, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 65, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 66, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 67, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 68, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 69, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 70, Character: 8}) + resultList = append(resultList, "local goodsList1 : GoodsModule[]") + resultList = append(resultList, "local goodsList2 : GoodsModule[]") + resultList = append(resultList, "local goodsList3 : GoodsModule[]") + resultList = append(resultList, "local goodsList4 : GoodsModule[]") + resultList = append(resultList, "local goodsList5 : GoodsModule[]") + resultList = append(resultList, "local goodsList6 : GoodsModule[]") + resultList = append(resultList, "local goodsList7 : GoodsModule[]") + resultList = append(resultList, "local goodsList8 : GoodsModule[]") + // 类成员方法定义测试 + positionList = append(positionList, lsp.Position{Line: 72, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 73, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 74, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 75, Character: 8}) + resultList = append(resultList, "local goodsIns11 : EmptyObject") + resultList = append(resultList, "local goodsIns12 : GoodsModule") + resultList = append(resultList, "local goodsIns13 : GoodsModule") + resultList = append(resultList, "local goodsIns14 : GoodsModule") + positionList = append(positionList, lsp.Position{Line: 76, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 77, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 78, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 79, Character: 8}) + resultList = append(resultList, "local goodsIns21 : GoodsModule") + resultList = append(resultList, "local goodsIns22 : GoodsModule") + resultList = append(resultList, "local goodsIns23 : GoodsModule") + resultList = append(resultList, "local goodsIns24 : GoodsModule") + positionList = append(positionList, lsp.Position{Line: 80, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 81, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 82, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 83, Character: 8}) + resultList = append(resultList, "local goodsIns31 : EmptyObject") + resultList = append(resultList, "local goodsIns32 : GoodsModule") + resultList = append(resultList, "local goodsIns33 : GoodsModule") + resultList = append(resultList, "local goodsIns34 : GoodsModule") + positionList = append(positionList, lsp.Position{Line: 84, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 85, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 86, Character: 8}) + positionList = append(positionList, lsp.Position{Line: 87, Character: 8}) + resultList = append(resultList, "local goodsIns41 : GoodsModule[]") + resultList = append(resultList, "local goodsIns42 : GoodsModule[]") + resultList = append(resultList, "local goodsIns43 : GoodsModule[]") + resultList = append(resultList, "local goodsIns44 : GoodsModule[]") + + for index, onePoisiton := range positionList { + hoverParams := lsp.TextDocumentPositionParams{ + TextDocument: lsp.TextDocumentIdentifier{ + URI: lsp.DocumentURI(fileName), + }, + Position: onePoisiton, + } + hoverReturn1, err1 := lspServer.TextDocumentHover(context, hoverParams) + if err1 != nil { + t.Fatalf("TextDocumentHover file:%s err=%s", fileName, err1.Error()) + } + + hoverMarkUpReturn1, _ := hoverReturn1.(MarkupHover) + t.Log(hoverMarkUpReturn1.Contents.Value) + + oneStr := resultList[index] + if !strings.Contains(hoverMarkUpReturn1.Contents.Value, oneStr) { + t.Fatalf("hover error, not find str=%s, index=%d", oneStr, index) + } + + } +} + // expand local 扩展变量,出现了的变量 func TestHoverExpandLocal(t *testing.T) { _, filename, _, _ := runtime.Caller(0) diff --git a/luahelper-lsp/testdata/hover/hover_generic.lua b/luahelper-lsp/testdata/hover/hover_generic.lua new file mode 100644 index 0000000..656721b --- /dev/null +++ b/luahelper-lsp/testdata/hover/hover_generic.lua @@ -0,0 +1,88 @@ + +---@class UnitObject +local UnitClass = class('UnitObject') + + +---@class HeroObject : UnitObject +local HeroObject = class('HeroObject', UnitObject) + + +---@class EmptyObject : UnitObject +local EmptyObject = class('EmptyObject', UnitObject) + + +---@generic T +---@param classType T +---@return T +function GoodsBuild(classType) +end + + +---@generic T +---@param className `T` +---@return T +function GoodsBuildByName(className) +end + + +---@generic T +---@param classType T +---@return T[] +function GoodsBuilds(classType) +end + + +---@generic T +---@param className `T` +---@return T[] +function GoodsBuildsByName(className) +end + + +local nameLocal = 'GoodsModule' +local nameGlobal = GoodsDefine.BaseGoods +local classLocal = require('hover_generic_class') +local classGlobal = GoodsClass.BaseClass +-- 全局方法定义测试 +local cloneGoods1 = clone(EmptyObject) +local cloneGoods2 = clone(classLocal) +local cloneGoods3 = clone(classGlobal) +local cloneGoods4 = clone(GoodsClass.BaseClass) +-- 局部方法定义测试 +local classGoods1 = GoodsBuild(classLocal) +local classGoods2 = GoodsBuild(classGlobal) +-- 字符串泛型定义测试 +local nameGoods1 = GoodsBuildByName('GoodsModule') +local nameGoods2 = GoodsBuildByName(nameLocal) +local nameGoods3 = GoodsBuildByName(nameGlobal) +local nameGoods4 = GoodsBuildByName(GoodsDefine.BaseGoods) +local nameGoods5 = createByName('GoodsModule') +local nameGoods6 = createByName(nameLocal) +local nameGoods7 = createByName(nameGlobal) +local nameGoods8 = createByName(GoodsDefine.BaseGoods) +-- 数组泛型定义测试 +local goodsList1 = GoodsBuilds(classLocal) +local goodsList2 = GoodsBuilds(GoodsClass.BaseClass) +local goodsList3 = GoodsBuildsByName('GoodsModule') +local goodsList4 = GoodsBuildsByName(nameGlobal) +local goodsList5 = GoodsBuildsByName(GoodsDefine.BaseGoods) +local goodsList6 = createListByName('GoodsModule') +local goodsList7 = createListByName(nameGlobal) +local goodsList8 = createListByName(GoodsDefine.BaseGoods) +-- 类成员方法定义测试 +local goodsIns11 = Instances.GoodsIns:CloneGoods(EmptyObject) +local goodsIns12 = Instances.GoodsIns.CloneGoods(classLocal) +local goodsIns13 = Instances.GoodsIns:CloneGoods(classGlobal) +local goodsIns14 = Instances.GoodsIns:CloneGoods(GoodsClass.BaseClass) +local goodsIns21 = Instances.GoodsIns:CreateGoods('GoodsModule') +local goodsIns22 = Instances.GoodsIns:CreateGoods(nameLocal) +local goodsIns23 = Instances.GoodsIns:CreateGoods(nameGlobal) +local goodsIns24 = Instances.GoodsIns:CreateGoods(GoodsDefine.BaseGoods) +local goodsIns31 = Instances.GoodsIns:CloneGoodsList(EmptyObject) +local goodsIns32 = Instances.GoodsIns:CloneGoodsList(classLocal) +local goodsIns33 = Instances.GoodsIns:CloneGoodsList(classGlobal) +local goodsIns34 = Instances.GoodsIns:CloneGoodsList(GoodsClass.BaseClass) +local goodsIns41 = Instances.GoodsIns:CreateGoodsList('GoodsModule') +local goodsIns42 = Instances.GoodsIns:CreateGoodsList(nameLocal) +local goodsIns43 = Instances.GoodsIns:CreateGoodsList(nameGlobal) +local goodsIns44 = Instances.GoodsIns:CreateGoodsList(GoodsDefine.BaseGoods) diff --git a/luahelper-lsp/testdata/hover/hover_generic_class.lua b/luahelper-lsp/testdata/hover/hover_generic_class.lua new file mode 100644 index 0000000..091bd4b --- /dev/null +++ b/luahelper-lsp/testdata/hover/hover_generic_class.lua @@ -0,0 +1,56 @@ +---@class GoodsModule +local GoodsModule = class('GoodsModule') + + +---@return GoodsModule +function GoodsModule.new() +end + + +---@return GoodsModule +function GoodsModule.GetInstance() +end + + +function GoodsModule:init() + self.goodsId = 0 + self.goodsType = 0 + self.goodsNum = 0 + self.goodsName = '' +end + + +---@return boolean +function GoodsModule:isNew() +end + + +---@generic T +---@param goodsObj T +---@return T +function GoodsModule:CloneGoods(goodsObj) +end + + +---@generic T +---@param goodsObj T +---@return T[] +function GoodsModule:CloneGoodsList(goodsObj) +end + + +---@generic T +---@param goodsName `T` +---@return T +function GoodsModule:CreateGoods(goodsName) +end + + +---@generic T +---@param goodsName `T` +---@return T[] +function GoodsModule:CreateGoodsList(goodsName) +end + + +return GoodsModule diff --git a/luahelper-lsp/testdata/hover/hover_generic_config.lua b/luahelper-lsp/testdata/hover/hover_generic_config.lua new file mode 100644 index 0000000..e074e69 --- /dev/null +++ b/luahelper-lsp/testdata/hover/hover_generic_config.lua @@ -0,0 +1,15 @@ + +GoodsDefine = { + BaseGoods = 'GoodsModule', + CardGoods = 'CardGoodsModule', +} + + +GoodsClass = { + BaseClass = require('hover_generic_class') +} + + +Instances = { + GoodsIns = require('hover_generic_class').GetInstance() +} diff --git a/luahelper-lsp/testdata/hover/hover_generic_define.lua b/luahelper-lsp/testdata/hover/hover_generic_define.lua new file mode 100644 index 0000000..ad74da6 --- /dev/null +++ b/luahelper-lsp/testdata/hover/hover_generic_define.lua @@ -0,0 +1,20 @@ + +---@generic V +---@param obj V +---@return V +function clone(obj) +end + + +---@generic V +---@param name `V` +---@return V +function createByName(name) +end + + +---@generic V +---@param name `V` +---@return V[] +function createListByName(name) +end diff --git a/luahelper-vscode/src/debug/luaDebug.ts b/luahelper-vscode/src/debug/luaDebug.ts index 9723076..48fcbff 100644 --- a/luahelper-vscode/src/debug/luaDebug.ts +++ b/luahelper-vscode/src/debug/luaDebug.ts @@ -17,7 +17,7 @@ import * as Net from 'net'; import { DataProcessor } from './dataProcessor'; import { DebugLogger } from '../common/logManager'; //import { StatusBarManager } from '../common/statusBarManager'; -import { LineBreakpoint, ConditionBreakpoint, LogPoint } from './breakpoint'; +import { LineBreakpoint, ConditionBreakpoint, LogPoint } from './breakPoint'; import { Tools } from '../common/tools'; //import { UpdateManager } from './updateManager'; import { ThreadManager } from '../common/threadManager'; diff --git a/luahelper-vscode/syntaxes/lua.json b/luahelper-vscode/syntaxes/lua.json index ca438b4..00190ff 100644 --- a/luahelper-vscode/syntaxes/lua.json +++ b/luahelper-vscode/syntaxes/lua.json @@ -800,7 +800,7 @@ ] }, { - "begin": "(?=[a-zA-Z_\\.\\*\"'])", + "begin": "(?=[a-zA-Z_\\.\\*\"'`])", "end": "(?=[\\s\\),\\?])", "patterns": [ {