Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
137 changes: 137 additions & 0 deletions FORMATTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# MIDL3 Document Formatting

This document describes the document formatting feature added to the MIDL3 language server.

## Overview

The MIDL3 language server now includes a document formatter, similar to `clang-format` for C++. This feature automatically formats MIDL 3.0 code according to consistent style rules.

## Features

- **Automatic indentation**: Properly indents code blocks based on braces
- **Configurable indentation**: Respects VSCode settings for tabs vs spaces and tab size
- **Spacing normalization**: Ensures consistent spacing around:
- Keywords (`namespace`, `runtimeclass`, `interface`, etc.)
- Operators (`:`, `,`)
- Braces and property accessors (`{ get; set; }`)
- **Comment preservation**: Maintains single-line (`//`) and block (`/* */`) comments
- **Attribute formatting**: Properly formats attribute blocks (`[...]`)

## Usage

### Format Entire Document

- **Windows/Linux**: Press `Shift+Alt+F`
- **macOS**: Press `Shift+Option+F`
- **Command Palette**: Run "Format Document"

### Format Selection

1. Select the code you want to format
2. **Windows/Linux**: Press `Ctrl+K Ctrl+F`
3. **macOS**: Press `Cmd+K Cmd+F`
4. **Command Palette**: Run "Format Selection"

### Configuration

The formatter respects your VSCode editor settings:

```json
{
"editor.tabSize": 4, // Number of spaces per indentation level
"editor.insertSpaces": true, // Use spaces instead of tabs
"editor.formatOnSave": true // Automatically format on save (optional)
}
```

## Example

### Before Formatting

```midl
namespace WindowsDemo
{
[contract(DemoContract, 1.0)]
interface IDemoInterface
{
void DoWork();
String GetData(Int32 value);
}

runtimeclass DemoControl:IDemoInterface
{
DemoControl();
String Title{get;set;};
Int32 Value{get;};
}
}
```

### After Formatting

```midl
namespace WindowsDemo
{
[contract(DemoContract, 1.0)]
interface IDemoInterface
{
void DoWork();
String GetData(Int32 value);
}

runtimeclass DemoControl : IDemoInterface
{
DemoControl();
String Title{ get; set; };
Int32 Value{ get; };
}
}
```

## Formatting Rules

### Indentation

- Each level of nesting increases indentation by one level
- Opening braces `{` increase indent for following lines
- Closing braces `}` decrease indent for the current line

### Spacing

- **Keywords**: Single space after keywords (`namespace Name`, not `namespace Name`)
- **Inheritance**: Space around colon (`: Interface`, not `:Interface`)
- **Commas**: Space after commas (`, `, not `,`)
- **Property accessors**: Space around braces and semicolons (`{ get; set; }`, not `{get;set;}`)
- **Braces**: Space before opening brace on same line (`Name {`, not `Name{`)

### Comments

- Comments are preserved with their content unchanged
- Comments are indented to match the surrounding code
- Both single-line (`//`) and multi-line (`/* */`) comments are supported

### Attributes

- Attribute blocks `[...]` are preserved and indented
- Multiple attributes on separate lines are supported
- Attribute content is not modified

## Implementation

The formatter is implemented in `server/src/formatter.ts` and integrates with the Language Server Protocol's document formatting capabilities:

- `documentFormattingProvider`: Formats entire document
- `documentRangeFormattingProvider`: Formats selected range

## Testing

The formatter includes comprehensive unit tests in `server/src/test/formatter.test.ts` covering:

- Basic namespace and class formatting
- Property accessor normalization
- Comment preservation
- Attribute formatting
- Configurable indentation (tabs vs spaces)
- Keyword spacing normalization

All tests pass and validate the formatter's behavior.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,24 @@ Provides syntax highlighting, autocomplete, and diagnostics for [MIDL 3](https:/
- [x] Syntax highlighting
- [x] Basic semantic parsing
- [x] Diagnostics ("squigglies") and context-free auto-completions
- [x] Document formatting (similar to clang-format)
- Format entire document or selection
- Configurable indentation (tabs or spaces)
- Normalizes spacing around keywords, operators, and braces
- Preserves comments

This extension collects basic usage telemetry (e.g. which version is being used).

## Usage

### Formatting

To format a MIDL 3.0 file:
- **Format entire document**: Press `Shift+Alt+F` (Windows/Linux) or `Shift+Option+F` (Mac)
- **Format selection**: Select code and press `Ctrl+K Ctrl+F` (Windows/Linux) or `Cmd+K Cmd+F` (Mac)

The formatter respects your VSCode settings for indentation (`editor.tabSize` and `editor.insertSpaces`).

## Feedback / bug reports

https://github.com/asklar/midl-langserv
14 changes: 14 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"vscode-languageclient": "^7.0.0"
},
"devDependencies": {
"@types/node": "^16.18.126",
"@types/vscode": "^1.52.0",
"vscode-test": "^1.3.0"
}
Expand Down
32 changes: 17 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 18 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@
],
"default": "off",
"description": "Traces the communication between VS Code and the language server."
},
"midl3.format.braceStyle": {
"scope": "resource",
"type": "string",
"enum": [
"newLine",
"sameLine"
],
"default": "newLine",
"description": "Controls brace placement style. 'newLine' places opening braces on a new line, 'sameLine' places them on the same line."
},
"midl3.format.indentSize": {
"scope": "resource",
"type": "number",
"default": 4,
"description": "Number of spaces per indentation level when using spaces. Overrides editor.tabSize for MIDL3 formatting."
}
}
}
Expand All @@ -95,13 +111,13 @@
},
"devDependencies": {
"@types/mocha": "^8.0.3",
"@types/node": "^12.12.0",
"@types/node": "^16.18.126",
"@types/pegjs": "^0.10.3",
"@typescript-eslint/parser": "^2.3.0",
"copyfiles": "^2.4.1",
"eslint": "^6.4.0",
"mocha": "^8.1.1",
"typescript": "^4.2.2",
"typescript": "^5.9.3",
"vsce": "^1.96.1"
},
"dependencies": {
Expand Down
30 changes: 23 additions & 7 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"scripts": {},
"devDependencies": {
"@types/glob": "^7.1.4",
"@types/mocha": "^8.2.3",
"@types/node": "^16.18.126",
"glob": "^7.1.7"
}
}
Loading