imageimportcheck.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2022 The Ebitengine Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "fmt"
  17. "go/token"
  18. "reflect"
  19. "strconv"
  20. "strings"
  21. "golang.org/x/tools/go/analysis"
  22. )
  23. // imageImportCheckAnalyzer is an analyzer to check whether unexpected `image/*` packages are imported.
  24. // Importing `image/gif`, `image/jpeg`, and `image/png` registers their recorders at `init` functions, so
  25. // it affects the result of `image.Decode`. Ebitengine should not have such side-effects.
  26. var imageImportCheckAnalyzer = &analysis.Analyzer{
  27. Name: "imageimportcheck",
  28. Doc: "check importing image/gif, image/jpeg, and image/png packages",
  29. Run: runImageImportCheck,
  30. ResultType: reflect.TypeOf(imageImportCheckResult{}),
  31. }
  32. type imageImportCheckResult struct {
  33. Errors []imageImportCheckError
  34. }
  35. type imageImportCheckError struct {
  36. Pos token.Pos
  37. Import string
  38. }
  39. func runImageImportCheck(pass *analysis.Pass) (any, error) {
  40. pkgPath := pass.Pkg.Path()
  41. if strings.HasPrefix(pkgPath, "github.com/hajimehoshi/ebiten/v2/examples/") {
  42. return nil, nil
  43. }
  44. if strings.HasSuffix(pkgPath, "_test") {
  45. return nil, nil
  46. }
  47. // TODO: Remove this exception after v3 is released (#2336).
  48. if pkgPath == "github.com/hajimehoshi/ebiten/v2/ebitenutil" {
  49. return nil, nil
  50. }
  51. var errs []imageImportCheckError
  52. for _, f := range pass.Files {
  53. for _, i := range f.Imports {
  54. path, err := strconv.Unquote(i.Path.Value)
  55. if err != nil {
  56. return nil, err
  57. }
  58. if path == "image/gif" || path == "image/jpeg" || path == "image/png" {
  59. err := imageImportCheckError{
  60. Pos: pass.Fset.File(f.Pos()).Pos(int(i.Pos())),
  61. Import: path,
  62. }
  63. errs = append(errs, err)
  64. pass.Report(analysis.Diagnostic{
  65. Pos: err.Pos,
  66. Message: fmt.Sprintf("unexpected import %q", err.Import),
  67. })
  68. }
  69. }
  70. }
  71. return imageImportCheckResult{
  72. Errors: errs,
  73. }, nil
  74. }