schema improvement

This commit is contained in:
Aleksandr Zelenin 2018-10-19 21:06:07 +03:00
parent ccea55b18f
commit c780ca35c4
7 changed files with 732 additions and 326 deletions

View file

@ -5,12 +5,12 @@ schema-update:
generate-json: generate-json:
go run ./cmd/generate-json.go \ go run ./cmd/generate-json.go \
-input "./data/td_api.tl" \ -version "${TAG}" \
-output "./data/td_api.json" -output "./data/td_api.json"
generate-code: generate-code:
go run ./cmd/generate-code.go \ go run ./cmd/generate-code.go \
-schema "./data/td_api.tl" \ -version "${TAG}" \
-outputDir "./client" \ -outputDir "./client" \
-package client \ -package client \
-functionFile function.go \ -functionFile function.go \

View file

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"flag" "flag"
"log" "log"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -12,7 +13,7 @@ import (
) )
type config struct { type config struct {
schemaFilePath string version string
outputDirPath string outputDirPath string
packageName string packageName string
functionFileName string functionFileName string
@ -23,7 +24,7 @@ type config struct {
func main() { func main() {
var config config var config config
flag.StringVar(&config.schemaFilePath, "schema", "./td_api.tl", ".tl schema file") flag.StringVar(&config.version, "version", "", "TDLib version")
flag.StringVar(&config.outputDirPath, "outputDir", "./tdlib", "output directory") flag.StringVar(&config.outputDirPath, "outputDir", "./tdlib", "output directory")
flag.StringVar(&config.packageName, "package", "tdlib", "package name") flag.StringVar(&config.packageName, "package", "tdlib", "package name")
flag.StringVar(&config.functionFileName, "functionFile", "function.go", "functions filename") flag.StringVar(&config.functionFileName, "functionFile", "function.go", "functions filename")
@ -32,15 +33,17 @@ func main() {
flag.Parse() flag.Parse()
schemaFile, err := os.OpenFile(config.schemaFilePath, os.O_RDONLY, os.ModePerm) resp, err := http.Get("https://raw.githubusercontent.com/tdlib/td/" + config.version + "/td/generate/scheme/td_api.tl")
if err != nil { if err != nil {
log.Fatalf("schemaFile open error: %s", err) log.Fatalf("http.Get error: %s", err)
return
} }
defer schemaFile.Close() defer resp.Body.Close()
schema, err := tlparser.Parse(schemaFile) schema, err := tlparser.Parse(resp.Body)
if err != nil { if err != nil {
log.Fatalf("schema parse error: %s", err) log.Fatalf("schema parse error: %s", err)
return
} }
err = os.MkdirAll(config.outputDirPath, 0755) err = os.MkdirAll(config.outputDirPath, 0755)

View file

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"flag" "flag"
"log" "log"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -12,33 +13,46 @@ import (
) )
func main() { func main() {
var inputFilePath string var version string
var outputFilePath string var outputFilePath string
flag.StringVar(&inputFilePath, "input", "./td_api.tl", "tl schema file") flag.StringVar(&version, "version", "", "TDLib version")
flag.StringVar(&outputFilePath, "output", "./td_api.json", "json schema file") flag.StringVar(&outputFilePath, "output", "./td_api.json", "json schema file")
flag.Parse() flag.Parse()
file, err := os.OpenFile(inputFilePath, os.O_RDONLY, os.ModePerm) resp, err := http.Get("https://raw.githubusercontent.com/tdlib/td/" + version + "/td/generate/scheme/td_api.tl")
if err != nil { if err != nil {
log.Fatalf("open file error: %s", err) log.Fatalf("http.Get error: %s", err)
return return
} }
defer file.Close() defer resp.Body.Close()
schema, err := tlparser.Parse(file) schema, err := tlparser.Parse(resp.Body)
if err != nil { if err != nil {
log.Fatalf("schema parse error: %s", err) log.Fatalf("schema parse error: %s", err)
return return
} }
resp, err = http.Get("https://raw.githubusercontent.com/tdlib/td/" + version + "/td/telegram/Td.cpp")
if err != nil {
log.Fatalf("http.Get error: %s", err)
return
}
defer resp.Body.Close()
err = tlparser.ParseCode(resp.Body, schema)
if err != nil {
log.Fatalf("parse code error: %s", err)
return
}
err = os.MkdirAll(filepath.Dir(outputFilePath), os.ModePerm) err = os.MkdirAll(filepath.Dir(outputFilePath), os.ModePerm)
if err != nil { if err != nil {
log.Fatalf("make dir error: %s", filepath.Dir(outputFilePath)) log.Fatalf("make dir error: %s", filepath.Dir(outputFilePath))
} }
file, err = os.OpenFile(outputFilePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.ModePerm) file, err := os.OpenFile(outputFilePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.ModePerm)
if err != nil { if err != nil {
log.Fatalf("open file error: %s", err) log.Fatalf("open file error: %s", err)
return return

File diff suppressed because it is too large Load diff

74
tlparser/code.go Normal file
View file

@ -0,0 +1,74 @@
package tlparser
import (
"bufio"
"fmt"
"io"
"strings"
)
func ParseCode(reader io.Reader, schema *Schema) error {
var prevLine string
var curLine string
userMethods := map[string]bool{}
botMethods := map[string]bool{}
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
prevLine = curLine
curLine = scanner.Text()
if strings.Contains(curLine, "CHECK_IS_USER();") {
fields := strings.Fields(prevLine)
for _, field := range fields {
var methodName string
n, err := fmt.Sscanf(field, "td_api::%s", &methodName)
if err == nil && n > 0 {
userMethods[methodName] = true
}
}
}
if strings.Contains(curLine, "CHECK_IS_BOT();") {
fields := strings.Fields(prevLine)
for _, field := range fields {
var methodName string
n, err := fmt.Sscanf(field, "td_api::%s", &methodName)
if err == nil && n > 0 {
botMethods[methodName] = true
}
}
}
}
err := scanner.Err()
if err != nil {
return err
}
var ok bool
for index, _ := range schema.Functions {
hasType := false
_, ok = userMethods[schema.Functions[index].Name]
if ok {
schema.Functions[index].Type = FUNCTION_TYPE_USER
hasType = true
}
_, ok = botMethods[schema.Functions[index].Name]
if ok {
schema.Functions[index].Type = FUNCTION_TYPE_BOT
hasType = true
}
if !hasType {
schema.Functions[index].Type = FUNCTION_TYPE_COMMON
}
ok = false
}
return nil
}

View file

@ -42,10 +42,12 @@ func Parse(reader io.Reader) (*Schema, error) {
class := strings.TrimRight(bodyFields[len(bodyFields)-1], ";") class := strings.TrimRight(bodyFields[len(bodyFields)-1], ";")
if hitFunctions { if hitFunctions {
schema.Functions = append(schema.Functions, &Function{ schema.Functions = append(schema.Functions, &Function{
Name: name, Name: name,
Description: "", Description: "",
Class: class, Class: class,
Properties: []*Property{}, Properties: []*Property{},
IsSynchronous: false,
Type: FUNCTION_TYPE_UNKNOWN,
}) })
} else { } else {
if name == "vector" { if name == "vector" {
@ -84,6 +86,7 @@ func parseFunction(firstLine string, scanner *bufio.Scanner) *Function {
Class: class, Class: class,
Properties: properties, Properties: properties,
IsSynchronous: isSynchronous, IsSynchronous: isSynchronous,
Type: FUNCTION_TYPE_UNKNOWN,
} }
} }

View file

@ -18,12 +18,22 @@ type Class struct {
Description string `json:"description"` Description string `json:"description"`
} }
type FunctionType int
const (
FUNCTION_TYPE_UNKNOWN FunctionType = iota
FUNCTION_TYPE_COMMON
FUNCTION_TYPE_USER
FUNCTION_TYPE_BOT
)
type Function struct { type Function struct {
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
Class string `json:"class"` Class string `json:"class"`
Properties []*Property `json:"properties"` Properties []*Property `json:"properties"`
IsSynchronous bool `json:"is_synchronous"` IsSynchronous bool `json:"is_synchronous"`
Type FunctionType `json:"type"`
} }
type Property struct { type Property struct {