Skip to content

Commit

Permalink
CORE, LSP: Actually allow namespaces inside of types instead of just …
Browse files Browse the repository at this point in the history
…expressions
  • Loading branch information
MineGame159 committed Jan 14, 2024
1 parent 9677406 commit 9fd9f20
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 71 deletions.
58 changes: 53 additions & 5 deletions cmd/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ func getCompletions(project *workspace.Project, file *ast.File, pos core.Pos) *p
if leaf != nil {
if isInFunctionBody(pos, leaf) {
switch parent := leaf.Parent().(type) {
case *ast.Resolvable:
getResolvableCompletions(resolver, &c, pos, parent)

case *ast.Member:
if isAfterNode(pos, parent.Value) {
getMemberCompletions(resolver, &c, parent)
Expand All @@ -53,6 +56,16 @@ func getCompletions(project *workspace.Project, file *ast.File, pos core.Pos) *p

if isInFunctionBody(pos, node) {
switch node := node.(type) {
case *ast.Resolvable:
getResolvableCompletions(resolver, &c, pos, node)

case *ast.Var:
if isAfterNode(pos, node.Name) && isBeforeCst(pos, node, scanner.Equal) {
getGlobalCompletions(resolver, &c, true)
} else if isAfterCst(pos, node, scanner.Equal, false) {
getIdentifierCompletions(resolver, &c, pos, node)
}

case *ast.Member:
if isAfterNode(pos, node.Value) {
getMemberCompletions(resolver, &c, node)
Expand Down Expand Up @@ -82,6 +95,23 @@ func getCompletions(project *workspace.Project, file *ast.File, pos core.Pos) *p
return c.get()
}

func getResolvableCompletions(resolver ast.Resolver, c *completions, pos core.Pos, resolvable *ast.Resolvable) {
if resolvable.Cst() == nil || !resolvable.Cst().Contains(scanner.Dot) {
getGlobalCompletions(resolver, c, true)
return
}

for _, part := range resolvable.Parts {
if part.Cst() != nil && pos.IsAfter(part.Cst().Range.End) && resolver != nil {
resolver = resolver.GetChild(part.String())
}
}

if resolver != nil {
getResolverCompletions(c, resolver, true)
}
}

func getTypeCompletions(root ast.RootResolver, resolver ast.Resolver, c *completions, pos core.Pos, node ast.Node) {
switch node := node.(type) {
case *ast.NamespaceName:
Expand Down Expand Up @@ -130,6 +160,9 @@ func getTypeCompletions(root ast.RootResolver, resolver ast.Resolver, c *complet
getGlobalCompletions(resolver, c, true)
}

case *ast.Resolvable:
getResolvableCompletions(resolver, c, pos, node)

case ast.Type:
if !isComplexType(node) {
getGlobalCompletions(resolver, c, true)
Expand Down Expand Up @@ -277,12 +310,14 @@ func getGlobalCompletions(resolver ast.Resolver, c *completions, symbolsOnlyType
c.add(protocol.CompletionItemKindStruct, "f32", "")
c.add(protocol.CompletionItemKindStruct, "f64", "")

// Builtin identifiers
c.add(protocol.CompletionItemKindKeyword, "true", "bool")
c.add(protocol.CompletionItemKindKeyword, "false", "bool")
if !symbolsOnlyTypes {
// Builtin identifiers
c.add(protocol.CompletionItemKindKeyword, "true", "bool")
c.add(protocol.CompletionItemKindKeyword, "false", "bool")

c.add(protocol.CompletionItemKindFunction, "sizeof", "(<type>) u32")
c.add(protocol.CompletionItemKindFunction, "alignof", "(<type>) u32")
c.add(protocol.CompletionItemKindFunction, "sizeof", "(<type>) u32")
c.add(protocol.CompletionItemKindFunction, "alignof", "(<type>) u32")
}

// Language defined types and functions
getResolverCompletions(c, resolver, symbolsOnlyTypes)
Expand Down Expand Up @@ -352,6 +387,19 @@ func isAfterCst(pos core.Pos, node ast.Node, kind scanner.TokenKind, sameLine bo
return pos.IsAfter(after)
}

func isBeforeCst(pos core.Pos, node ast.Node, kind scanner.TokenKind) bool {
if node.Cst() == nil {
return false
}

child := node.Cst().Get(kind)
if child == nil {
return true
}

return child.Range.Start.IsAfter(pos)
}

func isInFunctionBody(pos core.Pos, node ast.Node) bool {
function := ast.GetParent[*ast.Func](node)
if function == nil {
Expand Down
5 changes: 5 additions & 0 deletions cmd/lsp/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func getDefinition(node ast.Node, pos core.Pos) []protocol.Location {
func getDefinitionToken(token *ast.Token) []protocol.Location {
// Get definition based on the token's parent
switch parent := token.Parent().(type) {
case *ast.Resolvable:
if token == parent.Parts[len(parent.Parts)-1] {
return newDefinition(parent.Resolved())
}

case *ast.Member:
return getDefinitionExprResult(parent.Result())

Expand Down
8 changes: 6 additions & 2 deletions cmd/lsp/highlighter.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,15 @@ func (h *highlighter) visitType(type_ ast.Type) {
h.add(type_, typeKind)

case *ast.Resolvable:
for i := 0; i < len(type_.Parts)-1; i++ {
h.add(type_.Parts[i], namespaceKind)
}

switch type_.Resolved().(type) {
case *ast.Struct:
h.add(type_, classKind)
h.add(type_.Parts[len(type_.Parts)-1], classKind)
case *ast.Enum:
h.add(type_, enumKind)
h.add(type_.Parts[len(type_.Parts)-1], enumKind)
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion core/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,18 @@ func (g *get) contains(node Node) bool {
next := GetNextSibling(node)

if next == nil || (next.Cst() != nil && next.Cst().Range.Start.Line > g.pos.Line) {
return true
parent := node.Parent().Cst()
var after cst.Node

for _, child := range parent.Children {
if child.Range.Start.IsAfter(range_.End) && after.Kind == cst.UnknownNode {
after = child
}
}

if after.Kind == cst.UnknownNode || after.Range.Start.IsAfter(g.pos) {
return true
}
}
}
}
Expand Down
89 changes: 47 additions & 42 deletions core/ast/cst2ast/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,56 +23,61 @@ func (c *converter) convertType(node cst.Node) ast.Type {
}

func (c *converter) convertIdentifierType(node cst.Node) ast.Type {
for _, child := range node.Children {
if child.Kind == cst.IdentifierNode {
var kind ast.PrimitiveKind

switch child.Token.Lexeme {
case "void":
kind = ast.Void
case "bool":
kind = ast.Bool

case "u8":
kind = ast.U8
case "u16":
kind = ast.U16
case "u32":
kind = ast.U32
case "u64":
kind = ast.U64

case "i8":
kind = ast.I8
case "i16":
kind = ast.I16
case "i32":
kind = ast.I32
case "i64":
kind = ast.I64

case "f32":
kind = ast.F32
case "f64":
kind = ast.F64

default:
if r := ast.NewResolvable(node, child.Token); r != nil {
return r
}

return nil
}
if len(node.Children) == 1 {
kind := ast.Unknown

switch node.Children[0].Token.Lexeme {
case "void":
kind = ast.Void
case "bool":
kind = ast.Bool

case "u8":
kind = ast.U8
case "u16":
kind = ast.U16
case "u32":
kind = ast.U32
case "u64":
kind = ast.U64

case "i8":
kind = ast.I8
case "i16":
kind = ast.I16
case "i32":
kind = ast.I32
case "i64":
kind = ast.I64

case "f32":
kind = ast.F32
case "f64":
kind = ast.F64
}

if p := ast.NewPrimitive(node, kind, child.Token); p != nil {
if kind != ast.Unknown {
if p := ast.NewPrimitive(node, kind, node.Children[0].Token); p != nil {
return p
}

return nil
}
}

panic("cst2ast.convertIdentifierType() - Not implemented")
var parts []*ast.Token

for _, child := range node.Children {
if child.Kind == cst.IdentifierNode {
parts = append(parts, c.convertToken(child))
}
}

if r := ast.NewResolvable(node, parts); r != nil {
return r
}

return nil
}

func (c *converter) convertPointerType(node cst.Node) ast.Type {
Expand Down
29 changes: 20 additions & 9 deletions core/ast/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,18 +275,22 @@ type Resolvable struct {
cst cst.Node
parent Node

Name scanner.Token
Type Type
Parts []*Token
Type Type
}

func NewResolvable(node cst.Node, name scanner.Token) *Resolvable {
if name.IsEmpty() {
func NewResolvable(node cst.Node, parts []*Token) *Resolvable {
if parts == nil {
return nil
}

r := &Resolvable{
cst: node,
Name: name,
cst: node,
Parts: parts,
}

for _, child := range parts {
child.SetParent(r)
}

return r
Expand All @@ -301,7 +305,7 @@ func (r *Resolvable) Cst() *cst.Node {
}

func (r *Resolvable) Token() scanner.Token {
return r.Name
return scanner.Token{}
}

func (r *Resolvable) Parent() Node {
Expand All @@ -317,15 +321,22 @@ func (r *Resolvable) SetParent(parent Node) {
}

func (r *Resolvable) AcceptChildren(visitor Visitor) {
for _, child := range r.Parts {
visitor.VisitNode(child)
}
}

func (r *Resolvable) Clone() Node {
r2 := &Resolvable{
cst: r.cst,
Name: r.Name,
Type: r.Type,
}

r2.Parts = make([]*Token, len(r.Parts))
for i, child := range r2.Parts {
r2.Parts[i] = child.Clone().(*Token)
r2.Parts[i].SetParent(r2)
}
if r.Type != nil {
r2.Type = r.Type.Clone().(Type)
r2.Type.SetParent(r2)
Expand All @@ -335,7 +346,7 @@ func (r *Resolvable) Clone() Node {
}

func (r *Resolvable) String() string {
return r.Name.String()
return ""
}

func (r *Resolvable) AcceptType(visitor TypeVisitor) {
Expand Down
8 changes: 7 additions & 1 deletion core/ast/types_manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,13 @@ func (t *typePrinter) VisitArray(type_ *Array) {
}

func (t *typePrinter) VisitResolvable(type_ *Resolvable) {
t.str += type_.String()
for i, part := range type_.Parts {
if i > 0 {
t.str += "."
}

t.str += part.String()
}
}

func (t *typePrinter) VisitStruct(type_ *Struct) {
Expand Down
7 changes: 4 additions & 3 deletions core/cst/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@ func parsePrefixExprPratt(p *parser) Node {
case scanner.Identifier:
if p.next.Lexeme == "new" && p.peek2Is(canStartType) {
new_ := p.advanceGetLeaf()
type_ := parseType(p)

if p.peek2() == scanner.LeftBrace {
if p.peek() == scanner.LeftBrace {
p.begin(StructExprNode)

p.childAdd(new_)
if p.child(parseType) {
if p.childAdd(type_) {
return p.end()
}
if p.consume(scanner.LeftBrace) {
Expand All @@ -97,7 +98,7 @@ func parsePrefixExprPratt(p *parser) Node {
p.begin(AllocateArrayExprNode)

p.childAdd(new_)
if p.child(parseType) {
if p.childAdd(type_) {
return p.end()
}
if p.consume(scanner.LeftBracket) {
Expand Down
9 changes: 8 additions & 1 deletion core/cst/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ func parseType(p *parser) Node {
func parseIdentifierType(p *parser) Node {
p.begin(IdentifierTypeNode)

p.consume(scanner.Identifier)
if p.consume(scanner.Identifier) {
return p.end()
}
for p.optional(scanner.Dot) {
if p.consume(scanner.Identifier) {
return p.end()
}
}

return p.end()
}
Expand Down
Loading

0 comments on commit 9fd9f20

Please sign in to comment.