Created
October 8, 2023 16:34
-
-
Save eumel8/20012c51d6ab83de3e87231932e42c6d to your computer and use it in GitHub Desktop.
Sort Go Types with comments alphabetically
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mystruct | |
// LoggingSpec defines the desired state of Logging | |
type MyStruct struct { | |
// Reference to the logging system. Each of the `loggingRef`s can manage a fluentbit daemonset and a fluentd statefulset. | |
LoggingRef string `json:"loggingRef,omitempty"` | |
// Disable configuration check before applying new fluentd configuration. | |
FlowConfigCheckDisabled bool `json:"flowConfigCheckDisabled,omitempty"` | |
// Whether to skip invalid Flow and ClusterFlow resources | |
SkipInvalidResources bool `json:"skipInvalidResources,omitempty"` | |
// Override generated config. This is a *raw* configuration string for troubleshooting purposes. | |
FlowConfigOverride string `json:"flowConfigOverride,omitempty"` | |
// ConfigCheck settings that apply to both fluentd and syslog-ng | |
ConfigCheck ConfigCheck `json:"configCheck,omitempty"` | |
// FluentbitAgent daemonset configuration. | |
// Deprecated, will be removed with next major version | |
// Migrate to the standalone NodeAgent resource | |
FluentbitSpec *FluentbitSpec `json:"fluentbit,omitempty"` | |
// Fluentd statefulset configuration | |
FluentdSpec *FluentdSpec `json:"fluentd,omitempty"` | |
// Syslog-NG statefulset configuration | |
SyslogNGSpec *SyslogNGSpec `json:"syslogNG,omitempty"` | |
// Default flow for unmatched logs. This Flow configuration collects all logs that didn't matched any other Flow. | |
DefaultFlowSpec *DefaultFlowSpec `json:"defaultFlow,omitempty"` | |
// GlobalOutput name to flush ERROR events to | |
ErrorOutputRef string `json:"errorOutputRef,omitempty"` | |
// Global filters to apply on logs before any match or filter mechanism. | |
GlobalFilters []Filter `json:"globalFilters,omitempty"` | |
// Limit namespaces to watch Flow and Output custom resources. | |
WatchNamespaces []string `json:"watchNamespaces,omitempty"` | |
// WatchNamespaceSelector is a LabelSelector to find matching namespaces to watch as in WatchNamespaces | |
WatchNamespaceSelector *metav1.LabelSelector `json:"watchNamespaceSelector,omitempty"` | |
// Cluster domain name to be used when templating URLs to services (default: "cluster.local."). | |
ClusterDomain *string `json:"clusterDomain,omitempty"` | |
// Namespace for cluster wide configuration resources like CLusterFlow and ClusterOutput. | |
// This should be a protected namespace from regular users. | |
// Resources like fluentbit and fluentd will run in this namespace as well. | |
ControlNamespace string `json:"controlNamespace"` | |
// Allow configuration of cluster resources from any namespace. Mutually exclusive with ControlNamespace restriction of Cluster resources | |
AllowClusterResourcesFromAllNamespaces bool `json:"allowClusterResourcesFromAllNamespaces,omitempty"` | |
// InlineNodeAgent Configuration | |
// Deprecated, will be removed with next major version | |
NodeAgents []*InlineNodeAgent `json:"nodeAgents,omitempty"` | |
// EnableRecreateWorkloadOnImmutableFieldChange enables the operator to recreate the | |
// fluentbit daemonset and the fluentd statefulset (and possibly other resource in the future) | |
// in case there is a change in an immutable field | |
// that otherwise couldn't be managed with a simple update. | |
EnableRecreateWorkloadOnImmutableFieldChange bool `json:"enableRecreateWorkloadOnImmutableFieldChange,omitempty"` | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"go/ast" | |
"go/parser" | |
"go/token" | |
"io/ioutil" | |
"sort" | |
"strings" | |
) | |
type FieldInfo struct { | |
Name string | |
Type string | |
Tag string | |
Comment string | |
} | |
type MyStructInfo struct { | |
Fields []*FieldInfo | |
} | |
func main() { | |
// Lese den Inhalt der Datei "mystruct.go" ein | |
content, err := ioutil.ReadFile("mystruct2.go") | |
if err != nil { | |
fmt.Println("Fehler beim Lesen der Datei:", err) | |
return | |
} | |
fset := token.NewFileSet() | |
node, err := parser.ParseFile(fset, "", content, parser.ParseComments) | |
if err != nil { | |
fmt.Println("Fehler beim Parsen der Datei:", err) | |
return | |
} | |
// Finde das Struct in der Datei | |
var myStructInfo *MyStructInfo | |
for _, decl := range node.Decls { | |
if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.TYPE { | |
for _, spec := range gd.Specs { | |
if ts, ok := spec.(*ast.TypeSpec); ok && ts.Name.Name == "MyStruct" { | |
myStructInfo = extractFields(ts) | |
break | |
} | |
} | |
} | |
} | |
if myStructInfo == nil { | |
fmt.Println("Struct 'MyStruct' nicht gefunden") | |
return | |
} | |
// Sortiere die Felder alphabetisch nach Namen | |
sort.Slice(myStructInfo.Fields, func(i, j int) bool { | |
return myStructInfo.Fields[i].Name < myStructInfo.Fields[j].Name | |
}) | |
// Gib die sortierten Felder mit Kommentaren über den Typen aus | |
for _, field := range myStructInfo.Fields { | |
fmt.Printf("// %s\n", field.Comment) | |
fmt.Printf("%s %s %s\n", field.Name, field.Type, field.Tag) | |
} | |
} | |
func extractFields(ts *ast.TypeSpec) *MyStructInfo { | |
structType, ok := ts.Type.(*ast.StructType) | |
if !ok { | |
return nil | |
} | |
fields := make([]*FieldInfo, len(structType.Fields.List)) | |
for i, field := range structType.Fields.List { | |
fieldName := field.Names[0].Name | |
fieldType := fieldTypeString(field.Type) | |
fieldTag := "" | |
if field.Tag != nil { | |
fieldTag = field.Tag.Value | |
} | |
comment := extractComment(field.Doc) | |
fields[i] = &FieldInfo{Name: fieldName, Type: fieldType, Tag: fieldTag, Comment: comment} | |
} | |
return &MyStructInfo{Fields: fields} | |
} | |
func fieldTypeString(expr ast.Expr) string { | |
switch t := expr.(type) { | |
case *ast.Ident: | |
return t.Name | |
case *ast.StarExpr: | |
return "*" + fieldTypeString(t.X) | |
} | |
return "" | |
} | |
func extractComment(comments *ast.CommentGroup) string { | |
if comments != nil { | |
commentText := comments.Text() | |
return strings.TrimSpace(commentText) | |
} | |
return "" | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment