From 83aaa0eebab60cf23050febeed29e8745d3ce66e Mon Sep 17 00:00:00 2001 From: Vladyslav Kuksiuk Date: Thu, 21 May 2026 12:47:06 +0200 Subject: [PATCH 1/5] Add meaningful exception, when markdown fence is missing after embedding instruction. --- .DS_Store | Bin 0 -> 6148 bytes embedding/embedding_test.go | 13 +++++++++++++ embedding/parsing/blank_line.go | 3 +-- embedding/parsing/context.go | 7 +++++-- embedding/parsing/instruction_token.go | 10 ++++++++++ embedding/processor.go | 19 +++++++++++++++++++ test/resources/docs/missing-code-fence.md | 4 ++++ 7 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 .DS_Store create mode 100644 test/resources/docs/missing-code-fence.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3950d9ccd908de298273cef43c423c69bcced8c7 GIT binary patch literal 6148 zcmeHK%}T>S5T0$TO(;SS3Oz1(Ef}>5#Y?F51&ruHr8cD0V45xcv4>K~SzpK}@p+ut z-H4?XJc-yDnE7_+C(C>ZyIBAbt!Z=!Pz3-7m9XHVStArDU6F$I5DNW_2qK6fg?>0& z$!5o2WPskC3q2S>i1y3-8xO-og&2Jche^ocrKW&4NjHG99(@4!)YMMr4T^pEy<2r7qTAR-s zUZXBgyyl`V=glLpE*r3;hI~H?z#lf1+o`X@EsI-sK zyfUv~WCoZ4W?)kou=}4=*_4L4PiBA__%Q>tKS)$U-(qG^Zyjjp_mScyLJ}O)U4l?r z^etuvF@hpYDWWMA_KG1)Ir^o|^DSluO*sg?GCs$yEbI+M=+)6Lbvg*&AX{dD8CYhZ zXr@&<|1ZA3|1THuj2U1C{uKkF)DGG$Y{{OjE6veaD^VX%NhmKf_*sGjeH3FZ9mO?N aE$EjtK=dtU2GN7UKLVNtHq5}UGVlTH;Y||& literal 0 HcmV?d00001 diff --git a/embedding/embedding_test.go b/embedding/embedding_test.go index 6687ac6..592aedc 100644 --- a/embedding/embedding_test.go +++ b/embedding/embedding_test.go @@ -201,6 +201,19 @@ var _ = Describe("Embedding", func() { )) }) + It("should report a missing code fence after the instruction", func() { + docPath := fmt.Sprintf("%s/missing-code-fence.md", config.DocumentationRoot) + processor := embedding.NewProcessor(docPath, config) + + _, err := processor.Embed() + + Expect(err).Should(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring( + "missing-code-fence.md:3`: " + + "expected a markdown code fence after the embedding instruction", + )) + }) + // TODO:olena-zmiiova:https://github.com/SpineEventEngine/embed-code/issues/65 It("should successfully embed to a file in a nested dir", func() { Skip( diff --git a/embedding/parsing/blank_line.go b/embedding/parsing/blank_line.go index 9d43a81..d529080 100644 --- a/embedding/parsing/blank_line.go +++ b/embedding/parsing/blank_line.go @@ -32,8 +32,7 @@ type BlankLineState struct{} // Checks if the current line is empty and not part of a code fence, and if there is an embedding. // If these conditions are met, it returns true. Otherwise, it returns false. func (b BlankLineState) Recognize(context Context) bool { - isEmptyString := strings.TrimSpace(context.CurrentLine()) == "" - if !context.ReachedEOF() && isEmptyString { + if !context.ReachedEOF() && strings.TrimSpace(context.CurrentLine()) == "" { return !context.CodeFenceStarted && context.EmbeddingInstruction != nil } diff --git a/embedding/parsing/context.go b/embedding/parsing/context.go index 8eecb90..71014ad 100644 --- a/embedding/parsing/context.go +++ b/embedding/parsing/context.go @@ -160,10 +160,13 @@ func (c *Context) ResolveEmbeddingNotFound() { // // Also appends it to the list of such embeddings for logging. func (c *Context) ResolveUnacceptedEmbedding() { - currentEmbeddingInstruction := c.CurrentEmbedding().embeddingInstruction + currentEmbedding := c.CurrentEmbedding() + currentEmbedding.SourceEndIndex = c.lineIndex + currentEmbedding.resultEndIndex = len(c.Result) + currentEmbeddingInstruction := currentEmbedding.embeddingInstruction c.UnacceptedEmbeddings = append(c.UnacceptedEmbeddings, currentEmbeddingInstruction) c.embeddings = c.embeddings[:c.currentEmbeddingIndex()] - c.SetEmbedding(nil) + c.EmbeddingInstruction = nil } // SetEmbedding sets an embedding to Context. Also sets fileContainsEmbedding flag. diff --git a/embedding/parsing/instruction_token.go b/embedding/parsing/instruction_token.go index 8a85c52..4bde802 100644 --- a/embedding/parsing/instruction_token.go +++ b/embedding/parsing/instruction_token.go @@ -36,6 +36,11 @@ type InstructionParseError struct { Reason string } +// MissingCodeFenceError reports that an embedding instruction is not followed by a code fence. +type MissingCodeFenceError struct { + Line int +} + // Error returns a user-facing description of an embedding instruction parse failure. func (e InstructionParseError) Error() string { return fmt.Sprintf( @@ -44,6 +49,11 @@ func (e InstructionParseError) Error() string { ) } +// Error returns a user-facing description of a missing code fence after an instruction. +func (e MissingCodeFenceError) Error() string { + return "expected a markdown code fence after the embedding instruction" +} + // Recognize reports whether the current line in the parsing context starts with " 0 { return context.CurrentEmbedding().SourceStartIndex - 1 } @@ -256,6 +261,20 @@ func errorLine(context parsing.Context, err error) int { return context.CurrentIndex() } +// unacceptedTransitionError explains why the parser could not accept the current state. +func unacceptedTransitionError(context parsing.Context, err error) error { + if err != nil { + return err + } + if context.EmbeddingInstruction != nil && !context.CodeFenceStarted { + return parsing.MissingCodeFenceError{ + Line: context.EmbeddingInstruction.DocumentationLine, + } + } + + return fmt.Errorf("unexpected parser state at line %d", context.CurrentIndex()) +} + // Moves to the next state accordingly to a transition map from the current state. Reports whether // it successfully moved to the next state and returns the new state. func (p Processor) moveToNextState(state *parsing.State, context *parsing.Context) ( diff --git a/test/resources/docs/missing-code-fence.md b/test/resources/docs/missing-code-fence.md new file mode 100644 index 0000000..2162160 --- /dev/null +++ b/test/resources/docs/missing-code-fence.md @@ -0,0 +1,4 @@ +# Example without a code fence + + +public static void main(String[] args) { From 5d12056a3b177dca1b795e41836c2fe465d1722b Mon Sep 17 00:00:00 2001 From: Vladyslav Kuksiuk Date: Thu, 21 May 2026 13:16:22 +0200 Subject: [PATCH 2/5] Add exception for unclosed code fence. --- embedding/embedding_test.go | 13 +++++++++++++ embedding/parsing/instruction_token.go | 10 ++++++++++ embedding/processor.go | 9 +++++++++ test/resources/docs/unclosed-code-fence.md | 5 +++++ 4 files changed, 37 insertions(+) create mode 100644 test/resources/docs/unclosed-code-fence.md diff --git a/embedding/embedding_test.go b/embedding/embedding_test.go index 592aedc..5b4c657 100644 --- a/embedding/embedding_test.go +++ b/embedding/embedding_test.go @@ -214,6 +214,19 @@ var _ = Describe("Embedding", func() { )) }) + It("should report an unclosed code fence after the instruction", func() { + docPath := fmt.Sprintf("%s/unclosed-code-fence.md", config.DocumentationRoot) + processor := embedding.NewProcessor(docPath, config) + + _, err := processor.Embed() + + Expect(err).Should(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring( + "unclosed-code-fence.md:3`: " + + "the markdown code fence after the embedding instruction is not closed", + )) + }) + // TODO:olena-zmiiova:https://github.com/SpineEventEngine/embed-code/issues/65 It("should successfully embed to a file in a nested dir", func() { Skip( diff --git a/embedding/parsing/instruction_token.go b/embedding/parsing/instruction_token.go index 4bde802..de0f2c3 100644 --- a/embedding/parsing/instruction_token.go +++ b/embedding/parsing/instruction_token.go @@ -41,6 +41,11 @@ type MissingCodeFenceError struct { Line int } +// UnclosedCodeFenceError reports that an embedding code fence is not closed. +type UnclosedCodeFenceError struct { + Line int +} + // Error returns a user-facing description of an embedding instruction parse failure. func (e InstructionParseError) Error() string { return fmt.Sprintf( @@ -54,6 +59,11 @@ func (e MissingCodeFenceError) Error() string { return "expected a markdown code fence after the embedding instruction" } +// Error returns a user-facing description of an unclosed embedding code fence. +func (e UnclosedCodeFenceError) Error() string { + return "the markdown code fence after the embedding instruction is not closed" +} + // Recognize reports whether the current line in the parsing context starts with " 0 { return context.CurrentEmbedding().SourceStartIndex - 1 } @@ -266,6 +270,11 @@ func unacceptedTransitionError(context parsing.Context, err error) error { if err != nil { return err } + if context.EmbeddingInstruction != nil && context.CodeFenceStarted { + return parsing.UnclosedCodeFenceError{ + Line: context.EmbeddingInstruction.DocumentationLine, + } + } if context.EmbeddingInstruction != nil && !context.CodeFenceStarted { return parsing.MissingCodeFenceError{ Line: context.EmbeddingInstruction.DocumentationLine, diff --git a/test/resources/docs/unclosed-code-fence.md b/test/resources/docs/unclosed-code-fence.md new file mode 100644 index 0000000..30c9eeb --- /dev/null +++ b/test/resources/docs/unclosed-code-fence.md @@ -0,0 +1,5 @@ +# Example with an unclosed code fence + + +```java +public static void main(String[] args) { From b2d0673605673f132d7ed273a10ebc6d32bedbc4 Mon Sep 17 00:00:00 2001 From: Vladyslav Kuksiuk Date: Thu, 21 May 2026 13:29:12 +0200 Subject: [PATCH 3/5] Add meaningful error on pattern mismatch. --- embedding/embedding_test.go | 29 ++++++++++ embedding/parsing/instruction.go | 57 +++++++++++++++++--- embedding/parsing/instruction_test.go | 42 ++++++++++----- embedding/processor.go | 4 ++ fragmentation/resolver.go | 13 +++++ test/resources/docs/missing-end-pattern.md | 5 ++ test/resources/docs/missing-start-pattern.md | 5 ++ 7 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 test/resources/docs/missing-end-pattern.md create mode 100644 test/resources/docs/missing-start-pattern.md diff --git a/embedding/embedding_test.go b/embedding/embedding_test.go index 5b4c657..7295997 100644 --- a/embedding/embedding_test.go +++ b/embedding/embedding_test.go @@ -165,6 +165,35 @@ var _ = Describe("Embedding", func() { )) }) + It("should report all pattern matching errors", func() { + config.DocIncludes = []string{"missing-start-pattern.md", "missing-end-pattern.md"} + + var recovered any + func() { + defer func() { + recovered = recover() + }() + embedding.CheckUpToDate(config) + }() + + Expect(recovered).ShouldNot(BeNil()) + Expect(fmt.Sprint(recovered)).Should(And( + ContainSubstring("missing-start-pattern.md:3"), + ContainSubstring( + "no line in code file `file://", + ), + ContainSubstring( + "` matches the start pattern "+ + "`Pattern *doesNotExistStart*`", + ), + ContainSubstring("missing-end-pattern.md:3"), + ContainSubstring( + "` matches the end pattern "+ + "`Pattern *doesNotExistEnd*`", + ), + )) + }) + It("should embed with multi lined tag attributes", func() { docPath := fmt.Sprintf("%s/multi-lined-valid-tag-attributes.md", config.DocumentationRoot) processor := embedding.NewProcessor(docPath, config) diff --git a/embedding/parsing/instruction.go b/embedding/parsing/instruction.go index 13e6089..f84bac5 100644 --- a/embedding/parsing/instruction.go +++ b/embedding/parsing/instruction.go @@ -61,6 +61,24 @@ type Instruction struct { Configuration configuration.Configuration } +// PatternNotFoundError reports that a start or end pattern did not match the code file. +type PatternNotFoundError struct { + Line int + CodeFileReference string + Kind string + Pattern *Pattern +} + +// Error returns a user-facing description of an unmatched start or end pattern. +func (e PatternNotFoundError) Error() string { + return fmt.Sprintf( + "no line in code file `%s` matches the %s pattern `%s`", + e.CodeFileReference, + e.Kind, + e.Pattern, + ) +} + // NewInstruction creates an Instruction based on provided attributes and configuration. // // attributes — a map with string-typed both keys and values. Possible keys are: @@ -116,12 +134,19 @@ func NewInstruction( // // Returns an error if there was an error during reading the content. func (e Instruction) Content() ([]string, error) { + codeFileReference, err := fragmentation.ResolveCodeFileReference(e.CodeFile, e.Configuration) + if err != nil { + return nil, err + } fileContent, err := fragmentation.ResolveContent(e.CodeFile, e.Fragment, e.Configuration) if err != nil { return nil, err } if e.StartPattern != nil || e.EndPattern != nil { - fileContent = e.matchingLines(fileContent) + fileContent, err = e.matchingLines(fileContent, codeFileReference) + if err != nil { + return nil, err + } } return commentfilter.Filter( @@ -144,19 +169,29 @@ func (e Instruction) String() string { // Filters and returns a subset of input lines based on start and end patterns. // // lines — a list of strings representing the input lines. -func (e Instruction) matchingLines(lines []string) []string { +func (e Instruction) matchingLines(lines []string, codeFileReference string) ([]string, error) { startPosition := 0 if e.StartPattern != nil { - startPosition = e.matchGlob(e.StartPattern, lines, 0) + var err error + startPosition, err = e.matchGlob(e.StartPattern, lines, 0, "start", + codeFileReference) + if err != nil { + return nil, err + } } endPosition := len(lines) - 1 if e.EndPattern != nil { - endPosition = e.matchGlob(e.EndPattern, lines, startPosition) + var err error + endPosition, err = e.matchGlob(e.EndPattern, lines, startPosition, "end", + codeFileReference) + if err != nil { + return nil, err + } } requiredLines := lines[startPosition : endPosition+1] indentation := indent.MaxCommonIndentation(requiredLines) - return indent.CutIndent(requiredLines, indentation) + return indent.CutIndent(requiredLines, indentation), nil } // Returns the index of a first line that matches given pattern. @@ -166,15 +201,21 @@ func (e Instruction) matchingLines(lines []string) []string { // lines — a list of lines to search in. // // startFrom — an index from which to start searching. -func (e Instruction) matchGlob(pattern *Pattern, lines []string, startFrom int) int { +func (e Instruction) matchGlob(pattern *Pattern, lines []string, startFrom int, + kind string, codeFileReference string) (int, error) { lineCount := len(lines) resultLine := startFrom for resultLine < lineCount { line := lines[resultLine] if pattern.Match(line) { - return resultLine + return resultLine, nil } resultLine++ } - panic(fmt.Sprintf("there is no line matching `%s`", pattern)) + return 0, PatternNotFoundError{ + Line: e.DocumentationLine, + CodeFileReference: codeFileReference, + Kind: kind, + Pattern: pattern, + } } diff --git a/embedding/parsing/instruction_test.go b/embedding/parsing/instruction_test.go index 9676f44..b4d70bc 100644 --- a/embedding/parsing/instruction_test.go +++ b/embedding/parsing/instruction_test.go @@ -22,6 +22,7 @@ import ( _type "embed-code/embed-code-go/type" "fmt" "os" + "path/filepath" "strings" "testing" @@ -343,7 +344,7 @@ var _ = Describe("Instruction", func() { Expect(actualLines[5]).Should(Equal(expectedLastLine)) }) - It("should panic when start glob does not match", func() { + It("should report an error when start glob does not match", func() { instructionParams := TestInstructionParams{ startGlob: "foo bar", endGlob: "*main*", @@ -351,15 +352,17 @@ var _ = Describe("Instruction", func() { xmlString := buildInstruction("org/example/Hello.java", instructionParams) instruction := createInstructionFromXML(xmlString, config) - Expect(func() { - _, err := instruction.Content() - if err != nil { - return - } - }).To(Panic()) + _, err := instruction.Content() + + Expect(err).Should(MatchError( + fmt.Sprintf( + "no line in code file `file://%s` matches the start pattern `Pattern foo bar`", + absTestCodeFile("org/example/Hello.java"), + ), + )) }) - It("should panic when end glob does not match", func() { + It("should report an error when end glob does not match", func() { instructionParams := TestInstructionParams{ startGlob: "*main*", endGlob: "foo bar", @@ -367,12 +370,14 @@ var _ = Describe("Instruction", func() { xmlString := buildInstruction("org/example/Hello.java", instructionParams) instruction := createInstructionFromXML(xmlString, config) - Expect(func() { - _, err := instruction.Content() - if err != nil { - return - } - }).To(Panic()) + _, err := instruction.Content() + + Expect(err).Should(MatchError( + fmt.Sprintf( + "no line in code file `file://%s` matches the end pattern `Pattern foo bar`", + absTestCodeFile("org/example/Hello.java"), + ), + )) }) }) @@ -436,6 +441,15 @@ func readInstructionContent(instruction parsing.Instruction) []string { return lines } +func absTestCodeFile(path string) string { + absolutePath, err := filepath.Abs(filepath.Join("../../test/resources/code/java", path)) + if err != nil { + Fail("unexpected error while resolving test code file: " + err.Error()) + } + + return absolutePath +} + func xmlAttribute(name string, value string) string { return fmt.Sprintf("%s=\"%v\"", name, value) } diff --git a/embedding/processor.go b/embedding/processor.go index 029ce51..ccbd836 100644 --- a/embedding/processor.go +++ b/embedding/processor.go @@ -258,6 +258,10 @@ func errorLine(context parsing.Context, err error) int { if errors.As(err, &unclosedFenceErr) { return unclosedFenceErr.Line } + var patternErr parsing.PatternNotFoundError + if errors.As(err, &patternErr) { + return patternErr.Line + } if context.EmbeddingsCount() > 0 { return context.CurrentEmbedding().SourceStartIndex - 1 } diff --git a/fragmentation/resolver.go b/fragmentation/resolver.go index 84f26ec..bcf4271 100644 --- a/fragmentation/resolver.go +++ b/fragmentation/resolver.go @@ -73,6 +73,19 @@ func ResolveContent(codePath string, fragmentName string, config config.Configur return fragmentLines(fragment, content.lines, config.Separator), nil } +// ResolveCodeFileReference returns a user-facing reference to the source file. +func ResolveCodeFileReference(codePath string, config config.Configuration) (string, error) { + source, found, err := resolveSource(codePath, config) + if err != nil { + return "", err + } + if found { + return "file://" + source.absolutePath, nil + } + + return codeFileReference(codePath, config) +} + // ClearResolverCache removes cached source fragmentations. func ClearResolverCache() { resolverCache.clear() diff --git a/test/resources/docs/missing-end-pattern.md b/test/resources/docs/missing-end-pattern.md new file mode 100644 index 0000000..9860297 --- /dev/null +++ b/test/resources/docs/missing-end-pattern.md @@ -0,0 +1,5 @@ +# Example with a missing end pattern + + +```java +``` diff --git a/test/resources/docs/missing-start-pattern.md b/test/resources/docs/missing-start-pattern.md new file mode 100644 index 0000000..b967b55 --- /dev/null +++ b/test/resources/docs/missing-start-pattern.md @@ -0,0 +1,5 @@ +# Example with a missing start pattern + + +```java +``` From 7e29cd9bbb2d01c486e07d290e2070748127db15 Mon Sep 17 00:00:00 2001 From: Vladyslav Kuksiuk Date: Thu, 21 May 2026 13:44:01 +0200 Subject: [PATCH 4/5] Improve readability. --- .DS_Store | Bin 6148 -> 0 bytes embedding/embedding_test.go | 4 ++-- embedding/parsing/context.go | 5 +---- embedding/parsing/instruction.go | 15 ++++++++++----- embedding/parsing/instruction_test.go | 4 ++-- embedding/processor.go | 11 +++++------ 6 files changed, 20 insertions(+), 19 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 3950d9ccd908de298273cef43c423c69bcced8c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5T0$TO(;SS3Oz1(Ef}>5#Y?F51&ruHr8cD0V45xcv4>K~SzpK}@p+ut z-H4?XJc-yDnE7_+C(C>ZyIBAbt!Z=!Pz3-7m9XHVStArDU6F$I5DNW_2qK6fg?>0& z$!5o2WPskC3q2S>i1y3-8xO-og&2Jche^ocrKW&4NjHG99(@4!)YMMr4T^pEy<2r7qTAR-s zUZXBgyyl`V=glLpE*r3;hI~H?z#lf1+o`X@EsI-sK zyfUv~WCoZ4W?)kou=}4=*_4L4PiBA__%Q>tKS)$U-(qG^Zyjjp_mScyLJ}O)U4l?r z^etuvF@hpYDWWMA_KG1)Ir^o|^DSluO*sg?GCs$yEbI+M=+)6Lbvg*&AX{dD8CYhZ zXr@&<|1ZA3|1THuj2U1C{uKkF)DGG$Y{{OjE6veaD^VX%NhmKf_*sGjeH3FZ9mO?N aE$EjtK=dtU2GN7UKLVNtHq5}UGVlTH;Y||& diff --git a/embedding/embedding_test.go b/embedding/embedding_test.go index 7295997..d30a421 100644 --- a/embedding/embedding_test.go +++ b/embedding/embedding_test.go @@ -184,12 +184,12 @@ var _ = Describe("Embedding", func() { ), ContainSubstring( "` matches the start pattern "+ - "`Pattern *doesNotExistStart*`", + "`*doesNotExistStart*`", ), ContainSubstring("missing-end-pattern.md:3"), ContainSubstring( "` matches the end pattern "+ - "`Pattern *doesNotExistEnd*`", + "`*doesNotExistEnd*`", ), )) }) diff --git a/embedding/parsing/context.go b/embedding/parsing/context.go index 71014ad..4629383 100644 --- a/embedding/parsing/context.go +++ b/embedding/parsing/context.go @@ -160,10 +160,7 @@ func (c *Context) ResolveEmbeddingNotFound() { // // Also appends it to the list of such embeddings for logging. func (c *Context) ResolveUnacceptedEmbedding() { - currentEmbedding := c.CurrentEmbedding() - currentEmbedding.SourceEndIndex = c.lineIndex - currentEmbedding.resultEndIndex = len(c.Result) - currentEmbeddingInstruction := currentEmbedding.embeddingInstruction + currentEmbeddingInstruction := c.CurrentEmbedding().embeddingInstruction c.UnacceptedEmbeddings = append(c.UnacceptedEmbeddings, currentEmbeddingInstruction) c.embeddings = c.embeddings[:c.currentEmbeddingIndex()] c.EmbeddingInstruction = nil diff --git a/embedding/parsing/instruction.go b/embedding/parsing/instruction.go index f84bac5..e1c0b84 100644 --- a/embedding/parsing/instruction.go +++ b/embedding/parsing/instruction.go @@ -71,11 +71,16 @@ type PatternNotFoundError struct { // Error returns a user-facing description of an unmatched start or end pattern. func (e PatternNotFoundError) Error() string { + pattern := "" + if e.Pattern != nil { + pattern = e.Pattern.sourceGlob + } + return fmt.Sprintf( "no line in code file `%s` matches the %s pattern `%s`", e.CodeFileReference, e.Kind, - e.Pattern, + pattern, ) } @@ -134,15 +139,15 @@ func NewInstruction( // // Returns an error if there was an error during reading the content. func (e Instruction) Content() ([]string, error) { - codeFileReference, err := fragmentation.ResolveCodeFileReference(e.CodeFile, e.Configuration) - if err != nil { - return nil, err - } fileContent, err := fragmentation.ResolveContent(e.CodeFile, e.Fragment, e.Configuration) if err != nil { return nil, err } if e.StartPattern != nil || e.EndPattern != nil { + codeFileReference, err := fragmentation.ResolveCodeFileReference(e.CodeFile, e.Configuration) + if err != nil { + return nil, err + } fileContent, err = e.matchingLines(fileContent, codeFileReference) if err != nil { return nil, err diff --git a/embedding/parsing/instruction_test.go b/embedding/parsing/instruction_test.go index b4d70bc..8361dd0 100644 --- a/embedding/parsing/instruction_test.go +++ b/embedding/parsing/instruction_test.go @@ -356,7 +356,7 @@ var _ = Describe("Instruction", func() { Expect(err).Should(MatchError( fmt.Sprintf( - "no line in code file `file://%s` matches the start pattern `Pattern foo bar`", + "no line in code file `file://%s` matches the start pattern `foo bar`", absTestCodeFile("org/example/Hello.java"), ), )) @@ -374,7 +374,7 @@ var _ = Describe("Instruction", func() { Expect(err).Should(MatchError( fmt.Sprintf( - "no line in code file `file://%s` matches the end pattern `Pattern foo bar`", + "no line in code file `file://%s` matches the end pattern `foo bar`", absTestCodeFile("org/example/Hello.java"), ), )) diff --git a/embedding/processor.go b/embedding/processor.go index ccbd836..df99270 100644 --- a/embedding/processor.go +++ b/embedding/processor.go @@ -232,9 +232,11 @@ func (p Processor) fillEmbeddingContext() (parsing.Context, error) { return context, fmt.Errorf(errorStr, absDocPath, errorLine(context, err), err) } if !accepted { - err = unacceptedTransitionError(context, err) + err = unacceptedTransitionError(context) currentState = &parsing.RegularLineState{} - context.ResolveUnacceptedEmbedding() + if context.EmbeddingInstruction != nil { + context.ResolveUnacceptedEmbedding() + } return context, fmt.Errorf(errorStr, absDocPath, errorLine(context, err), err) } @@ -270,10 +272,7 @@ func errorLine(context parsing.Context, err error) int { } // unacceptedTransitionError explains why the parser could not accept the current state. -func unacceptedTransitionError(context parsing.Context, err error) error { - if err != nil { - return err - } +func unacceptedTransitionError(context parsing.Context) error { if context.EmbeddingInstruction != nil && context.CodeFenceStarted { return parsing.UnclosedCodeFenceError{ Line: context.EmbeddingInstruction.DocumentationLine, From 3c2295326d18ebec4f60d67099cf9309c3f678a8 Mon Sep 17 00:00:00 2001 From: Vladyslav Kuksiuk Date: Thu, 21 May 2026 14:09:53 +0200 Subject: [PATCH 5/5] Improve readability. --- embedding/parsing/instruction.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/embedding/parsing/instruction.go b/embedding/parsing/instruction.go index e1c0b84..d061cd8 100644 --- a/embedding/parsing/instruction.go +++ b/embedding/parsing/instruction.go @@ -178,8 +178,9 @@ func (e Instruction) matchingLines(lines []string, codeFileReference string) ([] startPosition := 0 if e.StartPattern != nil { var err error - startPosition, err = e.matchGlob(e.StartPattern, lines, 0, "start", - codeFileReference) + startPosition, err = e.matchGlob( + e.StartPattern, lines, 0, "start", codeFileReference, + ) if err != nil { return nil, err } @@ -187,8 +188,9 @@ func (e Instruction) matchingLines(lines []string, codeFileReference string) ([] endPosition := len(lines) - 1 if e.EndPattern != nil { var err error - endPosition, err = e.matchGlob(e.EndPattern, lines, startPosition, "end", - codeFileReference) + endPosition, err = e.matchGlob( + e.EndPattern, lines, startPosition, "end", codeFileReference, + ) if err != nil { return nil, err }