cadence
cadence copied to clipboard
Implement pretty print for Cadence
Issue To Be Solved
At the moment there is no pretty print solution for Cadence, which leads to simple mistakes - single quotes for String literals, for example - and waste of time, when you would reformat your code to make it more readable.
(Optional): Suggest A Solution
Prettier is a de-facto goto solution for pretty print in web development. And it have support for plugins. Main repository also have multiple implementations - Swift, for example - which can serve as inspiration and guidance to build one for Cadence.
A formatter / pretty printer is something we've been wanting for quite a while, but have not gotten around too.
There are two things we need before we can pretty print:
-
Generate JSON from the AST where all position info (start and end) is fully calculated. Currently it is sometimes calculated from child nodes (for performance reasons: less work if not needed)
-
Add support for keeping "trivia" in the AST (that’s e.g. what it is called in Swift’s AST), i.e. leading and trailing whitespace and comments
Both aren’t hard, just a bit of work.
Once we add support for trivia, we can then also use it for other purposes, e.g. generate nice API documentation, use it as doc strings in the completion items in the VS Code extension.
I think if Prettier provides us some infrastructure which would save us some work, we should use it. As far as I understand it provides a pretty print document AST, and the task of a plugin is to translate its AST to Prettier's AST.
As an aside: The other day I played with Go’s WebAssembly target, and successfully compiled the new parser to WebAssembly in the browser. The code can be found in an unmerged branch: https://github.com/onflow/cadence/compare/bastian/astexplorer. I think we could use it to maybe avoid having to shell out to the parser (and have users build the Go parser)
I opened #210 for the JSON serialization improvements for the AST
I opened a first PR for #210 to demonstrate what needs to be done: #211
Created #308 for retaining comments in the AST
After all 5 PRs are merged, #210 should be done, and the AST is ready to be consumed!
For development, the cmd/parse tool can be used with the json flag to get the output.
Given a file program.cdc:
struct X {}
The JSON representation can be obtained with:
$ go run ./cmd/parse -json program.cdc
[
{
"path": "program.cdc",
"Program": {
"Declarations": [
{
"Type": "CompositeDeclaration",
"Access": "AccessNotSpecified",
"CompositeKind": "CompositeKindStructure",
"Identifier": {
"Identifier": "X",
"StartPos": {
"Offset": 7,
"Line": 1,
"Column": 7
},
"EndPos": {
"Offset": 7,
"Line": 1,
"Column": 7
}
},
"Conformances": null,
"Members": {
"Declarations": null
},
"DocString": "",
"StartPos": {
"Offset": 0,
"Line": 1,
"Column": 0
},
"EndPos": {
"Offset": 10,
"Line": 1,
"Column": 10
}
}
]
}
}
]
Note that the result is an array because the tool supports parsing multiple files.
List of AST elements that need to be printed:
Expressions:
- [x]
BoolExpression - [x]
NilExpression - [x]
StringExpression - [x]
IntegerExpression - [x]
FixedPointExpression - [x]
ArrayExpression - [x]
DictionaryExpression - [x]
IdentifierExpression - [x]
InvocationExpression- [x]
Argument
- [x]
- [x]
MemberExpression - [x]
IndexExpression - [x]
ConditionalExpression - [x]
UnaryExpression - [x]
BinaryExpression - [x]
FunctionExpression - [x]
CastingExpression - [x]
CreateExpression - [x]
DestroyExpression - [x]
ReferenceExpression - [x]
ForceExpression - [x]
PathExpression
Declarations:
- [x]
VariableDeclaration - [x]
FunctionDeclaration - [x]
SpecialFunctionDeclaration - [x]
ImportDeclaration - [x]
InterfaceDeclaration - [x]
TransactionDeclaration - [x]
PragmaDeclaration - [x]
CompositeDeclaration - [x]
FieldDeclaration
Function-related:
- [x]
Parameter - [x]
ParameterList - [x]
Condition - [x]
FunctionBlock
Statements:
- [x]
ReturnStatement - [x]
BreakStatement - [x]
ContinueStatement - [x]
IfStatement - [x]
WhileStatement - [x]
ForStatement - [x]
EmitStatement - [x]
AssignmentStatement - [x]
SwapStatement - [x]
ExpressionStatement
Types:
- [x]
TypeAnnotation - [x]
NominalType - [x]
OptionalType - [x]
VariableSizedType - [x]
ConstantSizedType - [x]
DictionaryType - [x]
FunctionType - [x]
ReferenceType - [x]
RestrictedType - [x]
InstantiationType
Locations:
- [x]
IdentifierLocation - [x]
StringLocation - [x]
AddressLocation
Transfer-related:
- [x]
Transfer - [x]
TransferOperation
Kinds:
- [x]
ConditionKind - [x]
VariableKind - [x]
DeclarationKind - [x]
CompositeKind
Other:
- [x]
Members - [x]
Operation - [x]
Program - [x]
Access - [x]
Block
I've started again on this, this time by implementing a pretty-printing library in Go, https://github.com/turbolent/prettier, and then started implementing functions for the AST elements above that return a prettier.Doc.
With #1520, pretty printing of all AST elements is now complete.
Last remaining actionable is printing comments, which depends on them being available in the AST, i.e. #308.
Optional / follow-up work:
- We could refactor
ast.Element.String()implementations to rely on their respectiveDoc()implementations - We could add settings/options to control certain aspects of pretty printing
- We could add more "breaks" (indentation), e.g. for
CastingExpression
What is the status of this issue?
@turbolent should we make this part of a grant?
@bjartek There has been no further progress. The last remaining item is still to retain comments in the formatted output.
@sideninja yes, we're currently working on a grant proposal for this (https://www.notion.so/dapperlabs/Implement-pretty-print-for-Cadence-32e7652c14454f668549d069cc0b5680?pvs=4)