|
1 | 1 | # QsFmt: Q# Formatter |
2 | 2 |
|
3 | | -QsFmt is a source code formatter for Q#. |
4 | | -It's in the very early stages of development and is currently experimental. |
5 | | -It will very likely eat your code when it tries to format it! |
| 3 | +QsFmt is a source code formatter and updater for Q#. |
6 | 4 |
|
7 | | -You can use the command-line tool by running `dotnet run -p App` from this folder. |
8 | | -This will only print the formatted code to the console, and won't overwrite your files, so it's safe to use. |
| 5 | +## Building From Source |
| 6 | + |
| 7 | +To build the tool from the source code, you will need to have Java installed. The latest version of |
| 8 | +Java can be downloaded from Oracle's website found [here](https://www.oracle.com/java/technologies/downloads/). |
| 9 | +Java is used by ANTLR to build the concrete syntax tree. |
| 10 | + |
| 11 | +Once Java in installed, you may build the App project by executing the following command from this directory: |
| 12 | +``` |
| 13 | +dotnet build ./App/App.fsproj |
| 14 | +``` |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +Updates the source code in input files: |
| 19 | + `qsfmt update --input Path\To\My\File1.qs Path\To\My\File2.qs` |
| 20 | +Updates the source code in project: |
| 21 | + `qsfmt update --project Path\To\My\Project.csproj` |
| 22 | + |
| 23 | +Command Line Options: |
| 24 | + `-i`, `--input`: Required. Files or folders to update. |
| 25 | + `-p`, `--project`: Required. The project file for the project to update. |
| 26 | + `-b`, `--backup`: Option to create backup files of input files. |
| 27 | + `-r`, `--recurse`: Option to process input folders recursively. |
| 28 | + `--qsharp-version`: Option to provide a Q# version to the tool. |
| 29 | + `--help`: Display this help screen. |
| 30 | + `--version`: Display version information. |
| 31 | + |
| 32 | +Either the `--input` option or the `--project` must be used to specify the input files to the tool. |
| 33 | +The `--recurse` and `--qsharp-version` options can only be used with the `--input` option. |
| 34 | + |
| 35 | +## Input and Output |
| 36 | +Input to the formatter can be specified in one of two ways. |
| 37 | +Individual files or folders can be specified with the `--input` command-line argument. |
| 38 | +Multiple files and folders can be specified after the argument, but at least one is expected. |
| 39 | +.qs extension directly under the folder will be processed. If the `--recurse` option is |
| 40 | +specified, subfolders will be processed recursively for Q# files. |
| 41 | +The other method of providing input to the formatter is by specifying a Q# project file |
| 42 | +with the `--project` command-line argument. When this method is used, exactly one project file |
| 43 | +is expected after the argument, and the tool will use MSBuild to determine all applicable Q# source |
| 44 | +files under this project. Source files from referenced libraries and other projects will not be processed. |
| 45 | +It is worth noting that the tool used to support input directly from the command-line. That is no |
| 46 | +longer supported. If there is interest in supporting that method of input, a third input command-line |
| 47 | +option specific to that input method may be created in the future. |
| 48 | + |
| 49 | +The output of the formatter is to overwrite the input files that it processes. The `--backup` |
| 50 | +option can be specified to create backup files for all input files with the original content in them. |
| 51 | + |
| 52 | +## Rules that are run |
| 53 | + |
| 54 | +Updating rules remove outdated syntax that is deprecated and will be no longer supported in the future. |
| 55 | + |
| 56 | +Updating rules currently in use: |
| 57 | + - Array Syntax - [proposal](https://github.com/microsoft/qsharp-language/blob/main/Approved/2-enhanced-array-literals.md) |
| 58 | + - Using and Borrowing Syntax - [proposal](https://github.com/microsoft/qsharp-language/blob/main/Approved/1-implicitly-scoped-qubit-allocation.md) |
| 59 | + - Parentheses in For Loop Syntax - Removes deprecated parentheses around for-loop range expressions. |
| 60 | + - Unit Syntax - Replaces deprecated unit syntax `()` for `Unit`. |
| 61 | + - Boolean Operator Syntax - Replaces deprecated use of boolean operators `&&`, `||`, and `!` with |
| 62 | + their keyword equivalence `and`, `or`, and `not` respectively. |
| 63 | + |
| 64 | +## Update vs. Format |
| 65 | + |
| 66 | +Currently the formatter only supports rules that update deprecated syntax |
| 67 | +through the use of the `update` command. A `format` command is being worked on |
| 68 | +but is not yet ready for release. This command, when ready, will format Q# |
| 69 | +code by running such rules like: |
| 70 | + - Collapsed Spaces - removes duplicate spaces so that there is only a single space where spaces are used |
| 71 | + - Operator Spacing - ensure that operators have the appropriate spaces in them |
| 72 | + - New Lines - removes excessive new lines |
| 73 | + - Indentation - ensures that there are appropriate indentation for the text |
9 | 74 |
|
10 | 75 | ## Limitations |
11 | 76 |
|
12 | | -* The current formatting capabilities are very simple, with only basic indentation and whitespace normalization. |
13 | | -* Many types of syntax are not yet supported and will remain unchanged by the formatter. |
14 | | -* There are several bugs related to other types of syntax, especially callable declaration syntax like attributes, type parameters, and specializations. |
15 | | - These may be swallowed by the formatter, resulting in incorrect output. |
| 77 | +- Currently the formatter only supports rules that update deprecated syntax through |
| 78 | + the use of the `update` command. The `format` command is not yet ready for release. |
| 79 | +- Many types of syntax are not yet supported and will remain unchanged by the formatter. |
| 80 | +- There are several bugs related to other types of syntax, especially callable declaration syntax like |
| 81 | + attributes, type parameters, and specializations. These may be swallowed by the formatter, |
| 82 | + resulting in incorrect output. |
16 | 83 |
|
17 | 84 | ## Design |
18 | 85 |
|
19 | | -QsFmt uses a [concrete syntax tree](https://en.wikipedia.org/wiki/Parse_tree), which is lossless: a Q# program parsed into a CST can be converted back into a string without any loss of information. |
20 | | -QsFmt's syntax tree is modeled on the Q# compiler's abstract syntax tree, but with additional information on every node for tokens like semicolons and curly braces that are unnecessary in an AST. |
| 86 | +QsFmt uses a [concrete syntax tree](https://en.wikipedia.org/wiki/Parse_tree), which is lossless: a |
| 87 | +Q# source file parsed into a CST can be converted back into a string without any loss of information. |
| 88 | +QsFmt's syntax tree is modeled on the Q# compiler's abstract syntax tree, but with additional |
| 89 | +information on every node for tokens like semicolons and curly braces that are unnecessary in an AST. |
21 | 90 | Whitespace and comment tokens, known as *trivia tokens*, are attached as a prefix to a non-trivia token. |
22 | | -For example, in the expression `x + y`, `x` has prefix `""`, `+` has prefix `" "`, and `y` has prefix `" "`. |
| 91 | +For example, in the expression `x + y`, `x` has prefix `""`, `+` has prefix `" "`, and `y` has |
| 92 | +prefix `" "`. |
23 | 93 |
|
24 | 94 | QsFmt uses [ANTLR](https://www.antlr.org/) to parse Q# programs. |
25 | 95 | It uses a grammar based on the [grammar in the Q# language specification](https://github.com/microsoft/qsharp-language/tree/main/Specifications/Language/5_Grammar). |
26 | 96 | ANTLR's parse tree is then converted into Q# Formatter's concrete syntax tree. |
27 | 97 |
|
28 | | -Formatting rules are a mapping from one CST to another CST. |
29 | | -Then the formatting pipeline is: |
| 98 | +Transformation rules are a mapping from one CST to another CST. |
| 99 | +Then the transformation pipeline is: |
30 | 100 |
|
31 | | -1. Parse a Q# program into a CST. |
32 | | -2. Apply formatting rules to the CST in order. |
33 | | -3. Unparse the CST into a Q# program. |
| 101 | +1. Parse a Q# source file into a CST. |
| 102 | +2. Apply transformation rules to the CST in order. |
| 103 | +3. Unparse the CST into a Q# source file. |
34 | 104 |
|
35 | | -This allows formatting transformations (indentation, brace position, etc.) to be written separately, and in many cases may be independent from each other. |
| 105 | +This allows transformations to be written separately, and in many cases may be independent from each other. |
36 | 106 | (However, there may be dependencies where one transformation must run before another.) |
37 | | -This will hopefully make the formatting transformations more modular and simpler to write. |
| 107 | +This will hopefully make the transformation rules more modular and simpler to write. |
0 commit comments