Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Retain comments in AST #3509

Draft
wants to merge 39 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d8066a5
stop consuming trivia as tokens
bartolomej Jul 26, 2024
76f7107
compute leading and trailing trivia
bartolomej Jul 26, 2024
95438a8
partially fix trivia sourcing
bartolomej Jul 26, 2024
a6619eb
add draft test case
bartolomej Jul 28, 2024
5cffdbf
test doc comments in AST
bartolomej Jul 29, 2024
44c666b
refactor trivia parsing
bartolomej Jul 30, 2024
0539fa3
start tracking comments in ast, add sample tests
bartolomej Jul 31, 2024
1fd5a6f
update comments
bartolomej Jul 31, 2024
96e7347
parse block trailing comments
bartolomej Aug 1, 2024
ff4f9d8
update old parser, remove DocField field on FunctionDeclaration
bartolomej Aug 1, 2024
86bd62b
Merge branch 'refs/heads/master' into preserve-comments
bartolomej Aug 1, 2024
e4a1073
fix existing lexer tests
bartolomej Aug 2, 2024
4158ce8
introduce `isFollowedByTrivia`
bartolomej Aug 10, 2024
e0d8714
remove custom meta left denotations
bartolomej Aug 10, 2024
8fe1b5f
keep emiting space/newline tokens to make the parsing logic work
bartolomej Aug 10, 2024
213ae48
Revert "remove custom meta left denotations"
bartolomej Aug 10, 2024
2d7093d
Revert "introduce `isFollowedByTrivia`"
bartolomej Aug 10, 2024
4c106aa
remove comment parsing logic and token types
bartolomej Aug 10, 2024
ae6525c
combine space and newline trivia types
bartolomej Aug 10, 2024
d1592df
do not track trivia on space tokens
bartolomej Aug 10, 2024
8d2ce86
track leading comment for special function declarations
bartolomej Aug 12, 2024
de4f950
track only comments as trivia in lexer
bartolomej Aug 12, 2024
d98ab21
update tests
bartolomej Aug 12, 2024
05ed569
test eof comment
bartolomej Aug 13, 2024
dcff58b
fix parser tests
bartolomej Aug 13, 2024
4c7047e
Revert "fix existing lexer tests"
bartolomej Aug 13, 2024
2be52ed
remove trivia structs
bartolomej Aug 13, 2024
1c28707
include comments in event declaration
bartolomej Aug 16, 2024
1f1c78f
update variable declaration parsing
bartolomej Sep 21, 2024
79ecacf
update parameter parsing
bartolomej Sep 25, 2024
28604a6
Merge branch 'refs/heads/master' into preserve-comments
bartolomej Sep 25, 2024
63155ed
update variable declaration parsing
bartolomej Sep 27, 2024
b9bd76a
update event parsing tests
bartolomej Sep 27, 2024
f65f9d5
fix old parser declaration tests
bartolomej Sep 28, 2024
a145552
update parsing for composite declaration, declaration field, declarat…
bartolomej Sep 29, 2024
39457a8
update attachment declaration parsing
bartolomej Sep 29, 2024
1c66016
update interface declaration, transaction declaration parsing
bartolomej Sep 29, 2024
3575509
update entitlement parsing
bartolomej Sep 29, 2024
716a3f4
update return statement parsing
bartolomej Oct 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions runtime/ast/attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ type AttachmentDeclaration struct {
BaseType *NominalType
Conformances []*NominalType
Members *Members
DocString string
Range
Comments
}

var _ Element = &AttachmentDeclaration{}
Expand All @@ -50,8 +50,8 @@ func NewAttachmentDeclaration(
baseType *NominalType,
conformances []*NominalType,
members *Members,
docString string,
declarationRange Range,
comments Comments,
) *AttachmentDeclaration {
common.UseMemory(memoryGauge, common.AttachmentDeclarationMemoryUsage)

Expand All @@ -61,8 +61,8 @@ func NewAttachmentDeclaration(
BaseType: baseType,
Conformances: conformances,
Members: members,
DocString: docString,
Range: declarationRange,
Comments: comments,
}
}

Expand Down Expand Up @@ -99,7 +99,7 @@ func (d *AttachmentDeclaration) DeclarationMembers() *Members {
}

func (d *AttachmentDeclaration) DeclarationDocString() string {
return d.DocString
return d.Comments.LeadingDocString()
}

func (*AttachmentDeclaration) Kind() common.CompositeKind {
Expand Down Expand Up @@ -199,9 +199,11 @@ func (d *AttachmentDeclaration) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Type string
*Alias
DocString string
}{
Type: "AttachmentDeclaration",
Alias: (*Alias)(d),
Type: "AttachmentDeclaration",
Alias: (*Alias)(d),
DocString: d.DeclarationDocString(),
})
}

Expand Down
16 changes: 12 additions & 4 deletions runtime/ast/attachment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,12 @@ func TestAttachmentDeclaration_MarshallJSON(t *testing.T) {
),
},
},
Members: NewMembers(nil, []Declaration{}),
DocString: "test",
Members: NewMembers(nil, []Declaration{}),
Comments: Comments{
Leading: []*Comment{
NewComment(nil, []byte("///test")),
},
},
Range: Range{
StartPos: Position{Offset: 1, Line: 2, Column: 3},
EndPos: Position{Offset: 4, Line: 5, Column: 6},
Expand Down Expand Up @@ -141,8 +145,12 @@ func TestAttachmentDeclaration_Doc(t *testing.T) {
),
},
},
Members: NewMembers(nil, []Declaration{}),
DocString: "test",
Members: NewMembers(nil, []Declaration{}),
Comments: Comments{
Leading: []*Comment{
NewComment(nil, []byte("///test")),
},
},
Range: Range{
StartPos: Position{Offset: 1, Line: 2, Column: 3},
EndPos: Position{Offset: 4, Line: 5, Column: 6},
Expand Down
3 changes: 2 additions & 1 deletion runtime/ast/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ import (
type Block struct {
Statements []Statement
Range
Comments
}

var _ Element = &Block{}

func NewBlock(memoryGauge common.MemoryGauge, statements []Statement, astRange Range) *Block {
func NewBlock(memoryGauge common.MemoryGauge, statements []Statement, astRange Range, comments Comments) *Block {
common.UseMemory(memoryGauge, common.BlockMemoryUsage)

return &Block{
Expand Down
93 changes: 93 additions & 0 deletions runtime/ast/comments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ast

import (
"bytes"
"github.com/onflow/cadence/runtime/common"
"strings"
)

type Comments struct {
Leading []*Comment `json:"-"`
Trailing []*Comment `json:"-"`
}

func (c Comments) PackToList() []*Comment {
var comments []*Comment
comments = append(comments, c.Leading...)
comments = append(comments, c.Trailing...)
return comments
}

// LeadingDocString prints the leading doc comments to string
func (c Comments) LeadingDocString() string {
var s strings.Builder
for _, comment := range c.Leading {
if comment.Doc() {
if s.Len() > 0 {
s.WriteRune('\n')
}
s.Write(comment.Text())
}
}
return s.String()
}

type Comment struct {
source []byte
}

func NewComment(memoryGauge common.MemoryGauge, source []byte) *Comment {
// TODO(preserve-comments): Track memory usage
return &Comment{
source: source,
}
}

var blockCommentDocStringPrefix = []byte("/**")
var blockCommentStringPrefix = []byte("/*")
var lineCommentDocStringPrefix = []byte("///")
var lineCommentStringPrefix = []byte("//")
var blockCommentStringSuffix = []byte("*/")

func (c Comment) Multiline() bool {
return bytes.HasPrefix(c.source, blockCommentStringPrefix)
}

func (c Comment) Doc() bool {
if c.Multiline() {
return bytes.HasPrefix(c.source, blockCommentDocStringPrefix)
} else {
return bytes.HasPrefix(c.source, lineCommentDocStringPrefix)
}
}

// Text without opening/closing comment characters /*, /**, */, //
func (c Comment) Text() []byte {
withoutPrefixes := cutOptionalPrefixes(c.source, [][]byte{
blockCommentDocStringPrefix, // must be before blockCommentStringPrefix
blockCommentStringPrefix,
lineCommentDocStringPrefix, // must be before lineCommentStringPrefix
lineCommentStringPrefix,
})
return cutOptionalSuffixes(withoutPrefixes, [][]byte{
blockCommentStringSuffix,
})
}

func cutOptionalPrefixes(input []byte, prefixes [][]byte) (output []byte) {
output = input
for _, prefix := range prefixes {
cut, _ := bytes.CutPrefix(output, prefix)
output = cut
}
return
}

func cutOptionalSuffixes(input []byte, suffixes [][]byte) (output []byte) {
output = input
for _, suffix := range suffixes {
cut, _ := bytes.CutSuffix(output, suffix)
output = cut
}
return
}
46 changes: 26 additions & 20 deletions runtime/ast/composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ func IsResourceDestructionDefaultEvent(identifier string) bool {

type CompositeDeclaration struct {
Members *Members
DocString string
Conformances []*NominalType
Identifier Identifier
Range
Access Access
CompositeKind common.CompositeKind
Comments
}

var _ Element = &CompositeDeclaration{}
Expand All @@ -71,8 +71,8 @@ func NewCompositeDeclaration(
identifier Identifier,
conformances []*NominalType,
members *Members,
docString string,
declarationRange Range,
comments Comments,
) *CompositeDeclaration {
common.UseMemory(memoryGauge, common.CompositeDeclarationMemoryUsage)

Expand All @@ -82,8 +82,8 @@ func NewCompositeDeclaration(
Identifier: identifier,
Conformances: conformances,
Members: members,
DocString: docString,
Range: declarationRange,
Comments: comments,
}
}

Expand Down Expand Up @@ -120,17 +120,19 @@ func (d *CompositeDeclaration) DeclarationMembers() *Members {
}

func (d *CompositeDeclaration) DeclarationDocString() string {
return d.DocString
return d.Comments.LeadingDocString()
}

func (d *CompositeDeclaration) MarshalJSON() ([]byte, error) {
type Alias CompositeDeclaration
return json.Marshal(&struct {
*Alias
Type string
Type string
DocString string
}{
Type: "CompositeDeclaration",
Alias: (*Alias)(d),
Type: "CompositeDeclaration",
Alias: (*Alias)(d),
DocString: d.DeclarationDocString(),
})
}

Expand Down Expand Up @@ -304,12 +306,14 @@ const (

type FieldDeclaration struct {
TypeAnnotation *TypeAnnotation
DocString string
Identifier Identifier
// TODO(preserve-comments): Remove
DocString string
Identifier Identifier
Range
Access Access
VariableKind VariableKind
Flags FieldDeclarationFlags
Comments
}

var _ Element = &FieldDeclaration{}
Expand All @@ -323,8 +327,8 @@ func NewFieldDeclaration(
variableKind VariableKind,
identifier Identifier,
typeAnnotation *TypeAnnotation,
docString string,
declRange Range,
comments Comments,
) *FieldDeclaration {
common.UseMemory(memoryGauge, common.FieldDeclarationMemoryUsage)

Expand All @@ -342,8 +346,8 @@ func NewFieldDeclaration(
VariableKind: variableKind,
Identifier: identifier,
TypeAnnotation: typeAnnotation,
DocString: docString,
Range: declRange,
Comments: comments,
}
}

Expand Down Expand Up @@ -382,16 +386,18 @@ func (d *FieldDeclaration) MarshalJSON() ([]byte, error) {
type Alias FieldDeclaration
return json.Marshal(&struct {
*Alias
Type string
Flags FieldDeclarationFlags `json:",omitempty"`
IsStatic bool
IsNative bool
Type string
Flags FieldDeclarationFlags `json:",omitempty"`
IsStatic bool
IsNative bool
DocString string
}{
Type: "FieldDeclaration",
Alias: (*Alias)(d),
IsStatic: d.IsStatic(),
IsNative: d.IsNative(),
Flags: 0,
Type: "FieldDeclaration",
Alias: (*Alias)(d),
IsStatic: d.IsStatic(),
IsNative: d.IsNative(),
Flags: 0,
DocString: d.DeclarationDocString(),
})
}

Expand Down
8 changes: 6 additions & 2 deletions runtime/ast/composite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,12 @@ func TestCompositeDeclaration_MarshalJSON(t *testing.T) {
},
},
},
Members: NewUnmeteredMembers([]Declaration{}),
DocString: "test",
Members: NewUnmeteredMembers([]Declaration{}),
Comments: Comments{
Leading: []*Comment{
NewComment(nil, []byte("///test")),
},
},
Range: Range{
StartPos: Position{Offset: 7, Line: 8, Column: 9},
EndPos: Position{Offset: 10, Line: 11, Column: 12},
Expand Down
Loading