From 351b998d9e6c2469ef9d357d3463a45efa335ebf Mon Sep 17 00:00:00 2001 From: Inkeliz Date: Thu, 1 Sep 2022 23:34:51 +0100 Subject: [PATCH] cmd,kmparser,kmcheck: add conflict and reserved names warnings Now, Karmem will report with "Warnings" with the schema contains potential conflicts with the names or uses reserved names. It's possible to avoid it using `-s`. Fixes #17 --- cmd/README.md | 22 + cmd/karmem/kmcheck/assemblyscript.go | 108 +++ cmd/karmem/kmcheck/c.go | 83 +++ cmd/karmem/kmcheck/dotnet.go | 155 +++++ cmd/karmem/kmcheck/general.go | 152 ++++ cmd/karmem/kmcheck/go.go | 91 +++ cmd/karmem/kmcheck/karmem.go | 33 + cmd/karmem/kmcheck/kmcheck.go | 48 ++ cmd/karmem/kmcheck/odin.go | 32 + cmd/karmem/kmcheck/swift.go | 124 ++++ cmd/karmem/kmcheck/zig.go | 114 +++ cmd/karmem/kmparser/kmgen.km | 85 ++- cmd/karmem/kmparser/kmparser_extension.go | 2 +- cmd/karmem/kmparser/kmparser_generated.go | 807 +++++++++++++++++++++- cmd/karmem/kmparser/parser.go | 20 +- cmd/karmem/main.go | 59 +- 16 files changed, 1882 insertions(+), 53 deletions(-) create mode 100644 cmd/README.md create mode 100644 cmd/karmem/kmcheck/assemblyscript.go create mode 100644 cmd/karmem/kmcheck/c.go create mode 100644 cmd/karmem/kmcheck/dotnet.go create mode 100644 cmd/karmem/kmcheck/general.go create mode 100644 cmd/karmem/kmcheck/go.go create mode 100644 cmd/karmem/kmcheck/karmem.go create mode 100644 cmd/karmem/kmcheck/kmcheck.go create mode 100644 cmd/karmem/kmcheck/odin.go create mode 100644 cmd/karmem/kmcheck/swift.go create mode 100644 cmd/karmem/kmcheck/zig.go diff --git a/cmd/README.md b/cmd/README.md new file mode 100644 index 0000000..854e525 --- /dev/null +++ b/cmd/README.md @@ -0,0 +1,22 @@ +## cmd/karmem + +This folder contains files related to the karmem cli tool. The `cmd/karmem` is equivalent of +`protoc` or `flatc`. That is designed to be used as a command line tool, in order to read +karmem files and generate code for the corresponding languages. + +## Usage + +You can run this program with `go run karmem.org/cmd/karmem help`. + +## Structure + +- kmcheck: + - This package will verify if the parsed karmem file (from the `kmparser` package) contains +any potential conflict, or use any or uses any deprecated features. +- kmgen: + - This generates code for multiple languages. That will read the parsed +file (from the `kmparser` package) and generates the code for the given language. +- kmparser: + - This package is responsible to read karmem schema file. That package is +language independent. +- main.go: The main file for the karmem cli tool (that uses `kmparser`, `kmgen` and `kmcheck`). \ No newline at end of file diff --git a/cmd/karmem/kmcheck/assemblyscript.go b/cmd/karmem/kmcheck/assemblyscript.go new file mode 100644 index 0000000..b3ec831 --- /dev/null +++ b/cmd/karmem/kmcheck/assemblyscript.go @@ -0,0 +1,108 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewAssemblyScript()) } + +type AssemblyScript struct { + RestrictedWords *RestrictedWords +} + +func (v *AssemblyScript) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) +} + +func (v *AssemblyScript) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewAssemblyScript() *AssemblyScript { + return &AssemblyScript{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageAssemblyScript, + Rules: []WordRule{ + NewMatchRule("await"), + NewMatchRule("break"), + NewMatchRule("case"), + NewMatchRule("catch"), + NewMatchRule("class"), + NewMatchRule("const"), + NewMatchRule("continue"), + NewMatchRule("debugger"), + NewMatchRule("default"), + NewMatchRule("delete"), + NewMatchRule("do"), + NewMatchRule("else"), + NewMatchRule("enum"), + NewMatchRule("export"), + NewMatchRule("extends"), + NewMatchRule("false"), + NewMatchRule("finally"), + NewMatchRule("for"), + NewMatchRule("function"), + NewMatchRule("if"), + NewMatchRule("import"), + NewMatchRule("in"), + NewMatchRule("of"), + NewMatchRule("instanceof"), + NewMatchRule("new"), + NewMatchRule("null"), + NewMatchRule("return"), + NewMatchRule("super"), + NewMatchRule("switch"), + NewMatchRule("this"), + NewMatchRule("throw"), + NewMatchRule("true"), + NewMatchRule("try"), + NewMatchRule("typeof"), + NewMatchRule("type"), + NewMatchRule("var"), + NewMatchRule("void"), + NewMatchRule("while"), + NewMatchRule("with"), + NewMatchRule("yield"), + NewMatchRule("let"), + NewMatchRule("static"), + NewMatchRule("as"), + NewMatchRule("any"), + NewMatchRule("set"), + NewMatchRule("from"), + NewMatchRule("constructor"), + NewMatchRule("module"), + NewMatchRule("require"), + NewMatchRule("implements"), + NewMatchRule("interface"), + NewMatchRule("package"), + NewMatchRule("private"), + NewMatchRule("protected"), + NewMatchRule("and"), + NewMatchRule("public"), + NewMatchRule("i8"), + NewMatchRule("i16"), + NewMatchRule("i32"), + NewMatchRule("i64"), + NewMatchRule("u8"), + NewMatchRule("u16"), + NewMatchRule("u32"), + NewMatchRule("u64"), + NewMatchRule("f32"), + NewMatchRule("f64"), + NewMatchRule("bool"), + NewMatchRule("boolean"), + NewMatchRule("isize"), + NewMatchRule("usize"), + NewMatchRule("v128"), + NewMatchRule("externref"), + NewMatchRule("funcref"), + NewMatchRule("string"), + NewMatchRule("number"), + NewMatchRule("symbol"), + NewMatchRule("undefined"), + }, + }, + } +} diff --git a/cmd/karmem/kmcheck/c.go b/cmd/karmem/kmcheck/c.go new file mode 100644 index 0000000..d86f647 --- /dev/null +++ b/cmd/karmem/kmcheck/c.go @@ -0,0 +1,83 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewC()) } + +type C struct { + RestrictedWords *RestrictedWords + CollisionArraySuffix *CollisionArraySuffix +} + +func (v *C) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) + +} + +func (v *C) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewC() *C { + return &C{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageC, + Rules: []WordRule{ + NewMatchRule("auto"), + NewMatchRule("else"), + NewMatchRule("long"), + NewMatchRule("switch"), + NewMatchRule("break"), + NewMatchRule("enum"), + NewMatchRule("register"), + NewMatchRule("typedef"), + NewMatchRule("case"), + NewMatchRule("extern"), + NewMatchRule("return"), + NewMatchRule("union"), + NewMatchRule("char"), + NewMatchRule("float"), + NewMatchRule("short"), + NewMatchRule("unsigned"), + NewMatchRule("const"), + NewMatchRule("for"), + NewMatchRule("signed"), + NewMatchRule("void"), + NewMatchRule("continue"), + NewMatchRule("goto"), + NewMatchRule("sizeof"), + NewMatchRule("volatile"), + NewMatchRule("default"), + NewMatchRule("if"), + NewMatchRule("static"), + NewMatchRule("while"), + NewMatchRule("do"), + NewMatchRule("int"), + NewMatchRule("struct"), + NewMatchRule("double"), + NewMatchRegexRule("^int[0-9]+_t$"), + NewMatchRegexRule("^uint[0-9]+_t$"), + NewMatchRegexRule("^int_fast[0-9]+_t$"), + NewMatchRegexRule("^uint_fast[0-9]+_t$"), + NewMatchRegexRule("^int_least[0-9]+_t$"), + NewMatchRegexRule("^uint_least[0-9]+_t$"), + NewMatchRegexRule("true"), + NewMatchRegexRule("false"), + NewMatchRegexRule("null"), + NewMatchRegexRule("bool"), + }, + }, + CollisionArraySuffix: &CollisionArraySuffix{ + Language: kmparser.LanguageC, + Rules: []WordRule{ + NewMatchSuffix("size"), + NewMatchSuffix("pointer"), + NewMatchSuffix("length"), + }, + }, + } +} diff --git a/cmd/karmem/kmcheck/dotnet.go b/cmd/karmem/kmcheck/dotnet.go new file mode 100644 index 0000000..1bc4dce --- /dev/null +++ b/cmd/karmem/kmcheck/dotnet.go @@ -0,0 +1,155 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewDotNet()) } + +type DotNet struct { + RestrictedWords *RestrictedWords + CollisionParentChildField *CollisionParentChildField +} + +func NewDotNet() *DotNet { + return &DotNet{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageDotnet, + Rules: []WordRule{ + NewMatchRule("abstract"), + NewMatchRule("as"), + NewMatchRule("base"), + NewMatchRule("bool"), + NewMatchRule("break"), + NewMatchRule("byte"), + NewMatchRule("case"), + NewMatchRule("catch"), + NewMatchRule("char"), + NewMatchRule("checked"), + NewMatchRule("class"), + NewMatchRule("const"), + NewMatchRule("continue"), + NewMatchRule("decimal"), + NewMatchRule("default"), + NewMatchRule("delegate"), + NewMatchRule("do"), + NewMatchRule("double"), + NewMatchRule("else"), + NewMatchRule("enum"), + NewMatchRule("event"), + NewMatchRule("explicit"), + NewMatchRule("extern"), + NewMatchRule("false"), + NewMatchRule("finally"), + NewMatchRule("fixed"), + NewMatchRule("float"), + NewMatchRule("for"), + NewMatchRule("foreach"), + NewMatchRule("goto"), + NewMatchRule("if"), + NewMatchRule("implicit"), + NewMatchRule("in"), + NewMatchRule("int"), + NewMatchRule("interface"), + NewMatchRule("internal"), + NewMatchRule("is"), + NewMatchRule("lock"), + NewMatchRule("long"), + NewMatchRule("namespace"), + NewMatchRule("new"), + NewMatchRule("null"), + NewMatchRule("object"), + NewMatchRule("operator"), + NewMatchRule("out"), + NewMatchRule("override"), + NewMatchRule("params"), + NewMatchRule("private"), + NewMatchRule("protected"), + NewMatchRule("public"), + NewMatchRule("readonly"), + NewMatchRule("ref"), + NewMatchRule("return"), + NewMatchRule("sbyte"), + NewMatchRule("sealed"), + NewMatchRule("short"), + NewMatchRule("sizeof"), + NewMatchRule("stackalloc"), + NewMatchRule("static"), + NewMatchRule("string"), + NewMatchRule("struct"), + NewMatchRule("switch"), + NewMatchRule("this"), + NewMatchRule("throw"), + NewMatchRule("true"), + NewMatchRule("try"), + NewMatchRule("typeof"), + NewMatchRule("uint"), + NewMatchRule("ulong"), + NewMatchRule("unchecked"), + NewMatchRule("unsafe"), + NewMatchRule("ushort"), + NewMatchRule("using"), + NewMatchRule("virtual"), + NewMatchRule("void"), + NewMatchRule("volatile"), + NewMatchRule("while"), + NewMatchRule("add"), + NewMatchRule("and"), + NewMatchRule("alias"), + NewMatchRule("ascending"), + NewMatchRule("args"), + NewMatchRule("async"), + NewMatchRule("await"), + NewMatchRule("by"), + NewMatchRule("descending"), + NewMatchRule("dynamic"), + NewMatchRule("equals"), + NewMatchRule("from"), + NewMatchRule("get"), + NewMatchRule("global"), + NewMatchRule("group"), + NewMatchRule("init"), + NewMatchRule("into"), + NewMatchRule("join"), + NewMatchRule("let"), + NewMatchRule("managed"), + NewMatchRule("nameof"), + NewMatchRule("nint"), + NewMatchRule("not"), + NewMatchRule("notnull"), + NewMatchRule("nuint"), + NewMatchRule("on"), + NewMatchRule("or"), + NewMatchRule("orderby"), + NewMatchRule("partial"), + NewMatchRule("record"), + NewMatchRule("remove"), + NewMatchRule("required"), + NewMatchRule("select"), + NewMatchRule("set"), + NewMatchRule("unmanage"), + NewMatchRule("value"), + NewMatchRule("var"), + NewMatchRule("when "), + NewMatchRule("where"), + NewMatchRule("with"), + NewMatchRule("yield"), + }, + }, + CollisionParentChildField: &CollisionParentChildField{ + Language: kmparser.LanguageDotnet, + }, + } +} + +func (v *DotNet) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) + v.CollisionParentChildField.CheckStruct(mutex, parsed, target) +} + +func (v *DotNet) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) + v.CollisionParentChildField.CheckEnum(mutex, parsed, target) +} diff --git a/cmd/karmem/kmcheck/general.go b/cmd/karmem/kmcheck/general.go new file mode 100644 index 0000000..8e475f9 --- /dev/null +++ b/cmd/karmem/kmcheck/general.go @@ -0,0 +1,152 @@ +package kmcheck + +import ( + "fmt" + "regexp" + "strings" + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +type WordRule func(needle string) bool + +func NewMatchRule(match string) WordRule { + return func(needle string) bool { + return strings.EqualFold(match, needle) + } +} + +func NewMatchRegexRule(reg string) WordRule { + r := regexp.MustCompile(reg) + return func(needle string) bool { + return r.MatchString(strings.ToLower(needle)) + } +} + +func NewMatchPrefix(match string) WordRule { + return func(needle string) bool { + return strings.HasPrefix(match, strings.ToLower(needle)) + } +} + +func NewMatchSuffix(match string) WordRule { + return func(needle string) bool { + return strings.HasSuffix(match, strings.ToLower(needle)) + } +} + +type RestrictedWords struct { + Language kmparser.Language + Rules []WordRule +} + +func (r *RestrictedWords) newWarning(mutex *sync.Mutex, k *[]kmparser.Warning, msg string) { + mutex.Lock() + defer mutex.Unlock() + + *k = append(*k, kmparser.Warning{Data: kmparser.WarningData{ + Message: msg, + Rule: "RestrictedWords", + Type: kmparser.RuleTypeReservedName, + Languages: r.Language, + }}) +} + +func (r *RestrictedWords) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + for _, word := range r.Rules { + if word(target.Name) { + r.newWarning(mutex, &target.Warnings, fmt.Sprintf("%s is a restricted name", target.Name)) + } + for i := range target.Fields { + field := &target.Fields[i] + if word(field.Data.Name) { + r.newWarning(mutex, &field.Data.Warnings, fmt.Sprintf("%s is a restricted name", field.Data.Name)) + } + } + } +} + +func (r *RestrictedWords) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + for _, word := range r.Rules { + if word(target.Name) { + r.newWarning(mutex, &target.Warnings, fmt.Sprintf("%s is a restricted name", target.Name)) + } + for i := range target.Fields { + field := &target.Fields[i] + if word(field.Data.Name) { + r.newWarning(mutex, &field.Data.Warnings, fmt.Sprintf("%s is a restricted name", field.Data.Name)) + } + } + } +} + +type CollisionParentChildField struct { + Language kmparser.Language +} + +func (r *CollisionParentChildField) newWarning(mutex *sync.Mutex, k *[]kmparser.Warning, msg string) { + mutex.Lock() + defer mutex.Unlock() + + *k = append(*k, kmparser.Warning{Data: kmparser.WarningData{ + Message: msg, + Rule: "FieldNameMatchesStructName", + Type: kmparser.RuleTypeDuplicateName, + Languages: r.Language, + }}) +} + +func (r *CollisionParentChildField) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + for i := range target.Fields { + x := &target.Fields[i] + if target.Name == x.Data.Name { + r.newWarning(mutex, &x.Data.Warnings, fmt.Sprintf("%s is the same name of parent struct", target.Name)) + } + } +} + +func (r *CollisionParentChildField) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + for i := range target.Fields { + x := &target.Fields[i] + if target.Name == x.Data.Name { + r.newWarning(mutex, &target.Warnings, fmt.Sprintf("%s is the same name of parent enum", target.Name)) + } + } +} + +type CollisionArraySuffix struct { + Language kmparser.Language + Rules []WordRule +} + +func (r *CollisionArraySuffix) newWarning(mutex *sync.Mutex, k *[]kmparser.Warning, msg string) { + mutex.Lock() + defer mutex.Unlock() + *k = append(*k, kmparser.Warning{Data: kmparser.WarningData{ + Message: msg, + Rule: "", + Type: kmparser.RuleTypeDuplicateName, + Languages: kmparser.LanguageC, + }}) +} + +func (r *CollisionArraySuffix) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + for i := range target.Fields { + x := &target.Fields[i] + for _, v := range r.Rules { + if !v(x.Data.Name) { + continue + } + for i := range target.Fields { + y := &target.Fields[i] + if strings.EqualFold(x.Data.Name, y.Data.Name) { + r.newWarning(mutex, &y.Data.Warnings, fmt.Sprintf("%s may collides with %s, the generated code may generate functions with such suffix", x.Data.Name, y.Data.Name)) + } + } + } + } +} + +func (r *CollisionArraySuffix) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { +} diff --git a/cmd/karmem/kmcheck/go.go b/cmd/karmem/kmcheck/go.go new file mode 100644 index 0000000..8845133 --- /dev/null +++ b/cmd/karmem/kmcheck/go.go @@ -0,0 +1,91 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewGolang()) } + +type Golang struct { + RestrictedWords *RestrictedWords +} + +func (v *Golang) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) +} + +func (v *Golang) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewGolang() *Golang { + return &Golang{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageGolang, + Rules: []WordRule{ + NewMatchRule("break"), + NewMatchRule("default"), + NewMatchRule("delete"), + NewMatchRule("func"), + NewMatchRule("interface"), + NewMatchRule("select"), + NewMatchRule("case"), + NewMatchRule("defer"), + NewMatchRule("go"), + NewMatchRule("map"), + NewMatchRule("struct"), + NewMatchRule("chan"), + NewMatchRule("else"), + NewMatchRule("goto"), + NewMatchRule("package"), + NewMatchRule("switch"), + NewMatchRule("const"), + NewMatchRule("fallthrough"), + NewMatchRule("if"), + NewMatchRule("range"), + NewMatchRule("type"), + NewMatchRule("continue"), + NewMatchRule("for"), + NewMatchRule("import"), + NewMatchRule("return"), + NewMatchRule("var"), + NewMatchRule("append"), + NewMatchRule("bool"), + NewMatchRule("byte"), + NewMatchRule("cap"), + NewMatchRule("close"), + NewMatchRule("complex"), + NewMatchRule("complex64"), + NewMatchRule("complex128"), + NewMatchRule("uint16"), + NewMatchRule("copy"), + NewMatchRule("false"), + NewMatchRule("float32"), + NewMatchRule("float64"), + NewMatchRule("imag"), + NewMatchRule("int"), + NewMatchRule("int8"), + NewMatchRule("int16"), + NewMatchRule("uint32"), + NewMatchRule("int32"), + NewMatchRule("int64"), + NewMatchRule("iota"), + NewMatchRule("len"), + NewMatchRule("make"), + NewMatchRule("new"), + NewMatchRule("nil"), + NewMatchRule("panic"), + NewMatchRule("uint64"), + NewMatchRule("real"), + NewMatchRule("recover"), + NewMatchRule("string"), + NewMatchRule("true"), + NewMatchRule("uint"), + NewMatchRule("uint8"), + NewMatchRule("uintptr"), + }, + }, + } +} diff --git a/cmd/karmem/kmcheck/karmem.go b/cmd/karmem/kmcheck/karmem.go new file mode 100644 index 0000000..61dfb99 --- /dev/null +++ b/cmd/karmem/kmcheck/karmem.go @@ -0,0 +1,33 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewKarmem()) } + +type Karmem struct { + RestrictedWords *RestrictedWords +} + +func NewKarmem() *Karmem { + return &Karmem{ + RestrictedWords: &RestrictedWords{ + Rules: []WordRule{ + NewMatchRule("KarmemPointer"), + NewMatchRule("KarmemSize"), + }, + }, + } +} + +func (v *Karmem) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) + +} + +func (v *Karmem) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} diff --git a/cmd/karmem/kmcheck/kmcheck.go b/cmd/karmem/kmcheck/kmcheck.go new file mode 100644 index 0000000..d8370b4 --- /dev/null +++ b/cmd/karmem/kmcheck/kmcheck.go @@ -0,0 +1,48 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +// Validators is a list of all Validator available and registered by RegisterValidator +var Validators []Validator + +// RegisterValidator register the given Validator. +// You should use it on `init` function. +func RegisterValidator(v Validator) { + Validators = append(Validators, v) +} + +type Validator interface { + CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) + CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) +} + +// Check checks potential naming conflicts and collisions, +// that function will return a list of warnings and also +// set into kmparser.Content. +func Check(parsed *kmparser.Content) []kmparser.Warning { + var ( + warnings []kmparser.Warning + mutex sync.Mutex + group sync.WaitGroup + ) + + for _, v := range Validators { + group.Add(1) + go func(v Validator) { + defer group.Done() + for i := range parsed.Structs { + v.CheckStruct(&mutex, parsed, &parsed.Structs[i].Data) + } + for i := range parsed.Enums { + v.CheckEnum(&mutex, parsed, &parsed.Enums[i].Data) + } + }(v) + } + + group.Wait() + return warnings +} diff --git a/cmd/karmem/kmcheck/odin.go b/cmd/karmem/kmcheck/odin.go new file mode 100644 index 0000000..06e4bf6 --- /dev/null +++ b/cmd/karmem/kmcheck/odin.go @@ -0,0 +1,32 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewOdin()) } + +type Odin struct { + RestrictedWords *RestrictedWords +} + +func (v *Odin) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) +} + +func (v *Odin) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewOdin() *Odin { + return &Odin{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageOdin, + Rules: []WordRule{ + // TODO: Add rules for Odin. + }, + }, + } +} diff --git a/cmd/karmem/kmcheck/swift.go b/cmd/karmem/kmcheck/swift.go new file mode 100644 index 0000000..2d63759 --- /dev/null +++ b/cmd/karmem/kmcheck/swift.go @@ -0,0 +1,124 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewSwift()) } + +type Swift struct { + RestrictedWords *RestrictedWords +} + +func (v *Swift) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) +} + +func (v *Swift) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewSwift() *Swift { + return &Swift{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageSwift, + Rules: []WordRule{ + NewMatchRule("associatedtype"), + NewMatchRule("class"), + NewMatchRule("deinit"), + NewMatchRule("enum"), + NewMatchRule("extension"), + NewMatchRule("fileprivate"), + NewMatchRule("func"), + NewMatchRule("import"), + NewMatchRule("init"), + NewMatchRule("inout"), + NewMatchRule("internal"), + NewMatchRule("let"), + NewMatchRule("open"), + NewMatchRule("operator"), + NewMatchRule("private"), + NewMatchRule("precedencegroup"), + NewMatchRule("protocol"), + NewMatchRule("public"), + NewMatchRule("rethrows"), + NewMatchRule("static"), + NewMatchRule("struct"), + NewMatchRule("subscript"), + NewMatchRule("typealias"), + NewMatchRule("var"), + NewMatchRule("break"), + NewMatchRule("case"), + NewMatchRule("catch"), + NewMatchRule("continue"), + NewMatchRule("default"), + NewMatchRule("defer"), + NewMatchRule("do"), + NewMatchRule("else"), + NewMatchRule("fallthrough"), + NewMatchRule("for"), + NewMatchRule("guard"), + NewMatchRule("if"), + NewMatchRule("in"), + NewMatchRule("repeat"), + NewMatchRule("return"), + NewMatchRule("throw"), + NewMatchRule("switch"), + NewMatchRule("where"), + NewMatchRule("while"), + NewMatchRule("Any"), + NewMatchRule("as"), + NewMatchRule("catch"), + NewMatchRule("false"), + NewMatchRule("is"), + NewMatchRule("nil"), + NewMatchRule("rethrows"), + NewMatchRule("self"), + NewMatchRule("Self"), + NewMatchRule("super"), + NewMatchRule("throw"), + NewMatchRule("throws"), + NewMatchRule("true"), + NewMatchRule("try"), + NewMatchRule("_"), + NewMatchRule("associativity"), + NewMatchRule("convenience"), + NewMatchRule("didSet"), + NewMatchRule("dynamic"), + NewMatchRule("final"), + NewMatchRule("get"), + NewMatchRule("indirect"), + NewMatchRule("infix"), + NewMatchRule("lazy"), + NewMatchRule("left"), + NewMatchRule("mutating"), + NewMatchRule("none"), + NewMatchRule("nonmutating"), + NewMatchRule("optional"), + NewMatchRule("override"), + NewMatchRule("postfix"), + NewMatchRule("precedence"), + NewMatchRule("prefix"), + NewMatchRule("Protocol"), + NewMatchRule("required"), + NewMatchRule("right"), + NewMatchRule("set"), + NewMatchRule("some"), + NewMatchRule("Type"), + NewMatchRule("unowned"), + NewMatchRule("weak"), + NewMatchRule("willSet"), + NewMatchRegexRule("^Int[0-9]+$"), + NewMatchRegexRule("^Uint[0-9]+$"), + NewMatchRegexRule("^Float[0-9]+$"), + NewMatchRule("Float"), + NewMatchRule("Double"), + NewMatchRule("Bool"), + NewMatchRule("Void"), + NewMatchRule("String"), + }, + }, + } +} diff --git a/cmd/karmem/kmcheck/zig.go b/cmd/karmem/kmcheck/zig.go new file mode 100644 index 0000000..3514c74 --- /dev/null +++ b/cmd/karmem/kmcheck/zig.go @@ -0,0 +1,114 @@ +package kmcheck + +import ( + "sync" + + "karmem.org/cmd/karmem/kmparser" +) + +func init() { RegisterValidator(NewZig()) } + +type Zig struct { + RestrictedWords *RestrictedWords +} + +func (v *Zig) CheckStruct(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.StructData) { + v.RestrictedWords.CheckStruct(mutex, parsed, target) +} + +func (v *Zig) CheckEnum(mutex *sync.Mutex, parsed *kmparser.Content, target *kmparser.EnumData) { + v.RestrictedWords.CheckEnum(mutex, parsed, target) +} + +func NewZig() *Zig { + return &Zig{ + RestrictedWords: &RestrictedWords{ + Language: kmparser.LanguageZig, + Rules: []WordRule{ + NewMatchRule("align"), + NewMatchRule("allowzero"), + NewMatchRule("and"), + NewMatchRule("anyframe"), + NewMatchRule("anytype"), + NewMatchRule("asm"), + NewMatchRule("async"), + NewMatchRule("await"), + NewMatchRule("break"), + NewMatchRule("catch"), + NewMatchRule("comptime"), + NewMatchRule("const"), + NewMatchRule("continue"), + NewMatchRule("defer"), + NewMatchRule("else"), + NewMatchRule("enum"), + NewMatchRule("errdefer"), + NewMatchRule("error"), + NewMatchRule("export"), + NewMatchRule("extern"), + NewMatchRule("false"), + NewMatchRule("fn"), + NewMatchRule("for"), + NewMatchRule("if"), + NewMatchRule("inline"), + NewMatchRule("noalias"), + NewMatchRule("nosuspend"), + NewMatchRule("null"), + NewMatchRule("or"), + NewMatchRule("orelse"), + NewMatchRule("packed"), + NewMatchRule("pub"), + NewMatchRule("resume"), + NewMatchRule("return"), + NewMatchRule("linksection"), + NewMatchRule("struct"), + NewMatchRule("suspend"), + NewMatchRule("switch"), + NewMatchRule("test"), + NewMatchRule("threadlocal"), + NewMatchRule("true"), + NewMatchRule("try"), + NewMatchRule("undefined"), + NewMatchRule("union"), + NewMatchRule("unreachable"), + NewMatchRule("usingnamespace"), + NewMatchRule("var"), + NewMatchRule("volatile"), + NewMatchRule("while"), + NewMatchRule("i8"), + NewMatchRule("u8"), + NewMatchRule("i16"), + NewMatchRule("u16"), + NewMatchRule("i32"), + NewMatchRule("u32"), + NewMatchRule("i64"), + NewMatchRule("u64"), + NewMatchRule("i128"), + NewMatchRule("u128"), + NewMatchRule("isize"), + NewMatchRule("usize"), + NewMatchRule("c_short"), + NewMatchRule("c_ushort"), + NewMatchRule("c_int"), + NewMatchRule("c_uint"), + NewMatchRule("c_long"), + NewMatchRule("c_ulong"), + NewMatchRule("c_longlong"), + NewMatchRule("c_ulonglong"), + NewMatchRule("c_longdouble"), + NewMatchRule("f16"), + NewMatchRule("f32"), + NewMatchRule("f64"), + NewMatchRule("f128"), + NewMatchRule("bool"), + NewMatchRule("anyopaque"), + NewMatchRule("void"), + NewMatchRule("noreturn"), + NewMatchRule("type"), + NewMatchRule("anyerror"), + NewMatchRule("comptime_int"), + NewMatchRule("comptime_float"), + NewMatchRegexRule("^[i|u][0-9]+$"), + }, + }, + } +} diff --git a/cmd/karmem/kmparser/kmgen.km b/cmd/karmem/kmparser/kmgen.km index aaf321b..c0459af 100644 --- a/cmd/karmem/kmparser/kmgen.km +++ b/cmd/karmem/kmparser/kmgen.km @@ -22,6 +22,42 @@ enum TypeFormat uint8 { Table; } +enum RuleType uint16 { + None; + ReservedName; + ReservedType; + DuplicateName; + DuplicateType; + CollisionName; + CollisionType; +} + +enum Language uint64 { + None = 0; + AssemblyScript = 1; + Zig = 2; + C = 4; + Swift = 8; + Dotnet = 16; + Odin = 32; + Golang = 64; + Rust = 128; + Nim = 256; + Kotlin = 512; + D = 1024; + Haskell = 2048; + Crystal = 4096; + Typescript = 8192; + PHP = 16384; + Python = 32768; +} + + +struct SchemaPosition table @id(`8944966152016866568`) { + File []char; + Line uint32; + Column uint32; +} struct Type table @id(`2206764383142231373`) { Schema []char; @@ -31,6 +67,17 @@ struct Type table @id(`2206764383142231373`) { Model TypeModel; } +struct WarningData table @id(`9648278712160971894`) { + Message []char; + Rule []char; + Type RuleType; + Languages Language; +} + +struct Warning inline @id(`5319256325625522744`) { + Data WarningData; +} + struct PaddingType inline @id(`6449815373135188035`) { Data Type; } @@ -55,9 +102,11 @@ struct StructFieldSize table @id(`3117293985139574571`) { } struct EnumFieldData table @id(`6917629752752470509`) { - Name []char; - Value []char; - Tags []Tag; + Name []char; + Value []char; + Tags []Tag; + Position SchemaPosition; + Warnings []Warning; } struct EnumField inline @id(`18350873289003309128`) { @@ -70,6 +119,8 @@ struct EnumData table @id(`18057555498029063613`) { Fields []EnumField; Tags []Tag; IsSequential bool; + Position SchemaPosition; + Warnings []Warning; } struct Enumeration inline @id(`1253319329451847685`) { @@ -77,11 +128,13 @@ struct Enumeration inline @id(`1253319329451847685`) { } struct StructFieldData table @id(`17962757807284521522`) { - Name []char; - Type Type; - Offset uint32; - Tags []Tag; - Size StructFieldSize; + Name []char; + Type Type; + Offset uint32; + Tags []Tag; + Size StructFieldSize; + Position SchemaPosition; + Warnings []Warning; } struct StructField inline @id(`12155838558451759529`) { @@ -89,13 +142,15 @@ struct StructField inline @id(`12155838558451759529`) { } struct StructData table @id(`8290009745541165076`) { - ID uint64; - Name []char; - Size StructSize; - Fields []StructField; - Class StructClass; - Tags []Tag; - Packed bool; + ID uint64; + Name []char; + Size StructSize; + Fields []StructField; + Class StructClass; + Tags []Tag; + Packed bool; + Position SchemaPosition; + Warnings []Warning; } struct Structure inline @id(`18088017590773436939`) { diff --git a/cmd/karmem/kmparser/kmparser_extension.go b/cmd/karmem/kmparser/kmparser_extension.go index 603cd75..5ed9b93 100644 --- a/cmd/karmem/kmparser/kmparser_extension.go +++ b/cmd/karmem/kmparser/kmparser_extension.go @@ -83,6 +83,6 @@ func (x *Type) IsEnum() bool { return x.Format == TypeFormatEnum } -func (x StructData) IsTable() bool { +func (x *StructData) IsTable() bool { return x.Class == StructClassTable } diff --git a/cmd/karmem/kmparser/kmparser_generated.go b/cmd/karmem/kmparser/kmparser_generated.go index be5329e..793b267 100644 --- a/cmd/karmem/kmparser/kmparser_generated.go +++ b/cmd/karmem/kmparser/kmparser_generated.go @@ -8,7 +8,7 @@ import ( var _ unsafe.Pointer -var _Null = [42]byte{} +var _Null = [54]byte{} var _NullReader = karmem.NewReader(_Null[:]) type ( @@ -45,12 +45,53 @@ const ( TypeFormatTable TypeFormat = 4 ) +type ( + RuleType uint16 +) + +const ( + RuleTypeNone RuleType = 0 + RuleTypeReservedName RuleType = 1 + RuleTypeReservedType RuleType = 2 + RuleTypeDuplicateName RuleType = 3 + RuleTypeDuplicateType RuleType = 4 + RuleTypeCollisionName RuleType = 5 + RuleTypeCollisionType RuleType = 6 +) + +type ( + Language uint64 +) + +const ( + LanguageNone Language = 0 + LanguageAssemblyScript Language = 1 + LanguageZig Language = 2 + LanguageC Language = 4 + LanguageSwift Language = 8 + LanguageDotnet Language = 16 + LanguageOdin Language = 32 + LanguageGolang Language = 64 + LanguageRust Language = 128 + LanguageNim Language = 256 + LanguageKotlin Language = 512 + LanguageD Language = 1024 + LanguageHaskell Language = 2048 + LanguageCrystal Language = 4096 + LanguageTypescript Language = 8192 + LanguagePHP Language = 16384 + LanguagePython Language = 32768 +) + type ( PacketIdentifier uint64 ) const ( + PacketIdentifierSchemaPosition = 8944966152016866568 PacketIdentifierType = 2206764383142231373 + PacketIdentifierWarningData = 9648278712160971894 + PacketIdentifierWarning = 5319256325625522744 PacketIdentifierPaddingType = 6449815373135188035 PacketIdentifierTag = 9280816983786621498 PacketIdentifierStructSize = 2296279785726396957 @@ -64,9 +105,74 @@ const ( PacketIdentifierStructData = 8290009745541165076 PacketIdentifierStructure = 18088017590773436939 PacketIdentifierContentSize = 8764462619562198222 + PacketIdentifierContentOptions = 12347233001904861813 PacketIdentifierContent = 6792576797909524956 ) +type SchemaPosition struct { + File string + Line uint32 + Column uint32 +} + +func NewSchemaPosition() SchemaPosition { + return SchemaPosition{} +} + +func (x *SchemaPosition) PacketIdentifier() PacketIdentifier { + return PacketIdentifierSchemaPosition +} + +func (x *SchemaPosition) Reset() { + x.Read((*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])), _NullReader) +} + +func (x *SchemaPosition) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { + return x.Write(writer, 0) +} + +func (x *SchemaPosition) Write(writer *karmem.Writer, start uint) (offset uint, err error) { + offset = start + size := uint(20) + if offset == 0 { + offset, err = writer.Alloc(size) + if err != nil { + return 0, err + } + } + writer.Write4At(offset, uint32(20)) + __FileSize := uint(1 * len(x.File)) + __FileOffset, err := writer.Alloc(__FileSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+4, uint32(__FileOffset)) + writer.Write4At(offset+4+4, uint32(__FileSize)) + __FileSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.File)), __FileSize, __FileSize} + writer.WriteAt(__FileOffset, *(*[]byte)(unsafe.Pointer(&__FileSlice))) + __LineOffset := offset + 12 + writer.Write4At(__LineOffset, *(*uint32)(unsafe.Pointer(&x.Line))) + __ColumnOffset := offset + 16 + writer.Write4At(__ColumnOffset, *(*uint32)(unsafe.Pointer(&x.Column))) + + return offset, nil +} + +func (x *SchemaPosition) ReadAsRoot(reader *karmem.Reader) { + x.Read(NewSchemaPositionViewer(reader, 0), reader) +} + +func (x *SchemaPosition) Read(viewer *SchemaPositionViewer, reader *karmem.Reader) { + __FileString := viewer.File(reader) + if x.File != __FileString { + __FileStringCopy := make([]byte, len(__FileString)) + copy(__FileStringCopy, __FileString) + x.File = *(*string)(unsafe.Pointer(&__FileStringCopy)) + } + x.Line = viewer.Line() + x.Column = viewer.Column() +} + type Type struct { Schema string PlainSchema string @@ -151,6 +257,136 @@ func (x *Type) Read(viewer *TypeViewer, reader *karmem.Reader) { x.Model = TypeModel(viewer.Model()) } +type WarningData struct { + Message string + Rule string + Type RuleType + Languages Language +} + +func NewWarningData() WarningData { + return WarningData{} +} + +func (x *WarningData) PacketIdentifier() PacketIdentifier { + return PacketIdentifierWarningData +} + +func (x *WarningData) Reset() { + x.Read((*WarningDataViewer)(unsafe.Pointer(&_Null[0])), _NullReader) +} + +func (x *WarningData) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { + return x.Write(writer, 0) +} + +func (x *WarningData) Write(writer *karmem.Writer, start uint) (offset uint, err error) { + offset = start + size := uint(30) + if offset == 0 { + offset, err = writer.Alloc(size) + if err != nil { + return 0, err + } + } + writer.Write4At(offset, uint32(30)) + __MessageSize := uint(1 * len(x.Message)) + __MessageOffset, err := writer.Alloc(__MessageSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+4, uint32(__MessageOffset)) + writer.Write4At(offset+4+4, uint32(__MessageSize)) + __MessageSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Message)), __MessageSize, __MessageSize} + writer.WriteAt(__MessageOffset, *(*[]byte)(unsafe.Pointer(&__MessageSlice))) + __RuleSize := uint(1 * len(x.Rule)) + __RuleOffset, err := writer.Alloc(__RuleSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+12, uint32(__RuleOffset)) + writer.Write4At(offset+12+4, uint32(__RuleSize)) + __RuleSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Rule)), __RuleSize, __RuleSize} + writer.WriteAt(__RuleOffset, *(*[]byte)(unsafe.Pointer(&__RuleSlice))) + __TypeOffset := offset + 20 + writer.Write2At(__TypeOffset, *(*uint16)(unsafe.Pointer(&x.Type))) + __LanguagesOffset := offset + 22 + writer.Write8At(__LanguagesOffset, *(*uint64)(unsafe.Pointer(&x.Languages))) + + return offset, nil +} + +func (x *WarningData) ReadAsRoot(reader *karmem.Reader) { + x.Read(NewWarningDataViewer(reader, 0), reader) +} + +func (x *WarningData) Read(viewer *WarningDataViewer, reader *karmem.Reader) { + __MessageString := viewer.Message(reader) + if x.Message != __MessageString { + __MessageStringCopy := make([]byte, len(__MessageString)) + copy(__MessageStringCopy, __MessageString) + x.Message = *(*string)(unsafe.Pointer(&__MessageStringCopy)) + } + __RuleString := viewer.Rule(reader) + if x.Rule != __RuleString { + __RuleStringCopy := make([]byte, len(__RuleString)) + copy(__RuleStringCopy, __RuleString) + x.Rule = *(*string)(unsafe.Pointer(&__RuleStringCopy)) + } + x.Type = RuleType(viewer.Type()) + x.Languages = Language(viewer.Languages()) +} + +type Warning struct { + Data WarningData +} + +func NewWarning() Warning { + return Warning{} +} + +func (x *Warning) PacketIdentifier() PacketIdentifier { + return PacketIdentifierWarning +} + +func (x *Warning) Reset() { + x.Read((*WarningViewer)(unsafe.Pointer(&_Null[0])), _NullReader) +} + +func (x *Warning) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { + return x.Write(writer, 0) +} + +func (x *Warning) Write(writer *karmem.Writer, start uint) (offset uint, err error) { + offset = start + size := uint(4) + if offset == 0 { + offset, err = writer.Alloc(size) + if err != nil { + return 0, err + } + } + __DataSize := uint(30) + __DataOffset, err := writer.Alloc(__DataSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+0, uint32(__DataOffset)) + if _, err := x.Data.Write(writer, __DataOffset); err != nil { + return offset, err + } + + return offset, nil +} + +func (x *Warning) ReadAsRoot(reader *karmem.Reader) { + x.Read(NewWarningViewer(reader, 0), reader) +} + +func (x *Warning) Read(viewer *WarningViewer, reader *karmem.Reader) { + x.Data.Read(viewer.Data(reader), reader) +} + type PaddingType struct { Data Type } @@ -407,9 +643,11 @@ func (x *StructFieldSize) Read(viewer *StructFieldSizeViewer, reader *karmem.Rea } type EnumFieldData struct { - Name string - Value string - Tags []Tag + Name string + Value string + Tags []Tag + Position SchemaPosition + Warnings []Warning } func NewEnumFieldData() EnumFieldData { @@ -430,14 +668,14 @@ func (x *EnumFieldData) WriteAsRoot(writer *karmem.Writer) (offset uint, err err func (x *EnumFieldData) Write(writer *karmem.Writer, start uint) (offset uint, err error) { offset = start - size := uint(28) + size := uint(40) if offset == 0 { offset, err = writer.Alloc(size) if err != nil { return 0, err } } - writer.Write4At(offset, uint32(28)) + writer.Write4At(offset, uint32(40)) __NameSize := uint(1 * len(x.Name)) __NameOffset, err := writer.Alloc(__NameSize) if err != nil { @@ -469,6 +707,28 @@ func (x *EnumFieldData) Write(writer *karmem.Writer, start uint) (offset uint, e } __TagsOffset += 16 } + __PositionSize := uint(20) + __PositionOffset, err := writer.Alloc(__PositionSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+28, uint32(__PositionOffset)) + if _, err := x.Position.Write(writer, __PositionOffset); err != nil { + return offset, err + } + __WarningsSize := uint(4 * len(x.Warnings)) + __WarningsOffset, err := writer.Alloc(__WarningsSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+32, uint32(__WarningsOffset)) + writer.Write4At(offset+32+4, uint32(__WarningsSize)) + for i := range x.Warnings { + if _, err := x.Warnings[i].Write(writer, __WarningsOffset); err != nil { + return offset, err + } + __WarningsOffset += 4 + } return offset, nil } @@ -502,6 +762,19 @@ func (x *EnumFieldData) Read(viewer *EnumFieldDataViewer, reader *karmem.Reader) x.Tags[i].Read(&__TagsSlice[i], reader) } x.Tags = x.Tags[:__TagsLen] + x.Position.Read(viewer.Position(reader), reader) + __WarningsSlice := viewer.Warnings(reader) + __WarningsLen := len(__WarningsSlice) + if __WarningsLen > cap(x.Warnings) { + x.Warnings = append(x.Warnings, make([]Warning, __WarningsLen-len(x.Warnings))...) + } + if __WarningsLen > len(x.Warnings) { + x.Warnings = x.Warnings[:__WarningsLen] + } + for i := 0; i < __WarningsLen; i++ { + x.Warnings[i].Read(&__WarningsSlice[i], reader) + } + x.Warnings = x.Warnings[:__WarningsLen] } type EnumField struct { @@ -533,7 +806,7 @@ func (x *EnumField) Write(writer *karmem.Writer, start uint) (offset uint, err e return 0, err } } - __DataSize := uint(28) + __DataSize := uint(40) __DataOffset, err := writer.Alloc(__DataSize) if err != nil { return 0, err @@ -560,6 +833,8 @@ type EnumData struct { Fields []EnumField Tags []Tag IsSequential bool + Position SchemaPosition + Warnings []Warning } func NewEnumData() EnumData { @@ -580,14 +855,14 @@ func (x *EnumData) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { func (x *EnumData) Write(writer *karmem.Writer, start uint) (offset uint, err error) { offset = start - size := uint(33) + size := uint(45) if offset == 0 { offset, err = writer.Alloc(size) if err != nil { return 0, err } } - writer.Write4At(offset, uint32(33)) + writer.Write4At(offset, uint32(45)) __NameSize := uint(1 * len(x.Name)) __NameOffset, err := writer.Alloc(__NameSize) if err != nil { @@ -634,6 +909,28 @@ func (x *EnumData) Write(writer *karmem.Writer, start uint) (offset uint, err er } __IsSequentialOffset := offset + 32 writer.Write1At(__IsSequentialOffset, *(*uint8)(unsafe.Pointer(&x.IsSequential))) + __PositionSize := uint(20) + __PositionOffset, err := writer.Alloc(__PositionSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+33, uint32(__PositionOffset)) + if _, err := x.Position.Write(writer, __PositionOffset); err != nil { + return offset, err + } + __WarningsSize := uint(4 * len(x.Warnings)) + __WarningsOffset, err := writer.Alloc(__WarningsSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+37, uint32(__WarningsOffset)) + writer.Write4At(offset+37+4, uint32(__WarningsSize)) + for i := range x.Warnings { + if _, err := x.Warnings[i].Write(writer, __WarningsOffset); err != nil { + return offset, err + } + __WarningsOffset += 4 + } return offset, nil } @@ -675,6 +972,19 @@ func (x *EnumData) Read(viewer *EnumDataViewer, reader *karmem.Reader) { } x.Tags = x.Tags[:__TagsLen] x.IsSequential = viewer.IsSequential() + x.Position.Read(viewer.Position(reader), reader) + __WarningsSlice := viewer.Warnings(reader) + __WarningsLen := len(__WarningsSlice) + if __WarningsLen > cap(x.Warnings) { + x.Warnings = append(x.Warnings, make([]Warning, __WarningsLen-len(x.Warnings))...) + } + if __WarningsLen > len(x.Warnings) { + x.Warnings = x.Warnings[:__WarningsLen] + } + for i := 0; i < __WarningsLen; i++ { + x.Warnings[i].Read(&__WarningsSlice[i], reader) + } + x.Warnings = x.Warnings[:__WarningsLen] } type Enumeration struct { @@ -706,7 +1016,7 @@ func (x *Enumeration) Write(writer *karmem.Writer, start uint) (offset uint, err return 0, err } } - __DataSize := uint(33) + __DataSize := uint(45) __DataOffset, err := writer.Alloc(__DataSize) if err != nil { return 0, err @@ -728,11 +1038,13 @@ func (x *Enumeration) Read(viewer *EnumerationViewer, reader *karmem.Reader) { } type StructFieldData struct { - Name string - Type Type - Offset uint32 - Tags []Tag - Size StructFieldSize + Name string + Type Type + Offset uint32 + Tags []Tag + Size StructFieldSize + Position SchemaPosition + Warnings []Warning } func NewStructFieldData() StructFieldData { @@ -753,14 +1065,14 @@ func (x *StructFieldData) WriteAsRoot(writer *karmem.Writer) (offset uint, err e func (x *StructFieldData) Write(writer *karmem.Writer, start uint) (offset uint, err error) { offset = start - size := uint(32) + size := uint(44) if offset == 0 { offset, err = writer.Alloc(size) if err != nil { return 0, err } } - writer.Write4At(offset, uint32(32)) + writer.Write4At(offset, uint32(44)) __NameSize := uint(1 * len(x.Name)) __NameOffset, err := writer.Alloc(__NameSize) if err != nil { @@ -803,6 +1115,28 @@ func (x *StructFieldData) Write(writer *karmem.Writer, start uint) (offset uint, if _, err := x.Size.Write(writer, __SizeOffset); err != nil { return offset, err } + __PositionSize := uint(20) + __PositionOffset, err := writer.Alloc(__PositionSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+32, uint32(__PositionOffset)) + if _, err := x.Position.Write(writer, __PositionOffset); err != nil { + return offset, err + } + __WarningsSize := uint(4 * len(x.Warnings)) + __WarningsOffset, err := writer.Alloc(__WarningsSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+36, uint32(__WarningsOffset)) + writer.Write4At(offset+36+4, uint32(__WarningsSize)) + for i := range x.Warnings { + if _, err := x.Warnings[i].Write(writer, __WarningsOffset); err != nil { + return offset, err + } + __WarningsOffset += 4 + } return offset, nil } @@ -833,6 +1167,19 @@ func (x *StructFieldData) Read(viewer *StructFieldDataViewer, reader *karmem.Rea } x.Tags = x.Tags[:__TagsLen] x.Size.Read(viewer.Size(reader), reader) + x.Position.Read(viewer.Position(reader), reader) + __WarningsSlice := viewer.Warnings(reader) + __WarningsLen := len(__WarningsSlice) + if __WarningsLen > cap(x.Warnings) { + x.Warnings = append(x.Warnings, make([]Warning, __WarningsLen-len(x.Warnings))...) + } + if __WarningsLen > len(x.Warnings) { + x.Warnings = x.Warnings[:__WarningsLen] + } + for i := 0; i < __WarningsLen; i++ { + x.Warnings[i].Read(&__WarningsSlice[i], reader) + } + x.Warnings = x.Warnings[:__WarningsLen] } type StructField struct { @@ -864,7 +1211,7 @@ func (x *StructField) Write(writer *karmem.Writer, start uint) (offset uint, err return 0, err } } - __DataSize := uint(32) + __DataSize := uint(44) __DataOffset, err := writer.Alloc(__DataSize) if err != nil { return 0, err @@ -886,13 +1233,15 @@ func (x *StructField) Read(viewer *StructFieldViewer, reader *karmem.Reader) { } type StructData struct { - ID uint64 - Name string - Size StructSize - Fields []StructField - Class StructClass - Tags []Tag - Packed bool + ID uint64 + Name string + Size StructSize + Fields []StructField + Class StructClass + Tags []Tag + Packed bool + Position SchemaPosition + Warnings []Warning } func NewStructData() StructData { @@ -913,14 +1262,14 @@ func (x *StructData) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) func (x *StructData) Write(writer *karmem.Writer, start uint) (offset uint, err error) { offset = start - size := uint(42) + size := uint(54) if offset == 0 { offset, err = writer.Alloc(size) if err != nil { return 0, err } } - writer.Write4At(offset, uint32(42)) + writer.Write4At(offset, uint32(54)) __IDOffset := offset + 4 writer.Write8At(__IDOffset, *(*uint64)(unsafe.Pointer(&x.ID))) __NameSize := uint(1 * len(x.Name)) @@ -971,6 +1320,28 @@ func (x *StructData) Write(writer *karmem.Writer, start uint) (offset uint, err } __PackedOffset := offset + 41 writer.Write1At(__PackedOffset, *(*uint8)(unsafe.Pointer(&x.Packed))) + __PositionSize := uint(20) + __PositionOffset, err := writer.Alloc(__PositionSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+42, uint32(__PositionOffset)) + if _, err := x.Position.Write(writer, __PositionOffset); err != nil { + return offset, err + } + __WarningsSize := uint(4 * len(x.Warnings)) + __WarningsOffset, err := writer.Alloc(__WarningsSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+46, uint32(__WarningsOffset)) + writer.Write4At(offset+46+4, uint32(__WarningsSize)) + for i := range x.Warnings { + if _, err := x.Warnings[i].Write(writer, __WarningsOffset); err != nil { + return offset, err + } + __WarningsOffset += 4 + } return offset, nil } @@ -1014,6 +1385,19 @@ func (x *StructData) Read(viewer *StructDataViewer, reader *karmem.Reader) { } x.Tags = x.Tags[:__TagsLen] x.Packed = viewer.Packed() + x.Position.Read(viewer.Position(reader), reader) + __WarningsSlice := viewer.Warnings(reader) + __WarningsLen := len(__WarningsSlice) + if __WarningsLen > cap(x.Warnings) { + x.Warnings = append(x.Warnings, make([]Warning, __WarningsLen-len(x.Warnings))...) + } + if __WarningsLen > len(x.Warnings) { + x.Warnings = x.Warnings[:__WarningsLen] + } + for i := 0; i < __WarningsLen; i++ { + x.Warnings[i].Read(&__WarningsSlice[i], reader) + } + x.Warnings = x.Warnings[:__WarningsLen] } type Structure struct { @@ -1045,7 +1429,7 @@ func (x *Structure) Write(writer *karmem.Writer, start uint) (offset uint, err e return 0, err } } - __DataSize := uint(42) + __DataSize := uint(54) __DataOffset, err := writer.Alloc(__DataSize) if err != nil { return 0, err @@ -1110,6 +1494,94 @@ func (x *ContentSize) Read(viewer *ContentSizeViewer, reader *karmem.Reader) { x.Largest = viewer.Largest() } +type ContentOptions struct { + Module string + Import string + Prefix string +} + +func NewContentOptions() ContentOptions { + return ContentOptions{} +} + +func (x *ContentOptions) PacketIdentifier() PacketIdentifier { + return PacketIdentifierContentOptions +} + +func (x *ContentOptions) Reset() { + x.Read((*ContentOptionsViewer)(unsafe.Pointer(&_Null[0])), _NullReader) +} + +func (x *ContentOptions) WriteAsRoot(writer *karmem.Writer) (offset uint, err error) { + return x.Write(writer, 0) +} + +func (x *ContentOptions) Write(writer *karmem.Writer, start uint) (offset uint, err error) { + offset = start + size := uint(28) + if offset == 0 { + offset, err = writer.Alloc(size) + if err != nil { + return 0, err + } + } + writer.Write4At(offset, uint32(28)) + __ModuleSize := uint(1 * len(x.Module)) + __ModuleOffset, err := writer.Alloc(__ModuleSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+4, uint32(__ModuleOffset)) + writer.Write4At(offset+4+4, uint32(__ModuleSize)) + __ModuleSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Module)), __ModuleSize, __ModuleSize} + writer.WriteAt(__ModuleOffset, *(*[]byte)(unsafe.Pointer(&__ModuleSlice))) + __ImportSize := uint(1 * len(x.Import)) + __ImportOffset, err := writer.Alloc(__ImportSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+12, uint32(__ImportOffset)) + writer.Write4At(offset+12+4, uint32(__ImportSize)) + __ImportSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Import)), __ImportSize, __ImportSize} + writer.WriteAt(__ImportOffset, *(*[]byte)(unsafe.Pointer(&__ImportSlice))) + __PrefixSize := uint(1 * len(x.Prefix)) + __PrefixOffset, err := writer.Alloc(__PrefixSize) + if err != nil { + return 0, err + } + writer.Write4At(offset+20, uint32(__PrefixOffset)) + writer.Write4At(offset+20+4, uint32(__PrefixSize)) + __PrefixSlice := [3]uint{*(*uint)(unsafe.Pointer(&x.Prefix)), __PrefixSize, __PrefixSize} + writer.WriteAt(__PrefixOffset, *(*[]byte)(unsafe.Pointer(&__PrefixSlice))) + + return offset, nil +} + +func (x *ContentOptions) ReadAsRoot(reader *karmem.Reader) { + x.Read(NewContentOptionsViewer(reader, 0), reader) +} + +func (x *ContentOptions) Read(viewer *ContentOptionsViewer, reader *karmem.Reader) { + __ModuleString := viewer.Module(reader) + if x.Module != __ModuleString { + __ModuleStringCopy := make([]byte, len(__ModuleString)) + copy(__ModuleStringCopy, __ModuleString) + x.Module = *(*string)(unsafe.Pointer(&__ModuleStringCopy)) + } + __ImportString := viewer.Import(reader) + if x.Import != __ImportString { + __ImportStringCopy := make([]byte, len(__ImportString)) + copy(__ImportStringCopy, __ImportString) + x.Import = *(*string)(unsafe.Pointer(&__ImportStringCopy)) + } + __PrefixString := viewer.Prefix(reader) + if x.Prefix != __PrefixString { + __PrefixStringCopy := make([]byte, len(__PrefixString)) + copy(__PrefixStringCopy, __PrefixString) + x.Prefix = *(*string)(unsafe.Pointer(&__PrefixStringCopy)) + } +} + type Content struct { Tags []Tag Structs []Structure @@ -1259,6 +1731,50 @@ func (x *Content) Read(viewer *ContentViewer, reader *karmem.Reader) { x.Packed = viewer.Packed() } +type SchemaPositionViewer [20]byte + +func NewSchemaPositionViewer(reader *karmem.Reader, offset uint32) (v *SchemaPositionViewer) { + if !reader.IsValidOffset(offset, 4) { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + v = (*SchemaPositionViewer)(unsafe.Add(reader.Pointer, offset)) + if !reader.IsValidOffset(offset, v.size()) { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + return v +} + +func (x *SchemaPositionViewer) size() uint32 { + return *(*uint32)(unsafe.Pointer(x)) +} +func (x *SchemaPositionViewer) File(reader *karmem.Reader) (v string) { + if 4+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *SchemaPositionViewer) Line() (v uint32) { + if 12+4 > x.size() { + return v + } + return *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12)) +} +func (x *SchemaPositionViewer) Column() (v uint32) { + if 16+4 > x.size() { + return v + } + return *(*uint32)(unsafe.Add(unsafe.Pointer(x), 16)) +} + type TypeViewer [26]byte func NewTypeViewer(reader *karmem.Reader, offset uint32) (v *TypeViewer) { @@ -1324,6 +1840,83 @@ func (x *TypeViewer) Model() (v TypeModel) { return *(*TypeModel)(unsafe.Add(unsafe.Pointer(x), 25)) } +type WarningDataViewer [30]byte + +func NewWarningDataViewer(reader *karmem.Reader, offset uint32) (v *WarningDataViewer) { + if !reader.IsValidOffset(offset, 4) { + return (*WarningDataViewer)(unsafe.Pointer(&_Null[0])) + } + v = (*WarningDataViewer)(unsafe.Add(reader.Pointer, offset)) + if !reader.IsValidOffset(offset, v.size()) { + return (*WarningDataViewer)(unsafe.Pointer(&_Null[0])) + } + return v +} + +func (x *WarningDataViewer) size() uint32 { + return *(*uint32)(unsafe.Pointer(x)) +} +func (x *WarningDataViewer) Message(reader *karmem.Reader) (v string) { + if 4+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *WarningDataViewer) Rule(reader *karmem.Reader) (v string) { + if 12+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *WarningDataViewer) Type() (v RuleType) { + if 20+2 > x.size() { + return v + } + return *(*RuleType)(unsafe.Add(unsafe.Pointer(x), 20)) +} +func (x *WarningDataViewer) Languages() (v Language) { + if 22+8 > x.size() { + return v + } + return *(*Language)(unsafe.Add(unsafe.Pointer(x), 22)) +} + +type WarningViewer [4]byte + +func NewWarningViewer(reader *karmem.Reader, offset uint32) (v *WarningViewer) { + if !reader.IsValidOffset(offset, 4) { + return (*WarningViewer)(unsafe.Pointer(&_Null[0])) + } + v = (*WarningViewer)(unsafe.Add(reader.Pointer, offset)) + return v +} + +func (x *WarningViewer) size() uint32 { + return 4 +} +func (x *WarningViewer) Data(reader *karmem.Reader) (v *WarningDataViewer) { + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 0)) + return NewWarningDataViewer(reader, offset) +} + type PaddingTypeViewer [4]byte func NewPaddingTypeViewer(reader *karmem.Reader, offset uint32) (v *PaddingTypeViewer) { @@ -1471,7 +2064,7 @@ func (x *StructFieldSizeViewer) Field() (v uint32) { return *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12)) } -type EnumFieldDataViewer [28]byte +type EnumFieldDataViewer [40]byte func NewEnumFieldDataViewer(reader *karmem.Reader, offset uint32) (v *EnumFieldDataViewer) { if !reader.IsValidOffset(offset, 4) { @@ -1532,6 +2125,28 @@ func (x *EnumFieldDataViewer) Tags(reader *karmem.Reader) (v []TagViewer) { } return *(*[]TagViewer)(unsafe.Pointer(&slice)) } +func (x *EnumFieldDataViewer) Position(reader *karmem.Reader) (v *SchemaPositionViewer) { + if 28+4 > x.size() { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 28)) + return NewSchemaPositionViewer(reader, offset) +} +func (x *EnumFieldDataViewer) Warnings(reader *karmem.Reader) (v []WarningViewer) { + if 32+8 > x.size() { + return []WarningViewer{} + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 32)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 32+4)) + if !reader.IsValidOffset(offset, size) { + return []WarningViewer{} + } + length := uintptr(size / 4) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*[]WarningViewer)(unsafe.Pointer(&slice)) +} type EnumFieldViewer [4]byte @@ -1551,7 +2166,7 @@ func (x *EnumFieldViewer) Data(reader *karmem.Reader) (v *EnumFieldDataViewer) { return NewEnumFieldDataViewer(reader, offset) } -type EnumDataViewer [33]byte +type EnumDataViewer [45]byte func NewEnumDataViewer(reader *karmem.Reader, offset uint32) (v *EnumDataViewer) { if !reader.IsValidOffset(offset, 4) { @@ -1625,6 +2240,28 @@ func (x *EnumDataViewer) IsSequential() (v bool) { } return *(*bool)(unsafe.Add(unsafe.Pointer(x), 32)) } +func (x *EnumDataViewer) Position(reader *karmem.Reader) (v *SchemaPositionViewer) { + if 33+4 > x.size() { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 33)) + return NewSchemaPositionViewer(reader, offset) +} +func (x *EnumDataViewer) Warnings(reader *karmem.Reader) (v []WarningViewer) { + if 37+8 > x.size() { + return []WarningViewer{} + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 37)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 37+4)) + if !reader.IsValidOffset(offset, size) { + return []WarningViewer{} + } + length := uintptr(size / 4) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*[]WarningViewer)(unsafe.Pointer(&slice)) +} type EnumerationViewer [4]byte @@ -1644,7 +2281,7 @@ func (x *EnumerationViewer) Data(reader *karmem.Reader) (v *EnumDataViewer) { return NewEnumDataViewer(reader, offset) } -type StructFieldDataViewer [32]byte +type StructFieldDataViewer [44]byte func NewStructFieldDataViewer(reader *karmem.Reader, offset uint32) (v *StructFieldDataViewer) { if !reader.IsValidOffset(offset, 4) { @@ -1710,6 +2347,28 @@ func (x *StructFieldDataViewer) Size(reader *karmem.Reader) (v *StructFieldSizeV offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 28)) return NewStructFieldSizeViewer(reader, offset) } +func (x *StructFieldDataViewer) Position(reader *karmem.Reader) (v *SchemaPositionViewer) { + if 32+4 > x.size() { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 32)) + return NewSchemaPositionViewer(reader, offset) +} +func (x *StructFieldDataViewer) Warnings(reader *karmem.Reader) (v []WarningViewer) { + if 36+8 > x.size() { + return []WarningViewer{} + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 36)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 36+4)) + if !reader.IsValidOffset(offset, size) { + return []WarningViewer{} + } + length := uintptr(size / 4) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*[]WarningViewer)(unsafe.Pointer(&slice)) +} type StructFieldViewer [4]byte @@ -1729,7 +2388,7 @@ func (x *StructFieldViewer) Data(reader *karmem.Reader) (v *StructFieldDataViewe return NewStructFieldDataViewer(reader, offset) } -type StructDataViewer [42]byte +type StructDataViewer [54]byte func NewStructDataViewer(reader *karmem.Reader, offset uint32) (v *StructDataViewer) { if !reader.IsValidOffset(offset, 4) { @@ -1815,6 +2474,28 @@ func (x *StructDataViewer) Packed() (v bool) { } return *(*bool)(unsafe.Add(unsafe.Pointer(x), 41)) } +func (x *StructDataViewer) Position(reader *karmem.Reader) (v *SchemaPositionViewer) { + if 42+4 > x.size() { + return (*SchemaPositionViewer)(unsafe.Pointer(&_Null[0])) + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 42)) + return NewSchemaPositionViewer(reader, offset) +} +func (x *StructDataViewer) Warnings(reader *karmem.Reader) (v []WarningViewer) { + if 46+8 > x.size() { + return []WarningViewer{} + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 46)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 46+4)) + if !reader.IsValidOffset(offset, size) { + return []WarningViewer{} + } + length := uintptr(size / 4) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*[]WarningViewer)(unsafe.Pointer(&slice)) +} type StructureViewer [4]byte @@ -1857,6 +2538,68 @@ func (x *ContentSizeViewer) Largest() (v uint32) { return *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4)) } +type ContentOptionsViewer [28]byte + +func NewContentOptionsViewer(reader *karmem.Reader, offset uint32) (v *ContentOptionsViewer) { + if !reader.IsValidOffset(offset, 4) { + return (*ContentOptionsViewer)(unsafe.Pointer(&_Null[0])) + } + v = (*ContentOptionsViewer)(unsafe.Add(reader.Pointer, offset)) + if !reader.IsValidOffset(offset, v.size()) { + return (*ContentOptionsViewer)(unsafe.Pointer(&_Null[0])) + } + return v +} + +func (x *ContentOptionsViewer) size() uint32 { + return *(*uint32)(unsafe.Pointer(x)) +} +func (x *ContentOptionsViewer) Module(reader *karmem.Reader) (v string) { + if 4+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 4+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *ContentOptionsViewer) Import(reader *karmem.Reader) (v string) { + if 12+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 12+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} +func (x *ContentOptionsViewer) Prefix(reader *karmem.Reader) (v string) { + if 20+8 > x.size() { + return v + } + offset := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 20)) + size := *(*uint32)(unsafe.Add(unsafe.Pointer(x), 20+4)) + if !reader.IsValidOffset(offset, size) { + return "" + } + length := uintptr(size / 1) + slice := [3]uintptr{ + uintptr(unsafe.Add(reader.Pointer, offset)), length, length, + } + return *(*string)(unsafe.Pointer(&slice)) +} + type ContentViewer [41]byte func NewContentViewer(reader *karmem.Reader, offset uint32) (v *ContentViewer) { diff --git a/cmd/karmem/kmparser/parser.go b/cmd/karmem/kmparser/parser.go index a812b75..cddefc4 100644 --- a/cmd/karmem/kmparser/parser.go +++ b/cmd/karmem/kmparser/parser.go @@ -15,11 +15,13 @@ import ( ) //go:generate go run ../main.go build -golang kmgen.km -//go:generate go run ../main.go fmt -s kmgen.km +//go:generate go run ../main.go fmt -w kmgen.km // Reader reads and decodes Karmem files. type Reader struct { - Parsed Content + Parsed Content + WarningsDisabled bool + hasher func(s string) uint64 hasherHash hash.Hash hasherKey []byte @@ -225,6 +227,10 @@ func unicodeSpaceTab(r rune) bool { func (r *Reader) enumName() parserFunc { b := r.nextRune() t := &r.Parsed.Enums[len(r.Parsed.Enums)-1].Data + t.Position.File = r.path + t.Position.Line = uint32(r.line) + t.Position.Column = uint32(r.column) + switch { case unicodeSpaceTab(b) && len(t.Name) > 0: return r.skipSpace(r.enumType) @@ -277,6 +283,10 @@ func (r *Reader) enumFieldName() parserFunc { b := r.nextRune() t := &r.Parsed.Enums[len(r.Parsed.Enums)-1].Data f := &t.Fields[len(t.Fields)-1].Data + f.Position.File = r.path + f.Position.Line = uint32(r.line) + f.Position.Column = uint32(r.column) + switch { case b == ';': r.prevRune() @@ -452,6 +462,9 @@ func (r *Reader) structInit() parserFunc { func (r *Reader) structName() parserFunc { b := r.nextRune() t := &r.Parsed.Structs[len(r.Parsed.Structs)-1].Data + t.Position.File = r.path + t.Position.Line = uint32(r.line) + t.Position.Column = uint32(r.column) switch { case unicodeSpaceTab(b) && len(t.Name) > 0: @@ -547,6 +560,9 @@ func (r *Reader) structFieldName() parserFunc { b := r.nextRune() t := &r.Parsed.Structs[len(r.Parsed.Structs)-1].Data f := &t.Fields[len(t.Fields)-1].Data + f.Position.File = r.path + f.Position.Line = uint32(r.line) + f.Position.Column = uint32(r.column) switch { case unicode.IsSpace(b) && len(f.Name) == 0: diff --git a/cmd/karmem/main.go b/cmd/karmem/main.go index 60720ed..920daf1 100644 --- a/cmd/karmem/main.go +++ b/cmd/karmem/main.go @@ -5,9 +5,11 @@ import ( "errors" "flag" "fmt" + "io" "os" "path/filepath" + "karmem.org/cmd/karmem/kmcheck" "karmem.org/cmd/karmem/kmgen" "karmem.org/cmd/karmem/kmparser" ) @@ -22,8 +24,11 @@ func main() { fmt.Println("Usage: karmem []") fmt.Println("Commands:") fmt.Println(" build") - fmt.Println(" Builds the schema file.") + fmt.Println(" Generates the language-specific implementation based on the schema file.") fmt.Println(" Use \"build help\" to see the list of available options.") + fmt.Println(" fmt") + fmt.Println(" Format the schema file.") + fmt.Println(" Use \"fmt help\" to see the list of available options.") os.Exit(1) } flag.Parse() @@ -94,6 +99,7 @@ type Build struct { SchemaFile language []bool output string + warns io.Writer generator []kmgen.Generator } @@ -103,9 +109,14 @@ func NewBuild() (b *Build, _ error) { b.language = make([]bool, len(kmgen.Generators)) for i, g := range kmgen.Generators { - flags.BoolVar(&b.language[i], g.Language(), false, fmt.Sprintf("Enable geneartion for %s language.", g.Language())) + flags.BoolVar(&b.language[i], g.Language(), false, fmt.Sprintf("Enable generation for %s language.", g.Language())) } flags.StringVar(&b.output, "o", ".", "Output directory path.") + var disableWarnings bool + flags.BoolVar(&disableWarnings, "s", false, "Silence warnings.") + if !disableWarnings { + b.warns = os.Stdout + } if err := flags.Parse(flag.Args()[1:]); err != nil { return nil, err } @@ -136,6 +147,11 @@ func (b *Build) Execute() error { return err } + if b.warns != nil { + kmcheck.Check(parsed) + ReportWarnings(b.warns, parsed) + } + for _, gen := range b.generator { compiler, err := gen.Start(parsed) if err != nil { @@ -185,7 +201,12 @@ func NewFormat() (f *Format, _ error) { flags := flag.NewFlagSet("build", flag.ExitOnError) f.language = make([]bool, len(kmgen.Generators)) - flags.BoolVar(&f.save, "s", false, "Save and override the original schema file.") + flags.BoolVar(&f.save, "w", false, "Write and override the original schema file.") + var disableWarnings bool + flags.BoolVar(&disableWarnings, "s", false, "Silence warnings.") + if !disableWarnings { + f.warns = os.Stdout + } if err := flags.Parse(flag.Args()[1:]); err != nil { return nil, err } @@ -206,6 +227,11 @@ func (b *Format) Execute() error { return err } + if b.warns != nil { + kmcheck.Check(parsed) + ReportWarnings(b.warns, parsed) + } + gen := kmgen.KarmemSchemaGenerator() compiler, err := gen.Start(parsed) if err != nil { @@ -239,3 +265,30 @@ func (b *Format) Execute() error { } return nil } + +func ReportWarnings(out io.Writer, parsed *kmparser.Content) { + for _, x := range parsed.Structs { + for _, w := range x.Data.Warnings { + reportWarning(out, &x.Data.Position, &w.Data) + } + for _, x := range x.Data.Fields { + for _, w := range x.Data.Warnings { + reportWarning(out, &x.Data.Position, &w.Data) + } + } + } + for _, x := range parsed.Enums { + for _, w := range x.Data.Warnings { + reportWarning(out, &x.Data.Position, &w.Data) + } + for _, x := range x.Data.Fields { + for _, w := range x.Data.Warnings { + reportWarning(out, &x.Data.Position, &w.Data) + } + } + } +} + +func reportWarning(out io.Writer, position *kmparser.SchemaPosition, w *kmparser.WarningData) { + fmt.Fprintf(out, "Warning: %s:%d:%d %s\n", position.File, position.Line, position.Column, w.Message) +}