Repository: TomWright/dasel

Issue:
🔧 Integrate golangci-lint for Static Code Analysis
**Is your feature request related to a problem? Please describe.**
To improve code quality and maintain consistency across the project, I'd like to propose adding golangci-lint to our development workflow.
This tool helps catch common bugs, enforces style guidelines, and ensures adherence to Go best practices—all with minimal setup and configuration.

**Describe the solution you'd like**
Proposed steps:

- Add golangci-lint configuration file (.golangci.yml) to the root of the repository.
- Define rules and linters we want to enforce.
- Update documentation or contributing guide to include linting steps.
- Integrate it into the CI pipeline to auto-run checks on PRs.

**Describe alternatives you've considered**
the golangci-lint is the best for linting go code
**Additional context**
Here is a quick analysis from the linter(there are around 52 fixes possible)

<img width="771" height="132" alt="Image" src="https://github.com/user-attachments/assets/8c05e219-95ad-4755-84d3-7a518ceb2532" />

<img width="916" height="633" alt="Image" src="https://github.com/user-attachments/assets/376c9af0-03c6-4106-bc2a-705401e4d85b" />

Hints from issue comments:
@TomWright: Thanks for the suggestion!

Solution patch:
diff --git a/.github/workflows/build-dev.yaml b/.github/workflows/build-dev.yaml
index eae4f1e..30b3752 100644
--- a/.github/workflows/build-dev.yaml
+++ b/.github/workflows/build-dev.yaml
@@ -62,8 +62,8 @@ jobs:
     name: Dev build ${{ matrix.os }} ${{ matrix.arch }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-go@v4
+      - uses: actions/checkout@v5
+      - uses: actions/setup-go@v5
         with:
           go-version: '^1.24.0' # The Go version to download (if necessary) and use.
       - name: Set env
diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml
index 947f556..9c8907a 100644
--- a/.github/workflows/build-test.yaml
+++ b/.github/workflows/build-test.yaml
@@ -74,8 +74,8 @@ jobs:
     name: Dev build ${{ matrix.os }} ${{ matrix.arch }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-go@v4
+      - uses: actions/checkout@v5
+      - uses: actions/setup-go@v5
         with:
           go-version: '^1.24.0' # The Go version to download (if necessary) and use.
       - name: Set env
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index b4f3271..518e8f0 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -70,8 +70,8 @@ jobs:
     name: Build ${{ matrix.os }} ${{ matrix.arch }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
-      - uses: actions/setup-go@v4
+      - uses: actions/checkout@v5
+      - uses: actions/setup-go@v5
         with:
           go-version: '^1.24.0'
       - name: Set env
diff --git a/.github/workflows/bump-homebrew.yaml b/.github/workflows/bump-homebrew.yaml
index 219e194..4556947 100644
--- a/.github/workflows/bump-homebrew.yaml
+++ b/.github/workflows/bump-homebrew.yaml
@@ -9,7 +9,7 @@ jobs:
     name: Update homebrew-core
     runs-on: macos-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v5
         with:
           fetch-depth: 0
       - name: Set env
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 0a919c8..d432c31 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -36,7 +36,7 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v3
+      uses: actions/checkout@v5
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml
index 7c65d18..d5cc4fc 100644
--- a/.github/workflows/container.yaml
+++ b/.github/workflows/container.yaml
@@ -18,7 +18,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
         - name: Checkout
-          uses: actions/checkout@v4
+          uses: actions/checkout@v5
         - name: Set up QEMU
           uses: docker/setup-qemu-action@v3
         - name: Set up Docker Buildx
diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml
new file mode 100644
index 0000000..da7f7b4
--- /dev/null
+++ b/.github/workflows/golangci-lint.yaml
@@ -0,0 +1,25 @@
+name: golangci-lint
+on:
+  push:
+    branches:
+      - main
+      - master
+  pull_request:
+
+permissions:
+  contents: read
+  pull-requests: read
+
+jobs:
+  golangci:
+    name: lint
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v5
+      - uses: actions/setup-go@v5
+        with:
+          go-version: '^1.25.0'
+      - name: golangci-lint
+        uses: golangci/golangci-lint-action@v8
+        with:
+          version: v2.1
\ No newline at end of file
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 99418ce..72048f8 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -9,8 +9,8 @@ jobs:
         with:
           go-version: '^1.24.0'
       - name: Checkout code
-        uses: actions/checkout@v3
-      - uses: actions/cache@v3
+        uses: actions/checkout@v5
+      - uses: actions/cache@v4
         with:
           path: ~/go/pkg/mod
           key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
diff --git a/execution/execute.go b/execution/execute.go
index 37328a5..6dcfce0 100644
--- a/execution/execute.go
+++ b/execution/execute.go
@@ -138,14 +138,14 @@ func exprExecutor(options *Options, expr ast.Expr) (expressionExecutor, error) {
 	case ast.RegexExpr:
 		// Noop
 		return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-			ctx = WithExecutorID(ctx, "regexExpr")
+			//ctx = WithExecutorID(ctx, "regexExpr")
 			return data, nil
 		}, nil
 	case ast.SortByExpr:
 		return sortByExprExecutor(e)
 	case ast.NullExpr:
 		return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-			ctx = WithExecutorID(ctx, "nullExpr")
+			//ctx = WithExecutorID(ctx, "nullExpr")
 			return model.NewNullValue(), nil
 		}, nil
 	default:
@@ -170,7 +170,7 @@ func chainedExprExecutor(e ast.ChainedExpr) (expressionExecutor, error) {
 
 func variableExprExecutor(e ast.VariableExpr) (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "variableExpr")
+		//ctx = WithExecutorID(ctx, "variableExpr")
 		varName := e.Name
 		res, ok := options.Vars[varName]
 		if ok {
diff --git a/execution/execute_literal.go b/execution/execute_literal.go
index 30d2d58..f5844f5 100644
--- a/execution/execute_literal.go
+++ b/execution/execute_literal.go
@@ -8,28 +8,28 @@ import (
 
 func numberIntExprExecutor(e ast.NumberIntExpr) (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "numberIntExpr")
+		//ctx = WithExecutorID(ctx, "numberIntExpr")
 		return model.NewIntValue(e.Value), nil
 	}, nil
 }
 
 func numberFloatExprExecutor(e ast.NumberFloatExpr) (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "numberFloatExpr")
+		//ctx = WithExecutorID(ctx, "numberFloatExpr")
 		return model.NewFloatValue(e.Value), nil
 	}, nil
 }
 
 func stringExprExecutor(e ast.StringExpr) (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "stringExpr")
+		//ctx = WithExecutorID(ctx, "stringExpr")
 		return model.NewStringValue(e.Value), nil
 	}, nil
 }
 
 func boolExprExecutor(e ast.BoolExpr) (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "boolExpr")
+		//ctx = WithExecutorID(ctx, "boolExpr")
 		return model.NewBoolValue(e.Value), nil
 	}, nil
 }
diff --git a/execution/execute_object.go b/execution/execute_object.go
index 4140184..02b95fb 100644
--- a/execution/execute_object.go
+++ b/execution/execute_object.go
@@ -52,6 +52,9 @@ func objectExprExecutor(e ast.ObjectExpr) (expressionExecutor, error) {
 			}
 
 			keyStr, err := key.StringValue()
+			if err != nil {
+				return nil, fmt.Errorf("error getting string value: %w", err)
+			}
 			if err := obj.SetMapKey(keyStr, val); err != nil {
 				return nil, fmt.Errorf("error setting map key: %w", err)
 			}
diff --git a/execution/execute_sort_by.go b/execution/execute_sort_by.go
index 486c6da..41067e2 100644
--- a/execution/execute_sort_by.go
+++ b/execution/execute_sort_by.go
@@ -62,95 +62,3 @@ func sortByExprExecutor(e ast.SortByExpr) (expressionExecutor, error) {
 		return res, nil
 	}, nil
 }
-
-func sortByExprExecutor2(e ast.SortByExpr) (expressionExecutor, error) {
-	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		if !data.IsSlice() {
-			return nil, fmt.Errorf("cannot sort by on non-slice data")
-		}
-
-		sortedValues := model.NewSliceValue()
-		sortedIndexes := make([]int, 0)
-
-		if err := data.RangeSlice(func(i int, item *model.Value) error {
-			item, err := ExecuteAST(ctx, e.Expr, item, options)
-			if err != nil {
-				return err
-			}
-			if err := sortedValues.Append(item); err != nil {
-				return fmt.Errorf("error appending item to result: %w", err)
-			}
-			sortedIndexes = append(sortedIndexes, i)
-			return nil
-		}); err != nil {
-			return nil, fmt.Errorf("error ranging over slice: %w", err)
-		}
-
-		l, err := sortedValues.Len()
-		if err != nil {
-			return nil, fmt.Errorf("error getting length of slice: %w", err)
-		}
-
-		for i := 0; i < l-1; i++ {
-			cur, err := sortedValues.GetSliceIndex(i)
-			if err != nil {
-				return nil, fmt.Errorf("error getting slice index: %w", err)
-			}
-			curIndex := sortedIndexes[i]
-			next, err := sortedValues.GetSliceIndex(i + 1)
-			if err != nil {
-				return nil, fmt.Errorf("error getting slice index: %w", err)
-			}
-			nextIndex := sortedIndexes[i+1]
-
-			cmp, err := cur.Compare(next)
-			if err != nil {
-				return nil, fmt.Errorf("error comparing values: %w", err)
-			}
-
-			if cmp == 0 {
-				continue
-			}
-
-			if !e.Descending {
-				if cmp > 0 {
-					if err := sortedValues.SetSliceIndex(i, next); err != nil {
-						return nil, fmt.Errorf("error setting slice index: %w", err)
-					}
-					sortedIndexes[i] = nextIndex
-					if err := sortedValues.SetSliceIndex(i+1, cur); err != nil {
-						return nil, fmt.Errorf("error setting slice index: %w", err)
-					}
-					sortedIndexes[i+1] = curIndex
-					i -= 1
-				}
-			} else {
-				if cmp < 0 {
-					if err := sortedValues.SetSliceIndex(i, next); err != nil {
-						return nil, fmt.Errorf("error setting slice index: %w", err)
-					}
-					sortedIndexes[i] = nextIndex
-					if err := sortedValues.SetSliceIndex(i+1, cur); err != nil {
-						return nil, fmt.Errorf("error setting slice index: %w", err)
-					}
-					sortedIndexes[i+1] = curIndex
-					i -= 1
-				}
-			}
-		}
-
-		res := model.NewSliceValue()
-
-		for _, i := range sortedIndexes {
-			item, err := data.GetSliceIndex(i)
-			if err != nil {
-				return nil, fmt.Errorf("error getting slice index: %w", err)
-			}
-			if err := res.Append(item); err != nil {
-				return nil, fmt.Errorf("error appending item to result: %w", err)
-			}
-		}
-
-		return res, nil
-	}, nil
-}
diff --git a/execution/execute_spread.go b/execution/execute_spread.go
index e6d6777..52fb775 100644
--- a/execution/execute_spread.go
+++ b/execution/execute_spread.go
@@ -9,7 +9,7 @@ import (
 
 func spreadExprExecutor() (expressionExecutor, error) {
 	return func(ctx context.Context, options *Options, data *model.Value) (*model.Value, error) {
-		ctx = WithExecutorID(ctx, "spreadExpr")
+		//ctx = WithExecutorID(ctx, "spreadExpr")
 		s := model.NewSliceValue()
 
 		s.MarkAsSpread()
diff --git a/execution/func_readfile.go b/execution/func_readfile.go
index c3ceb2b..51c3478 100644
--- a/execution/func_readfile.go
+++ b/execution/func_readfile.go
@@ -21,7 +21,9 @@ var FuncReadFile = NewFunc(
 		if err != nil {
 			return nil, fmt.Errorf("readFile: %w", err)
 		}
-		defer f.Close()
+		defer func() {
+			_ = f.Close()
+		}()
 
 		fileBytes, err := io.ReadAll(f)
 		if err != nil {
diff --git a/internal/cli/interactive.go b/internal/cli/interactive.go
index 88a718b..eba5231 100644
--- a/internal/cli/interactive.go
+++ b/internal/cli/interactive.go
@@ -58,7 +58,7 @@ func (c *InteractiveCmd) Run(ctx *Globals) error {
 				err = fmt.Errorf("panic: %v", r)
 			}
 		}()
-		var stdIn *bytes.Reader = nil
+		var stdIn *bytes.Reader
 		if in != "" {
 			stdIn = bytes.NewReader([]byte(in))
 		} else {
diff --git a/internal/cli/interactive_tea.go b/internal/cli/interactive_tea.go
index 95154f7..fcd39c9 100644
--- a/internal/cli/interactive_tea.go
+++ b/internal/cli/interactive_tea.go
@@ -28,12 +28,6 @@ var (
 	inputStyle = func() lipgloss.Style {
 		return lipgloss.NewStyle().Margin(0, 0, 1, 0)
 	}()
-	inputContentStyle = func() lipgloss.Style {
-		return lipgloss.NewStyle().Padding(0, 1).Border(lipgloss.RoundedBorder())
-	}()
-	inputHeaderStyle = func() lipgloss.Style {
-		return lipgloss.NewStyle().Padding(0, 2).Margin(0, 0, 1, 0).Underline(true)
-	}()
 	outputContentStyle = func() lipgloss.Style {
 		return lipgloss.NewStyle().Padding(0, 1).Border(lipgloss.RoundedBorder())
 	}()
diff --git a/internal/cli/variable.go b/internal/cli/variable.go
index 124ee7c..a8e15c6 100644
--- a/internal/cli/variable.go
+++ b/internal/cli/variable.go
@@ -64,13 +64,14 @@ func (vm *variableMapper) Decode(ctx *kong.DecodeContext, target reflect.Value)
 	}
 	if strings.HasPrefix(valueRaw, "file:") {
 		filePath := valueRaw[len("file:"):]
-		valueRaw = valueRaw[:len("file:")]
 
 		f, err := os.Open(filePath)
 		if err != nil {
 			return fmt.Errorf("failed to open file: %w", err)
 		}
-		defer f.Close()
+		defer func() {
+			_ = f.Close()
+		}()
 		contents, err := io.ReadAll(f)
 		if err != nil {
 			return fmt.Errorf("failed to read file contents: %w", err)
diff --git a/model/value.go b/model/value.go
index 64d36ec..2e3ae32 100644
--- a/model/value.go
+++ b/model/value.go
@@ -88,7 +88,7 @@ func (v *Value) string(indent int) string {
 		}
 		return fmt.Sprintf("bool{%t}", val)
 	case TypeMap:
-		res := fmt.Sprintf("{\n")
+		res := "{\n"
 		if err := v.RangeMap(func(k string, v *Value) error {
 			res += fmt.Sprintf("%s%s: %s,\n", indentStr(indent+1), k, v.string(indent+1))
 			return nil
diff --git a/parsing/csv/csv.go b/parsing/csv/csv.go
index 63843f3..d7be6d5 100644
--- a/parsing/csv/csv.go
+++ b/parsing/csv/csv.go
@@ -65,9 +65,7 @@ func (j *csvReader) Read(data []byte) (*model.Value, error) {
 		}
 
 		if headers == nil {
-			for _, header := range record {
-				headers = append(headers, header)
-			}
+			headers = append(headers, record...)
 			continue
 		}
 
diff --git a/parsing/hcl/writer.go b/parsing/hcl/writer.go
index 7ebb510..751e9a7 100644
--- a/parsing/hcl/writer.go
+++ b/parsing/hcl/writer.go
@@ -10,7 +10,9 @@ import (
 )
 
 func newHCLWriter(options parsing.WriterOptions) (parsing.Writer, error) {
-	return &hclWriter{}, nil
+	return &hclWriter{
+		options: options,
+	}, nil
 }
 
 type hclWriter struct {
diff --git a/parsing/json/json.go b/parsing/json/json.go
index 82d6dd5..6a25edb 100644
--- a/parsing/json/json.go
+++ b/parsing/json/json.go
@@ -312,7 +312,7 @@ func (j *jsonWriter) writeMap(w io.Writer, encoder encoderFn, es encoderState, v
 				return err
 			}
 
-			if _, err := w.Write([]byte(fmt.Sprintf(`"%s": `, kv.Key))); err != nil {
+			if _, err := fmt.Fprintf(w, `"%s": `, kv.Key); err != nil {
 				return err
 			}
 
diff --git a/selector/lexer/tokenize.go b/selector/lexer/tokenize.go
index 0500883..a84ef12 100644
--- a/selector/lexer/tokenize.go
+++ b/selector/lexer/tokenize.go
@@ -207,7 +207,7 @@ func (p *Tokenizer) parseCurRune() (Token, error) {
 				return nil
 			}
 			other := p.src[pos : pos+l]
-			if m != other && !(caseInsensitive && strings.EqualFold(m, other)) {
+			if m != other && (!caseInsensitive || !strings.EqualFold(m, other)) {
 				return nil
 			}
 
@@ -220,7 +220,7 @@ func (p *Tokenizer) parseCurRune() (Token, error) {
 		}
 
 		matchRegexPattern := func(pos int) *Token {
-			if !(p.src[pos] == 'r' && p.peekRuneEqual(pos+1, '/')) {
+			if p.src[pos] != 'r' || !p.peekRuneEqual(pos+1, '/') {
 				return nil
 			}
 			start := pos
diff --git a/selector/parser/denotations.go b/selector/parser/denotations.go
index 8828cc8..a08362f 100644
--- a/selector/parser/denotations.go
+++ b/selector/parser/denotations.go
@@ -2,9 +2,6 @@ package parser
 
 import "github.com/tomwright/dasel/v3/selector/lexer"
 
-// null denotation tokens are tokens that expect no token to the left of them.
-var nullDenotationTokens = []lexer.TokenKind{}
-
 // left denotation tokens are tokens that expect a token to the left of them.
 var leftDenotationTokens = []lexer.TokenKind{
 	lexer.Plus,
diff --git a/selector/parser/parse_array.go b/selector/parser/parse_array.go
index 3004152..d335fa3 100644
--- a/selector/parser/parse_array.go
+++ b/selector/parser/parse_array.go
@@ -34,42 +34,6 @@ func parseArray(p *Parser) (ast.Expr, error) {
 	return res, nil
 }
 
-func parseIndex(p *Parser) (ast.Expr, error) {
-	if err := p.expect(lexer.Symbol, lexer.Variable); err != nil {
-		return nil, err
-	}
-	if err := p.expectN(1, lexer.OpenBracket); err != nil {
-		return nil, err
-	}
-	token := p.current()
-	p.advance()
-
-	idx, err := parseIndexSquareBrackets(p, false)
-	if err != nil {
-		return nil, err
-	}
-
-	var e ast.Expr
-
-	switch {
-	case token.IsKind(lexer.Variable):
-		e = ast.VariableExpr{
-			Name: token.Value,
-		}
-	case token.IsKind(lexer.Symbol):
-		e = ast.PropertyExpr{
-			Property: ast.StringExpr{Value: token.Value},
-		}
-	default:
-		panic("unexpected token kind")
-	}
-
-	return ast.ChainExprs(
-		e,
-		idx,
-	), nil
-}
-
 // parseIndexSquareBrackets parses square bracket array access.
 // E.g. [0], [0:1], [0:], [:2]
 func parseIndexSquareBrackets(p *Parser, expectIndex bool) (ast.Expr, error) {
diff --git a/selector/parser/parser.go b/selector/parser/parser.go
index 21ed600..90c32da 100644
--- a/selector/parser/parser.go
+++ b/selector/parser/parser.go
@@ -201,7 +201,7 @@ func (p *Parser) parseExpression(bp bindingPower) (left ast.Expr, err error) {
 }
 
 func (p *Parser) hasToken() bool {
-	return p.i < len(p.tokens) && !p.tokens[p.i].IsKind(lexer.EOF)
+	return p.hasTokenN(0)
 }
 
 func (p *Parser) hasTokenN(n int) bool {
@@ -215,17 +215,8 @@ func (p *Parser) current() lexer.Token {
 	return lexer.Token{Kind: lexer.EOF}
 }
 
-func (p *Parser) previous() lexer.Token {
-	i := p.i - 1
-	if i > 0 && i < len(p.tokens) {
-		return p.tokens[i]
-	}
-	return lexer.Token{Kind: lexer.EOF}
-}
-
 func (p *Parser) advance() lexer.Token {
-	p.i++
-	return p.current()
+	return p.advanceN(1)
 }
 
 func (p *Parser) advanceN(n int) lexer.Token {



Test patch:
diff --git a/parsing/xml/xml_test.go b/parsing/xml/xml_test.go
deleted file mode 100644
index a72629d..0000000
--- a/parsing/xml/xml_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package xml_test
-
-import (
-	"bytes"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-	"github.com/tomwright/dasel/v3/model"
-	"github.com/tomwright/dasel/v3/parsing"
-	"github.com/tomwright/dasel/v3/parsing/xml"
-)
-
-type testCase struct {
-	in     string
-	assert func(t *testing.T, res *model.Value)
-}
-
-func (tc testCase) run(t *testing.T) {
-	r, err := xml.XML.NewReader(parsing.DefaultReaderOptions())
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-	res, err := r.Read([]byte(tc.in))
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-
-	tc.assert(t, res)
-}
-
-type rwTestCase struct {
-	in  string
-	out string
-}
-
-func (tc rwTestCase) run(t *testing.T) {
-	if tc.out == "" {
-		tc.out = tc.in
-	}
-	r, err := xml.XML.NewReader(parsing.DefaultReaderOptions())
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-	w, err := xml.XML.NewWriter(parsing.WriterOptions{})
-	res, err := r.Read([]byte(tc.in))
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-	out, err := w.Write(res)
-	if err != nil {
-		t.Fatalf("unexpected error: %s", err)
-	}
-
-	if !bytes.Equal([]byte(tc.out), out) {
-		t.Errorf("unexpected output: %s", cmp.Diff(tc.out, string(out)))
-	}
-}
-
-func TestYamlValue_UnmarshalXML(t *testing.T) {
-	//t.Run("generic", rwTestCase{
-	//	in: `<html>
-	//<head>
-	//    <title>Test</title>
-	//</head>
-	//<body>
-	//    <h1>Test</h1>
-	//    <p class="testing">Test</p>
-	//    <div>
-	//        <a href="test2.html">Test 2</a>
-	//    </div>
-	//	<div>
-	//		<p>Hello</p>
-	//		<p>World</p>
-	//	</div>
-	//</body>
-	//</html>`,
-	//	}.run)
-}
diff --git a/parsing/yaml/yaml_test.go b/parsing/yaml/yaml_test.go
index 12c4da4..20d1db9 100644
--- a/parsing/yaml/yaml_test.go
+++ b/parsing/yaml/yaml_test.go
@@ -42,6 +42,9 @@ func (tc rwTestCase) run(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	w, err := yaml.YAML.NewWriter(parsing.WriterOptions{})
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
 	res, err := r.Read([]byte(tc.in))
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
diff --git a/selector/lexer/tokenize_test.go b/selector/lexer/tokenize_test.go
index 56acf9f..0602491 100644
--- a/selector/lexer/tokenize_test.go
+++ b/selector/lexer/tokenize_test.go
@@ -45,6 +45,7 @@ func (tc errTestCase) run(t *testing.T) {
 	}
 }
 
+// nolint:unused
 func matchUnexpectedError(r rune, p int) func(error) bool {
 	return func(err error) bool {
 		var e *lexer.UnexpectedTokenError