|
1 | 1 | package parser
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bufio" |
4 | 5 | "context"
|
5 | 6 | "errors"
|
| 7 | + "fmt" |
6 | 8 | "io"
|
7 | 9 | "io/fs"
|
8 | 10 | "os"
|
@@ -166,18 +168,69 @@ func (p *Parser) ParseFS(ctx context.Context, dir string) error {
|
166 | 168 | }
|
167 | 169 | sort.Strings(paths)
|
168 | 170 | for _, path := range paths {
|
169 |
| - if err := p.ParseFile(ctx, path); err != nil { |
170 |
| - if p.stopOnHCLError { |
| 171 | + var err error |
| 172 | + if err = p.ParseFile(ctx, path); err == nil { |
| 173 | + continue |
| 174 | + } |
| 175 | + |
| 176 | + if p.stopOnHCLError { |
| 177 | + return err |
| 178 | + } |
| 179 | + var diags hcl.Diagnostics |
| 180 | + if errors.As(err, &diags) { |
| 181 | + errc := p.showParseErrors(p.moduleFS, path, diags) |
| 182 | + if errc == nil { |
| 183 | + continue |
| 184 | + } |
| 185 | + p.logger.Error("Failed to get the causes of the parsing error", log.Err(errc)) |
| 186 | + } |
| 187 | + p.logger.Error("Error parsing file", log.FilePath(path), log.Err(err)) |
| 188 | + continue |
| 189 | + } |
| 190 | + |
| 191 | + return nil |
| 192 | +} |
| 193 | + |
| 194 | +func (p *Parser) showParseErrors(fsys fs.FS, filePath string, diags hcl.Diagnostics) error { |
| 195 | + file, err := fsys.Open(filePath) |
| 196 | + if err != nil { |
| 197 | + return fmt.Errorf("failed to read file: %w", err) |
| 198 | + } |
| 199 | + defer file.Close() |
| 200 | + |
| 201 | + for _, diag := range diags { |
| 202 | + if subj := diag.Subject; subj != nil { |
| 203 | + lines, err := readLinesFromFile(file, subj.Start.Line, subj.End.Line) |
| 204 | + if err != nil { |
171 | 205 | return err
|
172 | 206 | }
|
173 |
| - p.logger.Error("Error parsing file", log.FilePath(path), log.Err(err)) |
174 |
| - continue |
| 207 | + |
| 208 | + cause := strings.Join(lines, "\n") |
| 209 | + p.logger.Error("Error parsing file", log.FilePath(filePath), |
| 210 | + log.String("cause", cause), log.Err(diag)) |
175 | 211 | }
|
176 | 212 | }
|
177 | 213 |
|
178 | 214 | return nil
|
179 | 215 | }
|
180 | 216 |
|
| 217 | +func readLinesFromFile(f io.Reader, from, to int) ([]string, error) { |
| 218 | + scanner := bufio.NewScanner(f) |
| 219 | + rawLines := make([]string, 0, to-from+1) |
| 220 | + |
| 221 | + for lineNum := 0; scanner.Scan() && lineNum < to; lineNum++ { |
| 222 | + if lineNum >= from-1 { |
| 223 | + rawLines = append(rawLines, scanner.Text()) |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + if err := scanner.Err(); err != nil { |
| 228 | + return nil, fmt.Errorf("failed to scan file: %w", err) |
| 229 | + } |
| 230 | + |
| 231 | + return rawLines, nil |
| 232 | +} |
| 233 | + |
181 | 234 | var ErrNoFiles = errors.New("no files found")
|
182 | 235 |
|
183 | 236 | func (p *Parser) Load(ctx context.Context) (*evaluator, error) {
|
|
0 commit comments