-
Notifications
You must be signed in to change notification settings - Fork 5
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
llcppg:refactor to type-node level #157
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #157 +/- ##
==========================================
- Coverage 98.16% 93.17% -5.00%
==========================================
Files 17 18 +1
Lines 2179 2768 +589
==========================================
+ Hits 2139 2579 +440
- Misses 28 149 +121
- Partials 12 40 +28 ☔ View full report in Codecov by Sentry. |
708189f
to
a08a1c9
Compare
a08a1c9
to
eab96aa
Compare
066596f
to
c66e188
Compare
4fad511
to
09c19eb
Compare
2c989d3
to
730eb1c
Compare
ef18c3b
to
b0f5135
Compare
b0f5135
to
c6cda4e
Compare
if err != nil { | ||
return err | ||
} | ||
p.Process(order) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Process
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在代码中调用了函数 p.Process
,但没有检查其返回的错误值。根据Go语言的最佳实践,应该始终检查函数的错误返回值,以确保程序的健壮性。
错误用法
func main() {
p := &Processor{}
p.Process()
}
在这个示例中,调用了 p.Process()
但没有检查其返回的错误值。
正确用法
func main() {
p := &Processor{}
if err := p.Process(); err != nil {
log.Fatalf("Process failed: %v", err)
}
}
在这个示例中,调用了 p.Process()
并检查了其返回的错误值。如果错误不为空,则使用 log.Fatalf
记录错误并终止程序。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
return err | ||
} | ||
p.Process(order) | ||
p.Pkg.WritePkgFiles() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.WritePkgFiles
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在调用函数 p.Pkg.WritePkgFiles
时,其返回的错误值 err
没有被检查。虽然Go语言鼓励显式处理错误,但有时开发者可能会忽略错误检查,这可能导致潜在的问题。
错误用法
以下是一个示例代码,展示了不正确的用法:
func writePackageFiles(p *Pkg) {
p.Pkg.WritePkgFiles()
}
在这个例子中,p.Pkg.WritePkgFiles()
的返回值 err
被忽略了。
正确用法
以下是一个示例代码,展示了正确的用法:
func writePackageFiles(p *Pkg) error {
err := p.Pkg.WritePkgFiles()
if err != nil {
return fmt.Errorf("failed to write package files: %w", err)
}
return nil
}
在这个例子中,p.Pkg.WritePkgFiles()
的返回值 err
被检查。如果 err
不为 nil
,则返回一个包含错误信息的新的错误。这样可以确保在发生错误时能够及时处理和记录。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
} | ||
p.Process(order) | ||
p.Pkg.WritePkgFiles() | ||
p.Pkg.WriteLinkFile() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.WriteLinkFile
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在代码中调用了函数 p.Pkg.WriteLinkFile
,但没有检查该函数的返回值中的错误(error)。根据Go语言的最佳实践,应该始终检查函数的返回值中的错误,以确保程序的健壮性。
错误用法
以下是一个示例代码,展示了不正确的用法:
func main() {
p := &Package{}
p.Pkg.WriteLinkFile("path/to/file")
}
在这个示例中,调用了 p.Pkg.WriteLinkFile
但没有检查其返回的错误值。
正确用法
以下是一个示例代码,展示了正确的用法:
func main() {
p := &Package{}
err := p.Pkg.WriteLinkFile("path/to/file")
if err != nil {
// 处理错误
log.Fatalf("Failed to write link file: %v", err)
}
}
在这个示例中,调用了 p.Pkg.WriteLinkFile
并检查了其返回的错误值。如果错误不为空,则进行相应的处理(例如记录日志并退出程序)。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
p.Process(order) | ||
p.Pkg.WritePkgFiles() | ||
p.Pkg.WriteLinkFile() | ||
p.Pkg.WritePubFile() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.WritePubFile
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在调用函数 p.Pkg.WritePubFile
时,其返回的错误值 err
没有被检查。虽然Go语言鼓励显式处理错误,但有时开发者可能会忽略错误检查,这可能导致潜在的问题。
错误用法
以下是一个示例代码,展示了不正确的用法:
func writePubFile(p *Package) {
p.Pkg.WritePubFile("path/to/file")
}
在这个例子中,p.Pkg.WritePubFile
的返回值 err
被忽略了。
正确用法
以下是一个示例代码,展示了正确的用法:
func writePubFile(p *Package) error {
err := p.Pkg.WritePubFile("path/to/file")
if err != nil {
return fmt.Errorf("failed to write pub file: %w", err)
}
return nil
}
在这个例子中,p.Pkg.WritePubFile
的返回值 err
被检查。如果 err
不为 nil
,则返回一个包含错误信息的新的错误。这样可以确保在调用该函数时能够正确处理可能发生的错误。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
switch decl := typ.(type) { | ||
case *ast.TypeDecl: | ||
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File])) | ||
p.Pkg.ConvertTypeDecl(decl) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.ConvertTypeDecl
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在调用函数 p.Pkg.ConvertTypeDecl
时,其返回的错误值 err
没有被检查。虽然Go语言鼓励显式处理错误,但未检查错误可能会导致程序在遇到错误时继续执行,从而引发难以调试的问题。
错误用法
以下是一个示例代码,展示了不正确的用法:
func convertTypeDecl(p *Package) {
p.Pkg.ConvertTypeDecl()
}
在这个例子中,p.Pkg.ConvertTypeDecl()
的返回值 err
被忽略了。
正确用法
以下是一个示例代码,展示了正确的用法:
func convertTypeDecl(p *Package) error {
if err := p.Pkg.ConvertTypeDecl(); err != nil {
return fmt.Errorf("failed to convert type declaration: %w", err)
}
return nil
}
在这个例子中,p.Pkg.ConvertTypeDecl()
的返回值 err
被检查。如果 err
不为 nil
,则返回一个包含错误信息的新的错误。这样可以确保在遇到错误时能够正确处理并传递错误信息。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
p.Pkg.ConvertTypeDecl(decl) | ||
case *ast.EnumTypeDecl: | ||
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File])) | ||
p.Pkg.ConvertEnumTypeDecl(decl) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.ConvertEnumTypeDecl
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在函数 p.Pkg.ConvertEnumTypeDecl
的调用中,返回的错误值没有被检查。在Go语言中,函数通常会返回一个或多个值,其中最后一个值通常是错误(error)类型。如果调用者不检查这个错误值,可能会导致程序在遇到错误时继续执行,从而引发不可预测的行为。
错误用法
以下是一个示例代码,展示了如何错误地使用 p.Pkg.ConvertEnumTypeDecl
函数:
func someFunction(p *SomePackage) {
p.Pkg.ConvertEnumTypeDecl()
}
在这个例子中,p.Pkg.ConvertEnumTypeDecl()
的返回值没有被检查。
正确用法
以下是一个示例代码,展示了如何正确地使用 p.Pkg.ConvertEnumTypeDecl
函数:
func someFunction(p *SomePackage) {
if err := p.Pkg.ConvertEnumTypeDecl(); err != nil {
// 处理错误
log.Fatalf("Failed to convert enum type decl: %v", err)
}
}
在这个例子中,p.Pkg.ConvertEnumTypeDecl()
的返回值被检查,并且如果发生错误,程序会记录错误并退出。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
p.Pkg.ConvertEnumTypeDecl(decl) | ||
case *ast.TypedefDecl: | ||
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File])) | ||
p.Pkg.ConvertTypedefDecl(decl) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error return value of p.Pkg.ConvertTypedefDecl
is not checked (errcheck)
Details
lint 解释
这个lint结果表明在函数 p.Pkg.ConvertTypedefDecl
的调用中,返回的错误值没有被检查。在Go语言中,函数通常会返回一个或多个值,其中一个值是错误信息(error)。如果忽略了这个错误值,可能会导致程序在遇到错误时无法正确处理,从而引发潜在的问题。
错误用法
以下是一个示例代码,展示了不正确的用法:
func main() {
p := &Package{}
p.Pkg.ConvertTypedefDecl()
}
在这个例子中,p.Pkg.ConvertTypedefDecl()
调用没有检查返回的错误值。
正确用法
以下是一个示例代码,展示了正确的用法:
func main() {
p := &Package{}
if err := p.Pkg.ConvertTypedefDecl(); err != nil {
// 处理错误
log.Fatalf("Error converting typedef declaration: %v", err)
}
}
在这个例子中,p.Pkg.ConvertTypedefDecl()
调用的返回值被检查,并且在遇到错误时进行了处理。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
if err != nil { | ||
t.Fatal(err) | ||
} | ||
for _, fi := range outDir { | ||
if strings.HasSuffix(fi.Name(), "go.mod") || strings.HasSuffix(fi.Name(), "go.sum") || strings.HasSuffix(fi.Name(), "llcppg.pub") { | ||
continue | ||
} else { | ||
content, err := os.ReadFile(filepath.Join(outputDir, fi.Name())) | ||
content, err := os.ReadFile(filepath.Join(testInfo.outputDir, fi.Name())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shadow: declaration of "err" shadows declaration at line 156 (govet)
Details
lint 解释
shadow: declaration of "err" shadows declaration at line 156 (govet)
这个lint结果表示在代码中,变量 err
在当前作用域内被重新声明了。这可能会导致混淆和潜在的错误,因为之前的 err
变量可能没有被正确使用。
错误用法
func example() error {
err := someFunction()
if err != nil {
return err
}
// 其他代码
err := anotherFunction() // 这里重新声明了 err,导致 shadow 警告
if err != nil {
return err
}
return nil
}
正确用法
func example() error {
err := someFunction()
if err != nil {
return err
}
// 其他代码
anotherErr := anotherFunction() // 使用不同的变量名避免 shadow
if anotherErr != nil {
return anotherErr
}
return nil
}
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
t.Fatal(err) | ||
} | ||
defer func() { | ||
if err := os.Chdir(originalWd); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shadow: declaration of "err" shadows declaration at line 537 (govet)
Details
lint 解释
shadow: declaration of "err" shadows declaration at line 537 (govet)
这个lint结果表示在代码中,变量 err
在当前作用域内被重新声明了。这可能会导致混淆和潜在的错误,因为之前的 err
变量可能没有被正确使用。
错误用法
func example() error {
err := someFunction()
if err != nil {
return err
}
// 其他代码
err := anotherFunction() // 这里重新声明了 err,导致之前的 err 被覆盖
if err != nil {
return err
}
return nil
}
正确用法
func example() error {
err := someFunction()
if err != nil {
return err
}
// 其他代码
anotherErr := anotherFunction() // 使用不同的变量名避免 shadow
if anotherErr != nil {
return anotherErr
}
return nil
}
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
return nil | ||
} | ||
|
||
func (p *Package) ConvertTypeDecl(typeDecl *ast.TypeDecl) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
359-398 lines are duplicate of cmd/gogensig/convert/package.go:318-357
(dupl)
Details
lint 解释
这个lint结果表明在文件 cmd/gogensig/convert/package.go
中,从第359行到第398行的代码与从第318行到第357行的代码是完全重复的。这种重复性可能会导致代码冗余、维护困难以及潜在的错误。
错误用法
以下是一个示例,展示了可能的错误用法:
// 错误用法示例
func process() {
// 重复的代码块1
fmt.Println("Processing data")
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 重复的代码块2
fmt.Println("Processing data")
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
正确用法
以下是一个示例,展示了如何通过提取公共部分来避免重复:
// 正确用法示例
func process() {
// 提取公共部分到一个函数中
processData()
// 调用公共函数
processData()
}
func processData() {
fmt.Println("Processing data")
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
通过这种方式,可以减少代码冗余,提高代码的可维护性和可读性。
💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流
fix #61
fix #99
缺陷
目前Go Binding的生成逻辑是,根据获得的文件,均先处理其include文件,再处理文件本身。
对于大多数较为头文件组织清晰的库,可以正常进行转换,这里即会优先访问 type.h 处理 A的定义,然后在main.h 中正确的引用。
main.h
compat.h
但是根据C语言本省的特性,其Include的位置是可以存在于文件的任何位置的,对于如下姿势的声明方式,即不能做到正确转换,如下的用例即会存在先访问compat.h,但是此时A并没有定义。
main.h
compat.h
resolution
USR
通过libclang的USR的唯一标识,可以标识某个引用实际对应的类型。
这是对于
struct A
的描述。可以看到定义的时候Ident对应的USR是c:@S@A
,其 Field的USR是c:@S@A@FI@a
, 对于typedef A;
对应的USR即为c:main.h@T@A
, 并且其引用的Underlying Type即为引用 struct A;所以可以看到Type对应的USR即为c:@S@A
而对于compat.h 中的 typedef 的 引用可以看到正常的 引用了
c:main.h@T@A
通过类型引用关系重排文件顺序,保证被依赖的类型所在的文件会优先进行处理 (X,不可行)
可以解决如下问题,即根据类型引用可以分析得出 compat.h 的 B依赖了 A,所以优先处理main.h 的所有节点再处理compat.h 的定义。
compat.h
但是这个方案会导致以下用例中 main.h中的C定义时,B还未定义,所以基于引用关系分析出来的文件粒度的处理顺序,并不能满足当前需求。
main.h
compat.h
根据类型定义粒度,决定处理类型初始化的顺序。
可能可以创建那些类型定义节点,保证其在树中的结构,再根据引用关系逐渐完成类型初始化?