Move LSP semantics into typed analysis
This commit is contained in:
parent
f4cd4f4458
commit
bac1183593
26 changed files with 1232 additions and 637 deletions
|
|
@ -10,6 +10,19 @@ type Type interface {
|
|||
String() string
|
||||
}
|
||||
|
||||
type TypeRef struct {
|
||||
Source string
|
||||
Syntax Type
|
||||
}
|
||||
|
||||
func ParseTypeRef(source string) (TypeRef, error) {
|
||||
typ, err := ParseType(source)
|
||||
if err != nil {
|
||||
return TypeRef{}, err
|
||||
}
|
||||
return TypeRef{Source: source, Syntax: typ}, nil
|
||||
}
|
||||
|
||||
type UnknownType struct{}
|
||||
|
||||
func (UnknownType) typeNode() {}
|
||||
|
|
@ -20,6 +33,11 @@ type NamedType struct{ Name string }
|
|||
func (NamedType) typeNode() {}
|
||||
func (t NamedType) String() string { return t.Name }
|
||||
|
||||
type TypeParameterType struct{ Name string }
|
||||
|
||||
func (TypeParameterType) typeNode() {}
|
||||
func (t TypeParameterType) String() string { return t.Name }
|
||||
|
||||
type ClassType struct{ Class *ClassSymbol }
|
||||
|
||||
func (ClassType) typeNode() {}
|
||||
|
|
@ -36,8 +54,9 @@ func (GoPointerType) typeNode() {}
|
|||
func (t GoPointerType) String() string { return "*" + t.Element.String() }
|
||||
|
||||
type FunctionType struct {
|
||||
Params []Type
|
||||
Result Type
|
||||
TypeParams []string
|
||||
Params []Type
|
||||
Result Type
|
||||
}
|
||||
|
||||
func (FunctionType) typeNode() {}
|
||||
|
|
@ -54,6 +73,17 @@ type GenericType struct {
|
|||
Args []Type
|
||||
}
|
||||
|
||||
type TupleType struct{ Elements []Type }
|
||||
|
||||
func (TupleType) typeNode() {}
|
||||
func (t TupleType) String() string {
|
||||
elements := make([]string, len(t.Elements))
|
||||
for index, element := range t.Elements {
|
||||
elements[index] = element.String()
|
||||
}
|
||||
return "(" + strings.Join(elements, ", ") + ")"
|
||||
}
|
||||
|
||||
func (GenericType) typeNode() {}
|
||||
func (t GenericType) String() string {
|
||||
args := make([]string, 0, len(t.Args))
|
||||
|
|
@ -125,6 +155,8 @@ func resolveClassTypes(typ Type, classes map[string]*ClassSymbol) Type {
|
|||
return ClassType{Class: class}
|
||||
}
|
||||
return value
|
||||
case TypeParameterType:
|
||||
return value
|
||||
case NullableType:
|
||||
return NullableType{Element: resolveClassTypes(value.Element, classes)}
|
||||
case GoPointerType:
|
||||
|
|
@ -141,6 +173,46 @@ func resolveClassTypes(typ Type, classes map[string]*ClassSymbol) Type {
|
|||
args[i] = resolveClassTypes(arg, classes)
|
||||
}
|
||||
return GenericType{Base: resolveClassTypes(value.Base, classes), Args: args}
|
||||
case TupleType:
|
||||
elements := make([]Type, len(value.Elements))
|
||||
for index, element := range value.Elements {
|
||||
elements[index] = resolveClassTypes(element, classes)
|
||||
}
|
||||
return TupleType{Elements: elements}
|
||||
default:
|
||||
return typ
|
||||
}
|
||||
}
|
||||
|
||||
func resolveTypeParameters(typ Type, params map[string]bool) Type {
|
||||
switch value := typ.(type) {
|
||||
case NamedType:
|
||||
if params[value.Name] {
|
||||
return TypeParameterType{Name: value.Name}
|
||||
}
|
||||
return value
|
||||
case NullableType:
|
||||
return NullableType{Element: resolveTypeParameters(value.Element, params)}
|
||||
case GoPointerType:
|
||||
return GoPointerType{Element: resolveTypeParameters(value.Element, params)}
|
||||
case FunctionType:
|
||||
resolved := make([]Type, len(value.Params))
|
||||
for index, param := range value.Params {
|
||||
resolved[index] = resolveTypeParameters(param, params)
|
||||
}
|
||||
return FunctionType{TypeParams: value.TypeParams, Params: resolved, Result: resolveTypeParameters(value.Result, params)}
|
||||
case GenericType:
|
||||
args := make([]Type, len(value.Args))
|
||||
for index, arg := range value.Args {
|
||||
args[index] = resolveTypeParameters(arg, params)
|
||||
}
|
||||
return GenericType{Base: resolveTypeParameters(value.Base, params), Args: args}
|
||||
case TupleType:
|
||||
elements := make([]Type, len(value.Elements))
|
||||
for index, element := range value.Elements {
|
||||
elements[index] = resolveTypeParameters(element, params)
|
||||
}
|
||||
return TupleType{Elements: elements}
|
||||
default:
|
||||
return typ
|
||||
}
|
||||
|
|
@ -148,6 +220,63 @@ func resolveClassTypes(typ Type, classes map[string]*ClassSymbol) Type {
|
|||
|
||||
func typeEqual(left, right Type) bool { return left.String() == right.String() }
|
||||
|
||||
func substituteType(typ Type, bindings map[string]Type) Type {
|
||||
switch value := typ.(type) {
|
||||
case TypeParameterType:
|
||||
if bound, ok := bindings[value.Name]; ok {
|
||||
return bound
|
||||
}
|
||||
return value
|
||||
case NullableType:
|
||||
return NullableType{Element: substituteType(value.Element, bindings)}
|
||||
case GoPointerType:
|
||||
return GoPointerType{Element: substituteType(value.Element, bindings)}
|
||||
case GenericType:
|
||||
args := make([]Type, len(value.Args))
|
||||
for index, arg := range value.Args {
|
||||
args[index] = substituteType(arg, bindings)
|
||||
}
|
||||
return GenericType{Base: substituteType(value.Base, bindings), Args: args}
|
||||
case TupleType:
|
||||
elements := make([]Type, len(value.Elements))
|
||||
for index, element := range value.Elements {
|
||||
elements[index] = substituteType(element, bindings)
|
||||
}
|
||||
return TupleType{Elements: elements}
|
||||
case FunctionType:
|
||||
params := make([]Type, len(value.Params))
|
||||
for index, param := range value.Params {
|
||||
params[index] = substituteType(param, bindings)
|
||||
}
|
||||
return FunctionType{TypeParams: value.TypeParams, Params: params, Result: substituteType(value.Result, bindings)}
|
||||
default:
|
||||
return typ
|
||||
}
|
||||
}
|
||||
|
||||
func inferTypeBindings(parameter, argument Type, bindings map[string]Type) {
|
||||
switch expected := parameter.(type) {
|
||||
case TypeParameterType:
|
||||
if _, exists := bindings[expected.Name]; !exists && !isUnknownType(argument) {
|
||||
bindings[expected.Name] = argument
|
||||
}
|
||||
case NullableType:
|
||||
if actual, ok := argument.(NullableType); ok {
|
||||
inferTypeBindings(expected.Element, actual.Element, bindings)
|
||||
}
|
||||
case GenericType:
|
||||
actual, ok := argument.(GenericType)
|
||||
if !ok || expected.Base.String() != actual.Base.String() {
|
||||
return
|
||||
}
|
||||
for index := range expected.Args {
|
||||
if index < len(actual.Args) {
|
||||
inferTypeBindings(expected.Args[index], actual.Args[index], bindings)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func renderGoType(typ Type) string {
|
||||
switch value := typ.(type) {
|
||||
case UnknownType:
|
||||
|
|
@ -201,7 +330,12 @@ func renderGoType(typ Type) string {
|
|||
}
|
||||
return "*GotlinSQLIterator[" + argument + "]"
|
||||
}
|
||||
if class, ok := value.Base.(ClassType); ok {
|
||||
return "*" + class.Class.Name + "[" + strings.Join(args, ", ") + "]"
|
||||
}
|
||||
return base + "[" + strings.Join(args, ", ") + "]"
|
||||
case TypeParameterType:
|
||||
return value.Name
|
||||
case NamedType:
|
||||
switch value.Name {
|
||||
case "Int":
|
||||
|
|
@ -225,6 +359,12 @@ func renderGoType(typ Type) string {
|
|||
default:
|
||||
return value.Name
|
||||
}
|
||||
case TupleType:
|
||||
elements := make([]string, len(value.Elements))
|
||||
for index, element := range value.Elements {
|
||||
elements[index] = renderGoType(element)
|
||||
}
|
||||
return "(" + strings.Join(elements, ", ") + ")"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue