diff --git a/errgoengine.go b/errgoengine.go index 2455877..cdcfaf1 100644 --- a/errgoengine.go +++ b/errgoengine.go @@ -91,6 +91,12 @@ func (e *ErrgoEngine) Analyze(workingPath, msg string) (*CompiledErrorTemplate, Document: doc, Nearest: WrapNode(doc, nearest), } + } else if template == FallbackErrorTemplate { + contextData.MainError = &MainError{ + ErrorNode: nil, + Document: nil, + Nearest: SyntaxNode{}, + } } else { // return error template for bugbuddy to handle // incomplete error messages @@ -106,13 +112,18 @@ func (e *ErrgoEngine) Analyze(workingPath, msg string) (*CompiledErrorTemplate, func (e *ErrgoEngine) Translate(template *CompiledErrorTemplate, contextData *ContextData) (mainExp string, fullExp string) { expGen := &ExplainGenerator{errorName: template.Name} - fixGen := &BugFixGenerator{ - Document: contextData.MainError.Document, + fixGen := &BugFixGenerator{} + if contextData.MainError != nil { + fixGen.Document = contextData.MainError.Document } // execute error generator function template.OnGenExplainFn(contextData, expGen) - template.OnGenBugFixFn(contextData, fixGen) + + // execute bug fix generator function + if template.OnGenBugFixFn != nil { + template.OnGenBugFixFn(contextData, fixGen) + } output := e.OutputGen.Generate(contextData, expGen, fixGen) defer e.OutputGen.Reset() diff --git a/error_template.go b/error_template.go index b25b57f..f14e7cb 100644 --- a/error_template.go +++ b/error_template.go @@ -39,6 +39,9 @@ func (tmp *CompiledErrorTemplate) StackTraceRegex() *regexp.Regexp { } func (tmp *CompiledErrorTemplate) ExtractVariables(msg string) map[string]string { + if tmp.Pattern == nil { + return map[string]string{} + } variables := map[string]string{} groupNames := tmp.Pattern.SubexpNames() for _, submatches := range tmp.Pattern.FindAllStringSubmatch(msg, -1) { @@ -55,10 +58,13 @@ func (tmp *CompiledErrorTemplate) ExtractVariables(msg string) map[string]string func (tmp *CompiledErrorTemplate) ExtractStackTrace(cd *ContextData) TraceStack { traceStack := TraceStack{} - workingPath := cd.WorkingPath + stackTraceRegex := tmp.StackTraceRegex() + if stackTraceRegex == nil { + return traceStack + } + workingPath := cd.WorkingPath rawStackTraceItem := cd.Variables["stacktrace"] - stackTraceRegex := tmp.StackTraceRegex() symbolGroupIdx := stackTraceRegex.SubexpIndex("symbol") pathGroupIdx := stackTraceRegex.SubexpIndex("path") posGroupIdx := stackTraceRegex.SubexpIndex("position") @@ -94,6 +100,9 @@ func (tmp *CompiledErrorTemplate) ExtractStackTrace(cd *ContextData) TraceStack } func (tmp *CompiledErrorTemplate) Match(str string) bool { + if tmp == FallbackErrorTemplate { + return true + } return tmp.Pattern.MatchString(str) } @@ -187,5 +196,28 @@ func (tmps ErrorTemplates) Find(language, name string) *CompiledErrorTemplate { } func TemplateKey(language, name string) string { + if len(language) == 0 { + return name + } return fmt.Sprintf("%s.%s", language, name) } + +var FallbackErrorTemplate = &CompiledErrorTemplate{ + ErrorTemplate: ErrorTemplate{ + Name: "UnknownError", + Pattern: `.*`, + OnGenExplainFn: func(cd *ContextData, gen *ExplainGenerator) { + gen.Add("There are no available error templates for this error.\n") + gen.Add("```\n") + gen.Add(cd.Variables["message"]) + gen.Add("\n```") + }, + }, + Language: &Language{ + AnalyzerFactory: func(cd *ContextData) LanguageAnalyzer { + return nil + }, + }, + Pattern: nil, + StackTracePattern: nil, +} diff --git a/error_templates/fallback/fallback_test.go b/error_templates/fallback/fallback_test.go new file mode 100644 index 0000000..6ceaaca --- /dev/null +++ b/error_templates/fallback/fallback_test.go @@ -0,0 +1,17 @@ +package error_templates_test + +import ( + "testing" + + lib "github.com/nedpals/errgoengine" + testutils "github.com/nedpals/errgoengine/error_templates/test_utils" +) + +func TestFallbackErrorTemplate(t *testing.T) { + testutils.SetupTest(t, testutils.SetupTestConfig{ + DirName: "fallback", + TemplateLoader: func(et *lib.ErrorTemplates) { + (*et)[lib.TemplateKey("", lib.FallbackErrorTemplate.Name)] = lib.FallbackErrorTemplate + }, + }).Execute(t) +} diff --git a/error_templates/fallback/test_files/random/random_program.testlang b/error_templates/fallback/test_files/random/random_program.testlang new file mode 100644 index 0000000..9bd19a2 --- /dev/null +++ b/error_templates/fallback/test_files/random/random_program.testlang @@ -0,0 +1 @@ +hi im a random program! diff --git a/error_templates/fallback/test_files/random/test.txt b/error_templates/fallback/test_files/random/test.txt new file mode 100644 index 0000000..2f191ab --- /dev/null +++ b/error_templates/fallback/test_files/random/test.txt @@ -0,0 +1,8 @@ +template: "UnknownError" +--- +oh no i'm an error! :<<< + +=== +template: "UnknownError" +--- +aaa diff --git a/error_templates/test_utils/test_file_parser.go b/error_templates/test_utils/test_file_parser.go index 1e25991..238a242 100644 --- a/error_templates/test_utils/test_file_parser.go +++ b/error_templates/test_utils/test_file_parser.go @@ -236,10 +236,20 @@ func (p *Parser) ParseInputExpected(filename string, input string) (*TestOutput, return nil, nil, err } + if len(inputOut.Language) != 0 && len(inputOut.Template) == 0 { + inputOut.Template = inputOut.Language + inputOut.Language = "" + } + expOut, err := p.Parse(strings.NewReader(rawOutputs[1])) if err != nil { return nil, nil, err } + if len(expOut.Language) != 0 && len(expOut.Template) == 0 { + expOut.Template = expOut.Language + expOut.Language = "" + } + return inputOut, expOut, nil } diff --git a/error_templates/test_utils/test_utils.go b/error_templates/test_utils/test_utils.go index a79d51e..704a3b5 100644 --- a/error_templates/test_utils/test_utils.go +++ b/error_templates/test_utils/test_utils.go @@ -111,7 +111,7 @@ func SetupTest(tb testing.TB, cfg SetupTestConfig) TestCases { return e } - if expTemp.Language.MatchPath(path) { + if (expTemp == lib.FallbackErrorTemplate && !d.IsDir()) || expTemp.Language.MatchPath(path) { fileContent, err := os.ReadFile(path) if err != nil { return err diff --git a/output_gen.go b/output_gen.go index c22a0cb..fbedefb 100644 --- a/output_gen.go +++ b/output_gen.go @@ -82,7 +82,7 @@ func (gen *OutputGenerator) Generate(cd *ContextData, explain *ExplainGenerator, gen.generateFromExp(1, explain) doc := cd.MainError.Document - if gen.IsTesting && !cd.MainError.Nearest.IsNull() { + if doc != nil && gen.IsTesting && !cd.MainError.Nearest.IsNull() { startLineNr := cd.MainError.Nearest.StartPosition().Line startLines := doc.LinesAt(max(startLineNr-1, 0), startLineNr) endLines := doc.LinesAt(min(startLineNr+1, doc.TotalLines()), min(startLineNr+2, doc.TotalLines())) diff --git a/trace_stack.go b/trace_stack.go index fa516aa..986ad29 100644 --- a/trace_stack.go +++ b/trace_stack.go @@ -12,6 +12,9 @@ func (st *TraceStack) Add(symbolName string, loc Location) { } func (st TraceStack) Top() StackTraceEntry { + if len(st) == 0 { + return StackTraceEntry{} + } return st[len(st)-1] }