@@ -20,47 +20,49 @@ type ErrorInfo struct {
20
20
Tool string
21
21
}
22
22
23
- func (s * server ) TranspileAndBuild (file * GnoFile ) ([]ErrorInfo , error ) {
24
- pkgDir := filepath .Dir (file .URI .Filename ())
25
- pkgName := filepath .Base (pkgDir )
26
- tmpDir := filepath .Join (s .env .GNOHOME , "gnopls" , "tmp" , pkgName )
23
+ func (s * server ) Transpile () ([]ErrorInfo , error ) {
24
+ moduleName := filepath .Base (s .workspaceFolder )
25
+ tmpDir := filepath .Join (s .env .GNOHOME , "gnopls" , "tmp" , moduleName )
27
26
28
- err := copyDir (pkgDir , tmpDir )
27
+ err := copyDir (s . workspaceFolder , tmpDir )
29
28
if err != nil {
30
29
return nil , err
31
30
}
32
31
33
- preOut , _ := tools .Transpile (tmpDir )
34
- slog .Info (string (preOut ))
32
+ preOut , errTranspile := tools .Transpile (tmpDir )
35
33
if len (preOut ) > 0 {
36
- return parseErrors (file , string (preOut ), "transpile" )
34
+ // parse errors even if errTranspile!=nil bc that's always the case if
35
+ // there's errors to parse.
36
+ slog .Info ("transpile error" , "out" , string (preOut ), "err" , errTranspile )
37
+ errors , errParse := s .parseErrors (string (preOut ), "transpile" )
38
+ if errParse != nil {
39
+ return nil , errParse
40
+ }
41
+ if len (errors ) == 0 && errTranspile != nil {
42
+ // no parsed errors but errTranspile!=nil, this is an unexpected error.
43
+ // (for example the gno binary was not found)
44
+ return nil , errTranspile
45
+ }
46
+ return errors , nil
37
47
}
38
-
39
- buildOut , _ := tools .Build (tmpDir )
40
- slog .Info (string (buildOut ))
41
- return parseErrors (file , string (buildOut ), "build" )
48
+ return nil , nil
42
49
}
43
50
44
51
// This is used to extract information from the `gno build` command
45
52
// (see `parseError` below).
46
53
//
47
54
// TODO: Maybe there's a way to get this in a structured format?
55
+ // -> will be available in go1.24 with `go build -json`
48
56
var errorRe = regexp .MustCompile (`(?m)^([^#]+?):(\d+):(\d+):(.+)$` )
49
57
50
- // parseErrors parses the output of the `gno build` command for errors.
51
- //
52
- // They look something like this:
58
+ // parseErrors parses the output of the `gno transpile -gobuild` command for
59
+ // errors.
53
60
//
61
+ // The format is:
54
62
// ```
55
- // command-line-arguments
56
- // # command-line-arguments
57
- // <file>:20:9: undefined: strin
58
- //
59
- // <pkg_path>: build pkg: std go compiler: exit status 1
60
- //
61
- // 1 go build errors
63
+ // <file.gno>:<line>:<col>: <error>
62
64
// ```
63
- func parseErrors ( file * GnoFile , output , cmd string ) ([]ErrorInfo , error ) {
65
+ func ( s * server ) parseErrors ( output , cmd string ) ([]ErrorInfo , error ) {
64
66
errors := []ErrorInfo {}
65
67
66
68
matches := errorRe .FindAllStringSubmatch (output , - 1 )
@@ -69,24 +71,39 @@ func parseErrors(file *GnoFile, output, cmd string) ([]ErrorInfo, error) {
69
71
}
70
72
71
73
for _ , match := range matches {
74
+ path := match [1 ]
72
75
line , err := strconv .Atoi (match [2 ])
73
76
if err != nil {
74
- return nil , err
77
+ return nil , fmt . Errorf ( "parseErrors '%s': %w" , match , err )
75
78
}
76
79
77
80
column , err := strconv .Atoi (match [3 ])
78
81
if err != nil {
79
- return nil , err
82
+ return nil , fmt . Errorf ( "parseErrors '%s': %w" , match , err )
80
83
}
81
- slog .Info ("parsing" , "line" , line , "column" , column , "msg" , match [4 ])
82
-
83
- errorInfo := findError (file , match [1 ], line , column , match [4 ], cmd )
84
- errors = append (errors , errorInfo )
84
+ msg := strings .TrimSpace (match [4 ])
85
+ slog .Debug ("parseErrors" , "path" , path , "line" , line , "column" , column , "msg" , msg )
86
+ errors = append (errors , ErrorInfo {
87
+ FileName : filepath .Join (s .workspaceFolder , path ),
88
+ Line : line ,
89
+ Column : column ,
90
+ Span : []int {column , column },
91
+ Msg : msg ,
92
+ Tool : cmd ,
93
+ })
85
94
}
86
95
87
96
return errors , nil
88
97
}
89
98
99
+ // NOTE(tb): This function tries to guess the column start and end of the
100
+ // error, by splitting the line into tokens (space separated). While this
101
+ // might work most of the time, in some cases it might not, so I think
102
+ // it is preferable not to try to guess and just return:
103
+ // column_start = column_end
104
+ // just like the output of gno transpile which only returns the start of the
105
+ // column. This is why this function is no longer invoked in parseError.
106
+ //
90
107
// findError finds the error in the document, shifting the line and column
91
108
// numbers to account for the header information in the generated Go file.
92
109
func findError (file * GnoFile , fname string , line , col int , msg string , tool string ) ErrorInfo {
0 commit comments