initial commit

This commit is contained in:
astravexton 2021-10-22 15:24:12 +01:00
commit 6358d0754b
34 changed files with 82616 additions and 0 deletions

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
}

174
tlparser/parser.go Normal file
View file

@ -0,0 +1,174 @@
package tlparser
import (
"bufio"
"io"
"strings"
)
func Parse(reader io.Reader) (*Schema, error) {
schema := &Schema{
Types: []*Type{},
Classes: []*Class{},
Functions: []*Function{},
}
scanner := bufio.NewScanner(reader)
hitFunctions := false
for scanner.Scan() {
line := scanner.Text()
switch {
case strings.HasPrefix(line, "//@description"):
if hitFunctions {
schema.Functions = append(schema.Functions, parseFunction(line, scanner))
} else {
schema.Types = append(schema.Types, parseType(line, scanner))
}
case strings.HasPrefix(line, "//@class"):
schema.Classes = append(schema.Classes, parseClass(line, scanner))
case strings.Contains(line, "---functions---"):
hitFunctions = true
case line == "":
default:
bodyFields := strings.Fields(line)
name := bodyFields[0]
class := strings.TrimRight(bodyFields[len(bodyFields)-1], ";")
if hitFunctions {
schema.Functions = append(schema.Functions, &Function{
Name: name,
Description: "",
Class: class,
Properties: []*Property{},
IsSynchronous: false,
Type: FUNCTION_TYPE_UNKNOWN,
})
} else {
if name == "vector" {
name = "vector<t>"
class = "Vector<T>"
}
schema.Types = append(schema.Types, &Type{
Name: name,
Description: "",
Class: class,
Properties: []*Property{},
})
}
}
}
return schema, nil
}
func parseType(firstLine string, scanner *bufio.Scanner) *Type {
name, description, class, properties, _ := parseEntity(firstLine, scanner)
return &Type{
Name: name,
Description: description,
Class: class,
Properties: properties,
}
}
func parseFunction(firstLine string, scanner *bufio.Scanner) *Function {
name, description, class, properties, isSynchronous := parseEntity(firstLine, scanner)
return &Function{
Name: name,
Description: description,
Class: class,
Properties: properties,
IsSynchronous: isSynchronous,
Type: FUNCTION_TYPE_UNKNOWN,
}
}
func parseClass(firstLine string, scanner *bufio.Scanner) *Class {
class := &Class{
Name: "",
Description: "",
}
classLineParts := strings.Split(firstLine, "@")
_, class.Name = parseProperty(classLineParts[1])
_, class.Description = parseProperty(classLineParts[2])
return class
}
func parseEntity(firstLine string, scanner *bufio.Scanner) (string, string, string, []*Property, bool) {
name := ""
description := ""
class := ""
properties := []*Property{}
propertiesLine := strings.TrimLeft(firstLine, "//")
Loop:
for scanner.Scan() {
line := scanner.Text()
switch {
case strings.HasPrefix(line, "//@"):
propertiesLine += " " + strings.TrimLeft(line, "//")
case strings.HasPrefix(line, "//-"):
propertiesLine += " " + strings.TrimLeft(line, "//-")
default:
bodyFields := strings.Fields(line)
name = bodyFields[0]
for _, rawProperty := range bodyFields[1 : len(bodyFields)-2] {
propertyParts := strings.Split(rawProperty, ":")
property := &Property{
Name: propertyParts[0],
Type: propertyParts[1],
}
properties = append(properties, property)
}
class = strings.TrimRight(bodyFields[len(bodyFields)-1], ";")
break Loop
}
}
rawProperties := strings.Split(propertiesLine, "@")
for _, rawProperty := range rawProperties[1:] {
name, value := parseProperty(rawProperty)
switch {
case name == "description":
description = value
default:
name = strings.TrimPrefix(name, "param_")
property := getProperty(properties, name)
property.Description = value
}
}
return name, description, class, properties, strings.Contains(description, "Can be called synchronously")
}
func parseProperty(str string) (string, string) {
strParts := strings.Fields(str)
return strParts[0], strings.Join(strParts[1:], " ")
}
func getProperty(properties []*Property, name string) *Property {
for _, property := range properties {
if property.Name == name {
return property
}
}
return nil
}

43
tlparser/type.go Normal file
View file

@ -0,0 +1,43 @@
package tlparser
type Schema struct {
Types []*Type `json:"types"`
Classes []*Class `json:"classes"`
Functions []*Function `json:"functions"`
}
type Type struct {
Name string `json:"name"`
Description string `json:"description"`
Class string `json:"class"`
Properties []*Property `json:"properties"`
}
type Class struct {
Name string `json:"name"`
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 {
Name string `json:"name"`
Description string `json:"description"`
Class string `json:"class"`
Properties []*Property `json:"properties"`
IsSynchronous bool `json:"is_synchronous"`
Type FunctionType `json:"type"`
}
type Property struct {
Name string `json:"name"`
Type string `json:"type"`
Description string `json:"description"`
}