Skip to content

Commit 76c553d

Browse files
committed
feat: support for stub files in libraries
1 parent 8f8238d commit 76c553d

File tree

3 files changed

+108
-3
lines changed

3 files changed

+108
-3
lines changed

errgoengine.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,21 @@ import (
1212
type ErrgoEngine struct {
1313
SharedStore *Store
1414
ErrorTemplates ErrorTemplates
15-
FS fs.ReadFileFS
15+
FS *MultiReadFileFS
1616
OutputGen *OutputGenerator
1717
}
1818

1919
func New() *ErrgoEngine {
20+
filesystems := make([]fs.ReadFileFS, 2)
21+
filesystems[0] = &RawFS{}
22+
2023
return &ErrgoEngine{
2124
SharedStore: NewEmptyStore(),
2225
ErrorTemplates: ErrorTemplates{},
23-
FS: &RawFS{},
24-
OutputGen: &OutputGenerator{},
26+
FS: &MultiReadFileFS{
27+
FSs: filesystems,
28+
},
29+
OutputGen: &OutputGenerator{},
2530
}
2631
}
2732

@@ -34,6 +39,7 @@ func (e *ErrgoEngine) Analyze(workingPath, msg string) (*CompiledErrorTemplate,
3439
// initial context data extraction
3540
contextData := NewContextData(e.SharedStore, workingPath)
3641
contextData.Analyzer = template.Language.AnalyzerFactory(contextData)
42+
e.FS.FSs[1] = template.Language.stubFs
3743

3844
groupNames := template.Pattern.SubexpNames()
3945
for _, submatches := range template.Pattern.FindAllStringSubmatch(msg, -1) {
@@ -88,6 +94,11 @@ func (e *ErrgoEngine) Analyze(workingPath, msg string) (*CompiledErrorTemplate,
8894
return nil, nil, err
8995
}
9096

97+
// Skip stub files
98+
if len(contents) == 0 {
99+
continue
100+
}
101+
91102
var selectedLanguage *Language
92103
existingDoc, docExists := contextData.Documents[node.DocumentPath]
93104

fs.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,95 @@ import (
44
"io"
55
"io/fs"
66
"os"
7+
"time"
78
)
89

10+
type MultiReadFileFS struct {
11+
FSs []fs.ReadFileFS
12+
}
13+
14+
func (mfs *MultiReadFileFS) Open(name string) (fs.File, error) {
15+
for _, fs := range mfs.FSs {
16+
if fs == nil {
17+
continue
18+
}
19+
20+
if file, err := fs.Open(name); err == nil {
21+
return file, nil
22+
}
23+
}
24+
return nil, os.ErrNotExist
25+
}
26+
27+
type stubFileInfo struct {
28+
name string
29+
}
30+
31+
func (*stubFileInfo) Name() string { return "" }
32+
33+
func (*stubFileInfo) Size() int64 { return 0 }
34+
35+
func (*stubFileInfo) Mode() fs.FileMode { return 0400 }
36+
37+
func (*stubFileInfo) ModTime() time.Time { return time.Now() }
38+
39+
func (*stubFileInfo) IsDir() bool { return false }
40+
41+
func (*stubFileInfo) Sys() any { return nil }
42+
43+
type StubFile struct {
44+
Name string
45+
}
46+
47+
func (*StubFile) Read(bt []byte) (int, error) { return 0, io.EOF }
48+
49+
func (vf *StubFile) Stat() (fs.FileInfo, error) { return &stubFileInfo{vf.Name}, nil }
50+
51+
func (*StubFile) Close() error { return nil }
52+
53+
type StubFS struct {
54+
Files []*StubFile
55+
}
56+
57+
func (vfs *StubFS) StubFile(name string) *StubFile {
58+
file := &StubFile{
59+
Name: name,
60+
}
61+
vfs.Files = append(vfs.Files, file)
62+
return file
63+
}
64+
65+
func (vfs *StubFS) Open(name string) (fs.File, error) {
66+
for _, file := range vfs.Files {
67+
if file.Name == name {
68+
return file, nil
69+
}
70+
}
71+
return nil, os.ErrNotExist
72+
}
73+
74+
func (vfs *StubFS) ReadFile(name string) ([]byte, error) {
75+
for _, file := range vfs.Files {
76+
if file.Name == name {
77+
return make([]byte, 0), nil
78+
}
79+
}
80+
return nil, os.ErrNotExist
81+
}
82+
83+
func (mfs *MultiReadFileFS) ReadFile(name string) ([]byte, error) {
84+
for _, fs := range mfs.FSs {
85+
if fs == nil {
86+
continue
87+
}
88+
89+
if file, err := fs.Open(name); err == nil {
90+
return io.ReadAll(file)
91+
}
92+
}
93+
return nil, os.ErrNotExist
94+
}
95+
996
type RawFS struct{}
1097

1198
func (*RawFS) Open(name string) (fs.File, error) {

language.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type LanguageAnalyzer interface {
2222
type Language struct {
2323
isCompiled bool
2424
stackTraceRegex *regexp.Regexp
25+
stubFs *StubFS
2526
Name string
2627
FilePatterns []string
2728
SitterLanguage *sitter.Language
@@ -30,6 +31,7 @@ type Language struct {
3031
SymbolsToCapture string
3132
LocationConverter func(path, pos string) Location
3233
AnalyzerFactory func(cd *ContextData) LanguageAnalyzer
34+
OnGenStubFS func(fs *StubFS)
3335
}
3436

3537
func (lang *Language) MatchPath(path string) bool {
@@ -58,6 +60,11 @@ func (lang *Language) Compile() {
5860
panic(fmt.Sprintf("[Language -> %s] AnalyzerFactory must not be nil", lang.Name))
5961
}
6062

63+
if lang.stubFs == nil {
64+
lang.stubFs = &StubFS{}
65+
lang.OnGenStubFS(lang.stubFs)
66+
}
67+
6168
lang.isCompiled = true
6269
}
6370

0 commit comments

Comments
 (0)