Source file src/cmd/cgo/internal/testerrors/argposition_test.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Issue 42580: cmd/cgo: shifting identifier position in ast
     6  
     7  package errorstest
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"go/ast"
    13  	"go/parser"
    14  	"go/token"
    15  	"internal/testenv"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  	"strings"
    20  	"testing"
    21  )
    22  
    23  type ShortPosition struct {
    24  	Line    int
    25  	Column  int
    26  	Visited bool
    27  }
    28  
    29  type IdentPositionInfo map[string][]ShortPosition
    30  
    31  type Visitor struct {
    32  	identPosInfo IdentPositionInfo
    33  	fset         *token.FileSet
    34  	t            *testing.T
    35  }
    36  
    37  func (v *Visitor) Visit(node ast.Node) ast.Visitor {
    38  	if ident, ok := node.(*ast.Ident); ok {
    39  		if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
    40  			gotMatch := false
    41  			var errorMessage strings.Builder
    42  			for caseIndex, expectedPos := range expectedPositions {
    43  				actualPosition := v.fset.PositionFor(ident.Pos(), true)
    44  				errorOccurred := false
    45  				if expectedPos.Line != actualPosition.Line {
    46  					fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
    47  					errorOccurred = true
    48  				}
    49  				if expectedPos.Column != actualPosition.Column {
    50  					fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
    51  					errorOccurred = true
    52  				}
    53  				if errorOccurred {
    54  					continue
    55  				}
    56  				gotMatch = true
    57  				expectedPositions[caseIndex].Visited = true
    58  			}
    59  
    60  			if !gotMatch {
    61  				v.t.Error(errorMessage.String())
    62  			}
    63  		}
    64  	}
    65  	return v
    66  }
    67  
    68  func TestArgumentsPositions(t *testing.T) {
    69  	testenv.MustHaveCGO(t)
    70  	testenv.MustHaveExec(t)
    71  
    72  	testdata, err := filepath.Abs("testdata")
    73  	if err != nil {
    74  		t.Fatal(err)
    75  	}
    76  
    77  	tmpPath := t.TempDir()
    78  
    79  	dir := filepath.Join(tmpPath, "src", "testpositions")
    80  	if err := os.MkdirAll(dir, 0755); err != nil {
    81  		t.Fatal(err)
    82  	}
    83  
    84  	cmd := exec.Command("go", "tool", "cgo",
    85  		"-srcdir", testdata,
    86  		"-objdir", dir,
    87  		"issue42580.go")
    88  	cmd.Stderr = new(bytes.Buffer)
    89  
    90  	err = cmd.Run()
    91  	if err != nil {
    92  		t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
    93  	}
    94  	mainProcessed, err := os.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	fset := token.NewFileSet()
    99  	f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
   100  	if err != nil {
   101  		fmt.Println(err)
   102  		return
   103  	}
   104  
   105  	expectation := IdentPositionInfo{
   106  		"checkedPointer": []ShortPosition{
   107  			ShortPosition{
   108  				Line:   32,
   109  				Column: 56,
   110  			},
   111  		},
   112  		"singleInnerPointerChecked": []ShortPosition{
   113  			ShortPosition{
   114  				Line:   37,
   115  				Column: 91,
   116  			},
   117  		},
   118  		"doublePointerChecked": []ShortPosition{
   119  			ShortPosition{
   120  				Line:   42,
   121  				Column: 91,
   122  			},
   123  		},
   124  	}
   125  	for _, decl := range f.Decls {
   126  		if fdecl, ok := decl.(*ast.FuncDecl); ok {
   127  			ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
   128  		}
   129  	}
   130  	for ident, positions := range expectation {
   131  		for _, position := range positions {
   132  			if !position.Visited {
   133  				t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
   134  			}
   135  		}
   136  	}
   137  }
   138  

View as plain text