Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e926e3c
先简单粗暴方式实现 import 具有和 require 一样的提示特性;后续再研究如何添加配置的方式实现自定义导入方法
kaishiqi May 11, 2024
fa2cbf2
尝试修复:使用泛型声明时,如果方法定义和传参定义不在同一个文件时,需要两边同时检索定义源
kaishiqi May 15, 2024
c837c8e
Merge branch 'Tencent:master' into master
kaishiqi May 15, 2024
f123dbd
尝试修复泛型的推导不准确问题;对泛型支持字符串类型表达;对泛型返回数组格式支持
kaishiqi Jun 2, 2024
b9c07e6
Merge branch 'Tencent:master' into master
kaishiqi Jun 28, 2024
640fc23
增加ignore文件
yinfei8 Jun 28, 2024
7cf9289
提交mac版本二进制
yinfei8 Jun 28, 2024
10b1ce5
添加arm版本二进制
yinfei8 Jul 1, 2024
14b2a6b
增加linux的版本
yinfei8 Jul 1, 2024
40920c0
修改windows版本的二进制
yinfei8 Jul 1, 2024
2e94ae6
修改变更的日期
yinfei8 Jul 1, 2024
aa74487
优化性能,只增量处理有变更的文件的enum宏段
yinfei8 Jul 1, 2024
c4a25d9
继续加强泛型的推导能力:对类成员中定义了泛型方法,可以跳过self参数位置而正确的识别;修复调用者定义类型和泛型传参类型相同而不能正确推导的问题
kaishiqi Jul 1, 2024
02c1092
Merge remote-tracking branch 'Tencent/master'
kaishiqi Jul 1, 2024
148a287
Merge branch 'Tencent:master' into master
kaishiqi Jul 2, 2024
4e608cd
Merge branch 'Tencent:master' into master
kaishiqi Oct 15, 2024
d6967fe
@field 类型:语法上支持可选?的格式
kaishiqi Apr 6, 2025
4efbc96
Merge branch 'Tencent:master' into master
kaishiqi Apr 6, 2025
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 @@ -54,6 +54,7 @@ type AnnotateFieldState struct {
FieldScopeType FieldScopeType // 属性的类型 public、protected、private
FieldColonType FieldColonType // 属性是否为:
FiledType Type // 成员对应属性
IsOptional bool // 这个参数是否为可选的。例如 ---@field one? number ; 参数后面跟?表示参数是可选的
Comment string // 其他所有的注释内容
CommentLoc lexer.Location // 注释的位置信息
}
Expand Down Expand Up @@ -90,6 +91,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 == '`'
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ func parserFieldState(l *annotatelexer.AnnotateLexer) annotateast.AnnotateState
if l.LookAheadKind() == annotatelexer.ATokenSepColon {
l.NextToken()
fieldState.FieldColonType = annotateast.FieldColonYes
// 判断是否为可选的 ?
} else if l.LookAheadKind() == annotatelexer.ATokenOption {
fieldState.IsOptional = true
l.NextToken()
}

// 获取对应的type
Expand Down
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
Loading