move gotd fork into repo. (#111)
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type constructorMapping struct {
|
||||
// Name is go name of interface or struct.
|
||||
Name string
|
||||
// Constructor is go name of mapped constructor.
|
||||
// May be empty.
|
||||
Constructor string
|
||||
// Concrete is flag which is true when Name address a struct, not interface.
|
||||
Concrete bool
|
||||
// MapperName is name of mapper which created this sub.
|
||||
MapperName string
|
||||
// Fields is slice of field mappings from this struct to target.
|
||||
Fields []fieldPair
|
||||
}
|
||||
|
||||
// interfaceDef represents generic interface, type which has multiple constructors.
|
||||
type interfaceDef struct {
|
||||
// Name of interface.
|
||||
Name string
|
||||
// RawType is raw type from TL schema.
|
||||
RawType string
|
||||
|
||||
// Fields, common for every constructor.
|
||||
SharedFields map[string][]fieldDef
|
||||
// Sub interfaces of this TL class.
|
||||
// Need to create As${sub.MapperName}() ${sub.Name} mappers.
|
||||
Mappings []constructorMapping
|
||||
// Constructors of interface.
|
||||
Constructors []structDef
|
||||
Func string
|
||||
Namespace []string
|
||||
BaseName string
|
||||
URL string
|
||||
}
|
||||
|
||||
func interfaceHasOneSuffix(suffixes ...string) func(s structDef) bool {
|
||||
return func(s structDef) bool {
|
||||
for _, suffix := range suffixes {
|
||||
if strings.HasSuffix(s.Name, suffix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func makeMapping(def *interfaceDef, name string, emptyFilter func(s structDef) bool) {
|
||||
var (
|
||||
// Fields, common for every non-empty constructor.
|
||||
nonEmptyFields []fieldDef
|
||||
// Non-empty constructors.
|
||||
nonEmptyConstructors []structDef
|
||||
// Index of optional empty constructor.
|
||||
emptyIdx = -1
|
||||
)
|
||||
for _, s := range def.Constructors {
|
||||
if emptyFilter(s) {
|
||||
emptyIdx = len(def.Constructors)
|
||||
} else {
|
||||
nonEmptyFields = intersectFields(nonEmptyFields, s.Fields)
|
||||
nonEmptyConstructors = append(nonEmptyConstructors, s)
|
||||
}
|
||||
}
|
||||
|
||||
// If have at least one empty constructor.
|
||||
hasEmpty := emptyIdx >= 0
|
||||
|
||||
// If all non-empty constructors have common fields.
|
||||
nonEmptyHasCommonFields := len(nonEmptyFields) > 0
|
||||
|
||||
if hasEmpty && nonEmptyHasCommonFields && len(nonEmptyConstructors) > 0 {
|
||||
def.SharedFields[name] = nonEmptyFields
|
||||
|
||||
// If there are only one non-empty constructor, so we use concrete type.
|
||||
concrete := len(nonEmptyConstructors) < 2
|
||||
goName := name + strings.TrimSuffix(def.Name, "Class")
|
||||
if concrete {
|
||||
goName = nonEmptyConstructors[0].Name
|
||||
}
|
||||
|
||||
mapping := constructorMapping{
|
||||
Name: goName,
|
||||
Concrete: concrete,
|
||||
MapperName: name,
|
||||
}
|
||||
def.Mappings = append(def.Mappings, mapping)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) collectMappings(def *interfaceDef) {
|
||||
for _, s := range g.structs {
|
||||
// Filter constructors from same Class and empty constructors.
|
||||
if s.Interface == def.Name || len(s.Fields) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, constructor := range def.Constructors {
|
||||
// Filter constructors which have not similar name.
|
||||
if !strings.HasPrefix(s.Name, "Input") || !strings.Contains(s.Name, constructor.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
mapping, ok := mappableFields(constructor, s)
|
||||
// Filter constructors which we can't fill completely.
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
def.Mappings = append(def.Mappings, mapping)
|
||||
}
|
||||
}
|
||||
|
||||
emptyAnnotations := []struct {
|
||||
name string
|
||||
filter func(s structDef) bool
|
||||
}{
|
||||
{"NotEmpty", interfaceHasOneSuffix("Empty")},
|
||||
{"Modified", interfaceHasOneSuffix("NotModified")},
|
||||
{"Available", interfaceHasOneSuffix("Unavailable")},
|
||||
{"NotForbidden", interfaceHasOneSuffix("Forbidden")},
|
||||
{"Full", interfaceHasOneSuffix("Empty", "NotModified", "Forbidden")},
|
||||
}
|
||||
for _, annotation := range emptyAnnotations {
|
||||
// Full annotation is necessary only if there are more than two empty annotations.
|
||||
if annotation.name == "Full" && len(def.SharedFields) <= 2 {
|
||||
continue
|
||||
}
|
||||
makeMapping(def, annotation.name, annotation.filter)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) makeInterfaces() {
|
||||
// Make interfaces for classes.
|
||||
for _, c := range g.classes {
|
||||
if c.Singular {
|
||||
continue
|
||||
}
|
||||
def := interfaceDef{
|
||||
Name: c.Name,
|
||||
Namespace: c.Namespace,
|
||||
Func: c.Func,
|
||||
BaseName: c.BaseName,
|
||||
RawType: c.RawType,
|
||||
SharedFields: map[string][]fieldDef{},
|
||||
URL: g.docURL("type", c.RawType),
|
||||
}
|
||||
|
||||
for _, s := range g.structs {
|
||||
if s.Interface != def.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
def.SharedFields["Common"] = intersectFields(def.SharedFields["Common"], s.Fields)
|
||||
def.Constructors = append(def.Constructors, s)
|
||||
}
|
||||
g.collectMappings(&def)
|
||||
|
||||
g.interfaces = append(g.interfaces, def)
|
||||
g.mappings[def.Name] = append(g.mappings[def.Name], def.Mappings...)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user