cadence icon indicating copy to clipboard operation
cadence copied to clipboard

Implement pretty print for Cadence

Open MaxStalker opened this issue 5 years ago • 11 comments

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.

MaxStalker avatar Jul 04 '20 15:07 MaxStalker

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:

  1. 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)

  2. 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)

turbolent avatar Jul 05 '20 05:07 turbolent

I opened #210 for the JSON serialization improvements for the AST

turbolent avatar Jul 05 '20 22:07 turbolent

I opened a first PR for #210 to demonstrate what needs to be done: #211

turbolent avatar Jul 05 '20 22:07 turbolent

Created #308 for retaining comments in the AST

turbolent avatar Aug 10 '20 16:08 turbolent

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.

turbolent avatar Aug 10 '20 16:08 turbolent

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] 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

turbolent avatar Sep 07 '20 00:09 turbolent

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.

turbolent avatar Jun 20 '21 19:06 turbolent

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 respective Doc() implementations
  • We could add settings/options to control certain aspects of pretty printing
  • We could add more "breaks" (indentation), e.g. for CastingExpression

turbolent avatar Mar 21 '22 02:03 turbolent

What is the status of this issue?

bjartek avatar Apr 28 '23 08:04 bjartek

@turbolent should we make this part of a grant?

devbugging avatar May 04 '23 16:05 devbugging

@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)

turbolent avatar May 04 '23 17:05 turbolent