Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions internal/engine/directives.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,14 @@ func configKeyForType(mt mutator.Type) string {

// collectTokenLines returns the set of source lines that contain at least
// one non-comment AST node, used to distinguish end-of-line directives from
// own-line ones.
// own-line ones. Returning false on *ast.CommentGroup stops the walk before
// it reaches the *ast.Comment children, so no Comment guard is needed.
func collectTokenLines(set *token.FileSet, file *ast.File) map[int]bool {
lines := map[int]bool{}
ast.Inspect(file, func(n ast.Node) bool {
if n == nil {
return false
}
if _, isComment := n.(*ast.Comment); isComment {
return false
}
if _, isCG := n.(*ast.CommentGroup); isCG {
return false
}
Expand Down Expand Up @@ -264,9 +262,6 @@ func largestNodeStartingAtLine(set *token.FileSet, file *ast.File, line int) (as
if _, isCG := n.(*ast.CommentGroup); isCG {
return false
}
if _, isC := n.(*ast.Comment); isC {
return false
}
if set.Position(n.Pos()).Line != line {
return true
}
Expand Down
40 changes: 40 additions & 0 deletions internal/engine/directives_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,46 @@ func F() int {
}
}

func TestDirectiveIndex_NilReceiverIsSafe(t *testing.T) {
t.Parallel()

// A nil index must answer "not suppressed" without panicking. The
// engine relies on this so it can call isSuppressed unconditionally
// even when no index has been built (currently never happens, but
// the guard is cheap and protects future call sites).
var idx *directiveIndex
if idx.isSuppressed(token.Position{Line: 1}, mutator.ArithmeticBase) {
t.Errorf("nil directiveIndex must return false from isSuppressed")
}
}

func TestBuildDirectiveIndex_TypedFilterWithEmptyEntries(t *testing.T) {
t.Parallel()

// Doubled commas / leading commas leave empty strings in the comma-
// split type list. Each empty entry should be skipped silently and
// the surrounding valid types still parsed.
src := `package p

func F() int {
return 1 + 2 //nomutant:arithmetic-base,,invert-bitwise
}
`
set, file := parseSrc(t, src)
idx := buildDirectiveIndex(set, file)

pos := positionOf(t, set, src, "+")
if !idx.isSuppressed(pos, mutator.ArithmeticBase) {
t.Errorf("expected ArithmeticBase to be suppressed (valid type before doubled comma)")
}
if !idx.isSuppressed(pos, mutator.InvertBitwise) {
t.Errorf("expected InvertBitwise to be suppressed (valid type after doubled comma)")
}
if idx.isSuppressed(pos, mutator.ConditionalsBoundary) {
t.Errorf("did NOT expect ConditionalsBoundary to be suppressed (not in filter)")
}
}

func TestBuildDirectiveIndex_NestedBlocks_Additive(t *testing.T) {
t.Parallel()

Expand Down