aboutsummaryrefslogtreecommitdiff
path: root/gopls/internal/lsp/analysis/embeddirective/embeddirective.go
blob: 1b504f7cb4927c895036f627e48c5cc0620a440d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package embeddirective defines an Analyzer that validates import for //go:embed directive.
package embeddirective

import (
	"go/ast"
	"strings"

	"golang.org/x/tools/go/analysis"
)

const Doc = `check for //go:embed directive import

This analyzer checks that the embed package is imported when source code contains //go:embed comment directives.
The embed package must be imported for //go:embed directives to function.import _ "embed".`

var Analyzer = &analysis.Analyzer{
	Name:             "embed",
	Doc:              Doc,
	Requires:         []*analysis.Analyzer{},
	Run:              run,
	RunDespiteErrors: true,
}

func run(pass *analysis.Pass) (interface{}, error) {
	for _, f := range pass.Files {
		com := hasEmbedDirectiveComment(f)
		if com != nil {
			assertEmbedImport(pass, com, f)
		}
	}
	return nil, nil
}

// Check if the comment contains //go:embed directive.
func hasEmbedDirectiveComment(f *ast.File) *ast.Comment {
	for _, cg := range f.Comments {
		for _, c := range cg.List {
			if strings.HasPrefix(c.Text, "//go:embed ") {
				return c
			}
		}
	}
	return nil
}

// Verifies that "embed" import exists for //go:embed directive.
func assertEmbedImport(pass *analysis.Pass, com *ast.Comment, f *ast.File) {
	for _, imp := range f.Imports {
		if "\"embed\"" == imp.Path.Value {
			return
		}
	}
	pass.Report(analysis.Diagnostic{Pos: com.Pos(), End: com.Pos() + 10, Message: "The \"embed\" package must be imported when using go:embed directives."})
}