Refactor kafka to pure Go (franz-go), fix DBC stubs, update Dockerfile

This commit is contained in:
Chris Rai
2026-01-31 00:05:47 -05:00
parent fbb820d7b3
commit b5bec57dfa
776 changed files with 18945 additions and 2052 deletions

View File

@@ -0,0 +1,212 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"text/scanner"
"github.com/fiskerinc/cloud-services/pkg/can-go/internal/generate"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/definitiontypeorder"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/intervals"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/lineendings"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/messagenames"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/multiplexedsignals"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/newsymbols"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/nodereferences"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/noreservedsignals"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/requireddefinitions"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/signalbounds"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/signalnames"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/singletondefinitions"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/siunits"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/uniquenodenames"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/uniquesignalnames"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/unitsuffixes"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/valuedescriptions"
"github.com/fiskerinc/cloud-services/pkg/can-go/pkg/dbc/analysis/passes/version"
"github.com/fatih/color"
"gopkg.in/alecthomas/kingpin.v2"
)
func main() {
app := kingpin.New("cantool", "CAN tool for Go programmers")
generateCommand(app)
lintCommand(app)
kingpin.MustParse(app.Parse(os.Args[1:]))
}
func generateCommand(app *kingpin.Application) {
command := app.Command("generate", "generate CAN messages")
inputDir := command.
Arg("input-dir", "input directory").
Required().
ExistingDir()
outputDir := command.
Arg("output-dir", "output directory").
Required().
String()
command.Action(func(c *kingpin.ParseContext) error {
return filepath.Walk(*inputDir, func(p string, i os.FileInfo, err error) error {
if err != nil {
return err
}
if i.IsDir() || filepath.Ext(p) != ".dbc" {
return nil
}
relPath, err := filepath.Rel(*inputDir, p)
if err != nil {
return err
}
outputFile := relPath + ".go"
outputPath := filepath.Join(*outputDir, outputFile)
return genGo(p, outputPath)
})
})
}
func lintCommand(app *kingpin.Application) {
command := app.Command("lint", "lint DBC files")
fileOrDir := command.
Arg("file-or-dir", "DBC file or directory").
Required().
ExistingFileOrDir()
command.Action(func(context *kingpin.ParseContext) error {
filesToLint, err := resolveFileOrDirectory(*fileOrDir)
if err != nil {
return err
}
var hasFailed bool
for _, lintFile := range filesToLint {
f, err := os.Open(lintFile)
if err != nil {
return err
}
source, err := ioutil.ReadAll(f)
if err != nil {
return err
}
p := dbc.NewParser(f.Name(), source)
if err := p.Parse(); err != nil {
printError(source, err.Position(), err.Reason(), "parse")
continue
}
for _, a := range analyzers() {
pass := &analysis.Pass{
Analyzer: a,
File: p.File(),
}
if err := a.Run(pass); err != nil {
return err
}
hasFailed = hasFailed || len(pass.Diagnostics) > 0
for _, d := range pass.Diagnostics {
printError(source, d.Pos, d.Message, a.Name)
}
}
}
if hasFailed {
return errors.New("one or more lint errors")
}
return nil
})
}
func analyzers() []*analysis.Analyzer {
return []*analysis.Analyzer{
// TODO: Re-evaluate if we want boolprefix.Analyzer(), since it creates a lot of churn in vendor schemas
definitiontypeorder.Analyzer(),
intervals.Analyzer(),
lineendings.Analyzer(),
messagenames.Analyzer(),
multiplexedsignals.Analyzer(),
newsymbols.Analyzer(),
nodereferences.Analyzer(),
noreservedsignals.Analyzer(),
requireddefinitions.Analyzer(),
signalbounds.Analyzer(),
signalnames.Analyzer(),
singletondefinitions.Analyzer(),
siunits.Analyzer(),
uniquenodenames.Analyzer(),
uniquesignalnames.Analyzer(),
unitsuffixes.Analyzer(),
valuedescriptions.Analyzer(),
version.Analyzer(),
}
}
func genGo(inputFile, outputFile string) error {
if err := os.MkdirAll(filepath.Dir(outputFile), 0o755); err != nil {
return err
}
input, err := ioutil.ReadFile(inputFile)
if err != nil {
return err
}
result, err := generate.Compile(inputFile, input)
if err != nil {
return err
}
for _, warning := range result.Warnings {
return warning
}
output, err := generate.Database(result.Hash, result.Database)
if err != nil {
return err
}
if err := ioutil.WriteFile(outputFile, output, 0o600); err != nil {
return err
}
fmt.Println("hash:", result.Hash)
fmt.Println("version:", result.Database.Version)
fmt.Println("wrote:", outputFile)
return nil
}
func resolveFileOrDirectory(fileOrDirectory string) ([]string, error) {
fileInfo, err := os.Stat(fileOrDirectory)
if err != nil {
return nil, err
}
if !fileInfo.IsDir() {
return []string{fileOrDirectory}, nil
}
var files []string
if err := filepath.Walk(fileOrDirectory, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() && filepath.Ext(path) == ".dbc" {
files = append(files, path)
}
return nil
}); err != nil {
return nil, err
}
return files, nil
}
func printError(source []byte, pos scanner.Position, msg, name string) {
fmt.Printf("\n%s: %s (%s)\n", pos, color.RedString("%s", msg), name)
fmt.Printf("%s\n", getSourceLine(source, pos))
fmt.Printf("%s\n", caretAtPosition(pos))
}
func getSourceLine(source []byte, pos scanner.Position) []byte {
lineStart := pos.Offset
for lineStart > 0 && source[lineStart-1] != '\n' {
lineStart--
}
lineEnd := pos.Offset
for lineEnd < len(source) && source[lineEnd] != '\n' {
lineEnd++
}
return source[lineStart:lineEnd]
}
func caretAtPosition(pos scanner.Position) string {
return strings.Repeat(" ", pos.Column-1) + color.YellowString("^")
}