Move LSP semantics into typed analysis

This commit is contained in:
pavel 2026-08-27 21:28:11 +02:00
commit bac1183593
26 changed files with 1232 additions and 637 deletions

View file

@ -263,6 +263,7 @@ func (g *goGenerator) function(fn FunctionDecl) error {
}
g.write("func ")
g.write(fn.Name)
g.write(renderGoTypeParameters(fn.TypeParams))
g.write(g.renderGoFunctionParams(fn))
if ret := g.goReturnType(fn.ReturnType); ret != "" {
g.write(" ")
@ -346,7 +347,7 @@ func enumVariant(decl EnumDecl, name string) *EnumVariant {
}
func (g *goGenerator) classDecl(class ClassDecl) error {
g.line("type " + class.Name + " struct {")
g.line("type " + class.Name + renderGoTypeParameters(class.TypeParams) + " struct {")
g.indentLevel++
for _, field := range class.Fields {
name := field.Name
@ -366,6 +367,7 @@ func (g *goGenerator) classDecl(class ClassDecl) error {
g.line("")
g.write("func New")
g.write(class.Name)
g.write(renderGoTypeParameters(class.TypeParams))
g.write("(")
for i, field := range class.Fields {
if i > 0 {
@ -377,11 +379,13 @@ func (g *goGenerator) classDecl(class ClassDecl) error {
}
g.write(") *")
g.write(class.Name)
g.write(renderGoTypeArguments(class.TypeParams))
g.write(" {\n")
g.indentLevel++
g.writeIndent()
g.write("return &")
g.write(class.Name)
g.write(renderGoTypeArguments(class.TypeParams))
g.write("{")
for i, field := range class.Fields {
if i > 0 {
@ -427,6 +431,7 @@ func (g *goGenerator) method(class ClassDecl, fn FunctionDecl) error {
g.write("func (self *")
g.write(class.Name)
g.write(renderGoTypeArguments(class.TypeParams))
g.write(") ")
g.write(fn.Name)
g.write(g.renderGoFunctionParams(fn))
@ -792,8 +797,8 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
if e.Name == "this" {
return "self", nil
}
if g.classField(*g.currentClass, e.Name) && !g.isDefined(e.Name) {
return "self." + e.Name, nil
if field, found := classFieldByName(*g.currentClass, e.Name); found && !g.isDefined(e.Name) {
return "self." + mappingFieldName(*g.currentClass, field), nil
}
}
return e.Name, nil
@ -1189,7 +1194,7 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
}
if ident, ok := e.Callee.(IdentExpr); ok {
if _, ok := g.semantic.Classes[ident.Name]; ok && (resolvedCall == nil || resolvedCall.Meaning == ClassConstructionExpr) {
return fmt.Sprintf("New%s(%s)", ident.Name, strings.Join(args, ", ")), nil
return fmt.Sprintf("New%s%s(%s)", ident.Name, g.renderCallTypeArguments(e.TypeArgs), strings.Join(args, ", ")), nil
}
}
if ident, ok := e.Callee.(IdentExpr); ok {
@ -1217,6 +1222,9 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
if err != nil {
return "", err
}
if len(e.TypeArgs) > 0 {
callee += g.renderCallTypeArguments(e.TypeArgs)
}
call := fmt.Sprintf("%s(%s)", callee, strings.Join(args, ", "))
if result, ok := g.goErrorResult(e, call, expectedType); ok {
return result, nil
@ -2460,18 +2468,11 @@ func (g *goGenerator) isDefined(name string) bool {
return false
}
func (g *goGenerator) classField(class ClassDecl, name string) bool {
for _, field := range class.Fields {
if field.Name == name {
return true
}
}
return false
}
func (g *goGenerator) assignTarget(name string) string {
if g.currentClass != nil && g.classField(*g.currentClass, name) && !g.isDefined(name) {
return "self." + name
if g.currentClass != nil && !g.isDefined(name) {
if field, found := classFieldByName(*g.currentClass, name); found {
return "self." + mappingFieldName(*g.currentClass, field)
}
}
return name
}
@ -2496,6 +2497,35 @@ func (g *goGenerator) renderGoFunctionParams(function FunctionDecl) string {
return g.renderGoParamsWithPrefix(function.Params, prefix)
}
func renderGoTypeParameters(params []string) string {
if len(params) == 0 {
return ""
}
values := make([]string, len(params))
for index, param := range params {
values[index] = param + " any"
}
return "[" + strings.Join(values, ", ") + "]"
}
func renderGoTypeArguments(params []string) string {
if len(params) == 0 {
return ""
}
return "[" + strings.Join(params, ", ") + "]"
}
func (g *goGenerator) renderCallTypeArguments(args []string) string {
if len(args) == 0 {
return ""
}
values := make([]string, len(args))
for index, argument := range args {
values[index] = g.goType(argument)
}
return "[" + strings.Join(values, ", ") + "]"
}
func (g *goGenerator) renderGoParamsWithPrefix(params []Param, prefix string) string {
var b strings.Builder
b.WriteString("(")