github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/_utils/terror_gen/gen.go (about)

     1  // Copyright 2019 PingCAP, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package main
    15  
    16  import (
    17  	"bytes"
    18  	"fmt"
    19  	"go/ast"
    20  	"go/parser"
    21  	"go/token"
    22  	"os"
    23  	"strings"
    24  	"text/template"
    25  )
    26  
    27  const (
    28  	templateCheckerFile  = "checker_template.go"
    29  	generatedCheckerFile = "checker_generated.go"
    30  )
    31  
    32  var templatePlaceHolder = []byte("// TODO: fillin me")
    33  
    34  func getErrorInstances(filepath string) []string {
    35  	fset := token.NewFileSet()
    36  	parserMode := parser.ParseComments
    37  	var (
    38  		fileAst *ast.File
    39  		err     error
    40  		result  = make([]string, 0, 100)
    41  	)
    42  
    43  	fileAst, err = parser.ParseFile(fset, filepath, nil, parserMode)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  
    48  	for _, d := range fileAst.Decls {
    49  		switch decl := d.(type) {
    50  		case *ast.GenDecl:
    51  			specs := decl.Specs
    52  			for _, spec := range specs {
    53  				vs, ok := spec.(*ast.ValueSpec)
    54  				if !ok {
    55  					continue
    56  				}
    57  				name := vs.Names[0].Name
    58  				if strings.HasPrefix(name, "Err") {
    59  					result = append(result, name)
    60  				}
    61  			}
    62  		}
    63  	}
    64  	return result
    65  }
    66  
    67  func genFile(names []string) {
    68  	var (
    69  		buf, genBuf bytes.Buffer
    70  		content     []byte
    71  		err         error
    72  	)
    73  	content, err = os.ReadFile(templateCheckerFile)
    74  	if err != nil {
    75  		panic(err)
    76  	}
    77  	fmt.Fprint(&buf, "\n")
    78  	for _, name := range names {
    79  		fmt.Fprintf(&buf, "\t{\"%s\", terror.%s},\n", name, name)
    80  	}
    81  
    82  	data := map[string]interface{}{
    83  		"ErrList":     buf.String(),
    84  		"CheckerFile": generatedCheckerFile,
    85  	}
    86  	t := template.Must(template.New(generatedCheckerFile).Parse(string(content)))
    87  	err = t.Execute(&genBuf, data)
    88  	if err != nil {
    89  		panic(err)
    90  	}
    91  	err = os.WriteFile(generatedCheckerFile, genBuf.Bytes(), 0o600)
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  }
    96  
    97  func main() {
    98  	names := getErrorInstances(os.Args[1])
    99  	genFile(names)
   100  }