| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | package test
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | // These tests check for meta level items, like trailing whitespace, correct file naming etc.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | import (
 | 
					
						
							|  |  |  | 	"bufio"
 | 
					
						
							|  |  |  | 	"fmt"
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	"go/ast"
 | 
					
						
							|  |  |  | 	"go/parser"
 | 
					
						
							|  |  |  | 	"go/token"
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 	"os"
 | 
					
						
							|  |  |  | 	"path/filepath"
 | 
					
						
							|  |  |  | 	"strings"
 | 
					
						
							|  |  |  | 	"testing"
 | 
					
						
							|  |  |  | 	"unicode"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestTrailingWhitespace(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	walker := hasTrailingWhitespaceWalker{}
 | 
					
						
							|  |  |  | 	err := filepath.Walk("..", walker.walk)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(walker.Errors) > 0 {
 | 
					
						
							|  |  |  | 		for _, err = range walker.Errors {
 | 
					
						
							|  |  |  | 			t.Error(err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | type hasTrailingWhitespaceWalker struct {
 | 
					
						
							|  |  |  | 	Errors []error
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *hasTrailingWhitespaceWalker) walk(path string, info os.FileInfo, _ error) error {
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 	// Only handle regular files, skip files that are executable and skip file in the
 | 
					
						
							|  |  |  | 	// root that start with a .
 | 
					
						
							|  |  |  | 	if !info.Mode().IsRegular() {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if info.Mode().Perm()&0111 != 0 {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "../.") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-07-21 16:23:52 +08:00
										 |  |  | 	if strings.Contains(path, "/vendor") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	file, err := os.Open(path)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	defer file.Close()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scanner := bufio.NewScanner(file)
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	for i := 1; scanner.Scan(); i++ {
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 		text := scanner.Text()
 | 
					
						
							|  |  |  | 		trimmed := strings.TrimRightFunc(text, unicode.IsSpace)
 | 
					
						
							|  |  |  | 		if len(text) != len(trimmed) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 			absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 			w.Errors = append(w.Errors, fmt.Errorf("file %q has trailing whitespace at line %d, text: %q", absPath, i, text))
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	err = scanner.Err()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 		err = fmt.Errorf("file %q: %v", absPath, err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err
 | 
					
						
							| 
									
										
										
										
											2020-01-28 11:13:11 +00:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestFileNameHyphen(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	walker := hasHyphenWalker{}
 | 
					
						
							|  |  |  | 	err := filepath.Walk("..", walker.walk)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(walker.Errors) > 0 {
 | 
					
						
							|  |  |  | 		for _, err = range walker.Errors {
 | 
					
						
							|  |  |  | 			t.Error(err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type hasHyphenWalker struct {
 | 
					
						
							|  |  |  | 	Errors []error
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | func (w *hasHyphenWalker) walk(path string, info os.FileInfo, _ error) error {
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | 	// only for regular files, not starting with a . and those that are go files.
 | 
					
						
							|  |  |  | 	if !info.Mode().IsRegular() {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "../.") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-07-21 16:23:52 +08:00
										 |  |  | 	if strings.Contains(path, "/vendor") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | 	if filepath.Ext(path) != ".go" {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.Index(path, "-") > 0 {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 		absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 		w.Errors = append(w.Errors, fmt.Errorf("file %q has a hyphen, please use underscores in file names", absPath))
 | 
					
						
							| 
									
										
										
										
											2020-01-28 15:47:28 +00:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Test if error messages start with an upper case.
 | 
					
						
							|  |  |  | func TestLowercaseLog(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	walker := hasLowercaseWalker{}
 | 
					
						
							|  |  |  | 	err := filepath.Walk("..", walker.walk)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(walker.Errors) > 0 {
 | 
					
						
							|  |  |  | 		for _, err = range walker.Errors {
 | 
					
						
							|  |  |  | 			t.Error(err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type hasLowercaseWalker struct {
 | 
					
						
							|  |  |  | 	Errors []error
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | func (w *hasLowercaseWalker) walk(path string, info os.FileInfo, _ error) error {
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	// only for regular files, not starting with a . and those that are go files.
 | 
					
						
							|  |  |  | 	if !info.Mode().IsRegular() {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "../.") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-07-21 16:23:52 +08:00
										 |  |  | 	if strings.Contains(path, "/vendor") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	if !strings.HasSuffix(path, "_test.go") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs := token.NewFileSet()
 | 
					
						
							|  |  |  | 	f, err := parser.ParseFile(fs, path, nil, parser.AllErrors)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		return err
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	l := &logfmt{}
 | 
					
						
							|  |  |  | 	ast.Walk(l, f)
 | 
					
						
							|  |  |  | 	if l.err != nil {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 		w.Errors = append(w.Errors, l.err)
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type logfmt struct {
 | 
					
						
							|  |  |  | 	err error
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (l logfmt) Visit(n ast.Node) ast.Visitor {
 | 
					
						
							|  |  |  | 	if n == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	ce, ok := n.(*ast.CallExpr)
 | 
					
						
							|  |  |  | 	if !ok {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	se, ok := ce.Fun.(*ast.SelectorExpr)
 | 
					
						
							|  |  |  | 	if !ok {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	id, ok := se.X.(*ast.Ident)
 | 
					
						
							|  |  |  | 	if !ok {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if id.Name != "t" { //t *testing.T
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch se.Sel.Name {
 | 
					
						
							|  |  |  | 	case "Errorf":
 | 
					
						
							|  |  |  | 	case "Logf":
 | 
					
						
							|  |  |  | 	case "Log":
 | 
					
						
							|  |  |  | 	case "Fatalf":
 | 
					
						
							|  |  |  | 	case "Fatal":
 | 
					
						
							|  |  |  | 	default:
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	// Check first arg, that should have basic lit with capital
 | 
					
						
							|  |  |  | 	if len(ce.Args) < 1 {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	bl, ok := ce.Args[0].(*ast.BasicLit)
 | 
					
						
							|  |  |  | 	if !ok {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if bl.Kind != token.STRING {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(bl.Value, "\"%s") || strings.HasPrefix(bl.Value, "\"%d") {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(bl.Value, "\"%v") || strings.HasPrefix(bl.Value, "\"%+v") {
 | 
					
						
							|  |  |  | 		return l
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	for i, u := range bl.Value {
 | 
					
						
							|  |  |  | 		// disregard "
 | 
					
						
							|  |  |  | 		if i == 1 && !unicode.IsUpper(u) {
 | 
					
						
							|  |  |  | 			l.err = fmt.Errorf("test error message %s doesn't start with an uppercase", bl.Value)
 | 
					
						
							|  |  |  | 			return nil
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if i == 1 {
 | 
					
						
							|  |  |  | 			break
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return l
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestImportTesting(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	walker := hasLowercaseWalker{}
 | 
					
						
							|  |  |  | 	err := filepath.Walk("..", walker.walk)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(walker.Errors) > 0 {
 | 
					
						
							|  |  |  | 		for _, err = range walker.Errors {
 | 
					
						
							|  |  |  | 			t.Error(err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | type hasImportTestingWalker struct {
 | 
					
						
							|  |  |  | 	Errors []error
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *hasImportTestingWalker) walk(path string, info os.FileInfo, _ error) error {
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	// only for regular files, not starting with a . and those that are go files.
 | 
					
						
							|  |  |  | 	if !info.Mode().IsRegular() {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "../.") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-07-21 16:23:52 +08:00
										 |  |  | 	if strings.Contains(path, "/vendor") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 	if strings.HasSuffix(path, "_test.go") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasSuffix(path, ".go") {
 | 
					
						
							|  |  |  | 		fs := token.NewFileSet()
 | 
					
						
							|  |  |  | 		f, err := parser.ParseFile(fs, path, nil, parser.AllErrors)
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			return err
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		for _, im := range f.Imports {
 | 
					
						
							|  |  |  | 			if im.Path.Value == `"testing"` {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 				absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 				w.Errors = append(w.Errors, fmt.Errorf("file %q is importing %q", absPath, "testing"))
 | 
					
						
							| 
									
										
										
										
											2020-01-28 19:07:11 +00:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestImportOrdering(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 	walker := testImportOrderingWalker{}
 | 
					
						
							|  |  |  | 	err := filepath.Walk("..", walker.walk)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(walker.Errors) > 0 {
 | 
					
						
							|  |  |  | 		for _, err = range walker.Errors {
 | 
					
						
							|  |  |  | 			t.Error(err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type testImportOrderingWalker struct {
 | 
					
						
							|  |  |  | 	Errors []error
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | func (w *testImportOrderingWalker) walk(path string, info os.FileInfo, _ error) error {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	if !info.Mode().IsRegular() {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(path, "../.") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-07-21 16:23:52 +08:00
										 |  |  | 	if strings.Contains(path, "/vendor") {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	if filepath.Ext(path) != ".go" {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs := token.NewFileSet()
 | 
					
						
							|  |  |  | 	f, err := parser.ParseFile(fs, path, nil, parser.AllErrors)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		return err
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if len(f.Imports) == 0 {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 3 blocks total, if
 | 
					
						
							|  |  |  | 	// 3 blocks: std + coredns + 3rd party
 | 
					
						
							|  |  |  | 	// 2 blocks: std + coredns, std + 3rd party, coredns + 3rd party
 | 
					
						
							|  |  |  | 	// 1 block: std, coredns, 3rd party
 | 
					
						
							|  |  |  | 	// first entry in a block specifies the type (std, coredns, 3rd party)
 | 
					
						
							|  |  |  | 	// we want: std, coredns, 3rd party
 | 
					
						
							|  |  |  | 	// more than 3 blocks as an error
 | 
					
						
							|  |  |  | 	blocks := [3][]*ast.ImportSpec{}
 | 
					
						
							|  |  |  | 	prevpos := 0
 | 
					
						
							|  |  |  | 	bl := 0
 | 
					
						
							|  |  |  | 	for _, im := range f.Imports {
 | 
					
						
							|  |  |  | 		line := fs.Position(im.Path.Pos()).Line
 | 
					
						
							|  |  |  | 		if line-prevpos > 1 && prevpos > 0 {
 | 
					
						
							|  |  |  | 			bl++
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if bl > 2 {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 			absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 			w.Errors = append(w.Errors, fmt.Errorf("more than %d import blocks in %q", bl, absPath))
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 		blocks[bl] = append(blocks[bl], im)
 | 
					
						
							|  |  |  | 		prevpos = line
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	// if it:
 | 
					
						
							| 
									
										
										
										
											2020-09-24 18:14:41 +02:00
										 |  |  | 	// contains strings github.com/coredns -> coredns
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	// contains dots -> 3rd
 | 
					
						
							|  |  |  | 	// no dots -> std
 | 
					
						
							|  |  |  | 	ip := [3]string{} // type per block, just string, either std, coredns, 3rd
 | 
					
						
							|  |  |  | 	for i := 0; i <= bl; i++ {
 | 
					
						
							|  |  |  | 		ip[i] = importtype(blocks[i][0].Path.Value)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Ok, now that we have the type, let's see if all members adhere to it.
 | 
					
						
							|  |  |  | 	// After that we check if the are in the right order.
 | 
					
						
							|  |  |  | 	for i := 0; i < bl; i++ {
 | 
					
						
							|  |  |  | 		for _, p := range blocks[i] {
 | 
					
						
							|  |  |  | 			t := importtype(p.Path.Value)
 | 
					
						
							|  |  |  | 			if t != ip[i] {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 				absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 				w.Errors = append(w.Errors, fmt.Errorf("import path for %s is not of the same type %q in %q", p.Path.Value, ip[i], absPath))
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check order
 | 
					
						
							|  |  |  | 	switch bl {
 | 
					
						
							|  |  |  | 	case 0:
 | 
					
						
							|  |  |  | 		// we don't care
 | 
					
						
							|  |  |  | 	case 1:
 | 
					
						
							|  |  |  | 		if ip[0] == "std" && ip[1] == "coredns" {
 | 
					
						
							|  |  |  | 			break // OK
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if ip[0] == "std" && ip[1] == "3rd" {
 | 
					
						
							|  |  |  | 			break // OK
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if ip[0] == "coredns" && ip[1] == "3rd" {
 | 
					
						
							|  |  |  | 			break // OK
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 		absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 		w.Errors = append(w.Errors, fmt.Errorf("import path in %q are not in the right order (std -> coredns -> 3rd)", absPath))
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	case 2:
 | 
					
						
							|  |  |  | 		if ip[0] == "std" && ip[1] == "coredns" && ip[2] == "3rd" {
 | 
					
						
							|  |  |  | 			break // OK
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2020-01-30 13:06:58 +01:00
										 |  |  | 		absPath, _ := filepath.Abs(path)
 | 
					
						
							|  |  |  | 		w.Errors = append(w.Errors, fmt.Errorf("import path in %q are not in the right order (std -> coredns -> 3rd)", absPath))
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func importtype(s string) string {
 | 
					
						
							| 
									
										
										
										
											2020-09-24 18:14:41 +02:00
										 |  |  | 	if strings.Contains(s, "github.com/coredns") {
 | 
					
						
							| 
									
										
										
										
											2020-01-30 09:19:26 +00:00
										 |  |  | 		return "coredns"
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if strings.Contains(s, ".") {
 | 
					
						
							|  |  |  | 		return "3rd"
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return "std"
 | 
					
						
							|  |  |  | }
 |