Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dc4b73406d | |||
| 0012a5dc19 | |||
| 3cda88371e | |||
| 0338351680 | |||
| e372a0dd7c | |||
| d597f379ff | |||
| 9222a52d91 | |||
| c3670bb8cd | |||
| 2ea3456ff7 | |||
| c9379f0edb | |||
| f72010bd69 | |||
| cd027097f8 | |||
| 9cbbf729c0 | |||
|
|
c26c11e253 | ||
| 338ac358db | |||
| a83c7139c9 | |||
| 42c7d11c09 | |||
| 5ca5aa64c7 | |||
| eda7ef771e | |||
| 593c4d7783 | |||
| d24a522b32 | |||
| 41afb834ae | |||
| b745329e26 | |||
| 1fb4f64cb3 | |||
| 1f8e8981ce | |||
| a257d30dba | |||
| 97ee3b0667 | |||
| 8e2bafba5f | |||
| 6149bc133d | |||
| 5f22ee3b1f | |||
| fa72ff8061 | |||
| 65f24860e6 | |||
|
|
4881233211 | ||
| bc01fdf362 | |||
| 709998ff9c |
14
README.md
14
README.md
@@ -1,10 +1,10 @@
|
|||||||
# <img src="./frontend/public/appicon.png" alt="VoidRaft Logo" width="32" height="32" style="vertical-align: middle;"> VoidRaft
|
# <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
|
||||||
|
|
||||||
[中文](README_ZH.md) | **English**
|
[中文](README_ZH.md) | **English**
|
||||||
|
|
||||||
> *An elegant text snippet recording tool designed for developers.*
|
> *An elegant text snippet recording tool designed for developers.*
|
||||||
|
|
||||||
VoidRaft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, VoidRaft provides a smooth and elegant editing experience.
|
voidraft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, voidraft provides a smooth and elegant editing experience.
|
||||||
|
|
||||||
## Core Features
|
## Core Features
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ After building, the executable will be generated in the `bin` directory.
|
|||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
Voidraft/
|
voidraft/
|
||||||
├── frontend/ # Vue 3 frontend application
|
├── frontend/ # Vue 3 frontend application
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
│ │ ├── views/editor/ # Editor core views
|
│ │ ├── views/editor/ # Editor core views
|
||||||
@@ -129,11 +129,11 @@ Voidraft/
|
|||||||
|
|
||||||
> Standing on the shoulders of giants, paying tribute to the open source spirit
|
> Standing on the shoulders of giants, paying tribute to the open source spirit
|
||||||
|
|
||||||
The birth of VoidRaft is inseparable from the following excellent open source projects:
|
The birth of voidraft is inseparable from the following excellent open source projects:
|
||||||
|
|
||||||
### Special Thanks
|
### Special Thanks
|
||||||
|
|
||||||
- **[Heynote](https://github.com/heyman/heynote/)** - VoidRaft is a feature-enhanced version based on Heynote's concept
|
- **[Heynote](https://github.com/heyman/heynote/)** - voidraft is a feature-enhanced version based on Heynote's concept
|
||||||
- Inherits Heynote's elegant block editing philosophy
|
- Inherits Heynote's elegant block editing philosophy
|
||||||
- Adds more practical features on the original foundation
|
- Adds more practical features on the original foundation
|
||||||
- Rebuilt with modern technology stack
|
- Rebuilt with modern technology stack
|
||||||
@@ -157,7 +157,7 @@ This project is open source under the [MIT License](LICENSE).
|
|||||||
Welcome to Fork, Star, and contribute code.
|
Welcome to Fork, Star, and contribute code.
|
||||||
|
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://github.com/yourusername/Voidraft)
|
[](https://github.com/yourusername/voidraft)
|
||||||
[](https://github.com/yourusername/Voidraft)
|
[](https://github.com/yourusername/voidraft)
|
||||||
|
|
||||||
*Made with ❤️ by landaiqing*
|
*Made with ❤️ by landaiqing*
|
||||||
14
README_ZH.md
14
README_ZH.md
@@ -1,10 +1,10 @@
|
|||||||
# <img src="./frontend/public/appicon.png" alt="Voidraft Logo" width="32" height="32" style="vertical-align: middle;"> Voidraft
|
# <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
|
||||||
|
|
||||||
**中文** | [English](README.md)
|
**中文** | [English](README.md)
|
||||||
|
|
||||||
> *一个专为开发者打造的优雅文本片段记录工具。*
|
> *一个专为开发者打造的优雅文本片段记录工具。*
|
||||||
|
|
||||||
Voidraft 是一个现代化的开发者专用文本编辑器,让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,Voidraft 都能为你提供流畅而优雅的编辑体验。
|
voidraft 是一个现代化的开发者专用文本编辑器,让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,voidraft 都能为你提供流畅而优雅的编辑体验。
|
||||||
|
|
||||||
## 核心特性
|
## 核心特性
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ wails3 package
|
|||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
```
|
```
|
||||||
Voidraft/
|
voidraft/
|
||||||
├── frontend/ # Vue 3 前端应用
|
├── frontend/ # Vue 3 前端应用
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
│ │ ├── views/editor/ # 编辑器核心视图
|
│ │ ├── views/editor/ # 编辑器核心视图
|
||||||
@@ -131,11 +131,11 @@ Voidraft/
|
|||||||
|
|
||||||
> 站在巨人的肩膀上,致敬开源精神
|
> 站在巨人的肩膀上,致敬开源精神
|
||||||
|
|
||||||
Voidraft 的诞生离不开以下优秀的开源项目:
|
voidraft 的诞生离不开以下优秀的开源项目:
|
||||||
|
|
||||||
### 特别感谢
|
### 特别感谢
|
||||||
|
|
||||||
- **[Heynote](https://github.com/heyman/heynote/)** - Voidraft 是基于 Heynote 概念的功能增强版本
|
- **[Heynote](https://github.com/heyman/heynote/)** - voidraft 是基于 Heynote 概念的功能增强版本
|
||||||
- 继承了 Heynote 优雅的块状编辑理念
|
- 继承了 Heynote 优雅的块状编辑理念
|
||||||
- 在原有基础上增加了更多实用功能
|
- 在原有基础上增加了更多实用功能
|
||||||
- 采用现代化技术栈重新构建
|
- 采用现代化技术栈重新构建
|
||||||
@@ -159,7 +159,7 @@ Voidraft 的诞生离不开以下优秀的开源项目:
|
|||||||
欢迎 Fork、Star 和贡献代码。
|
欢迎 Fork、Star 和贡献代码。
|
||||||
|
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://github.com/yourusername/Voidraft)
|
[](https://github.com/yourusername/voidraft)
|
||||||
[](https://github.com/yourusername/Voidraft)
|
[](https://github.com/yourusername/voidraft)
|
||||||
|
|
||||||
*Made with ❤️ by landaiqing*
|
*Made with ❤️ by landaiqing*
|
||||||
|
|||||||
12
Taskfile.yml
12
Taskfile.yml
@@ -12,13 +12,25 @@ vars:
|
|||||||
VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}'
|
VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
version:
|
||||||
|
summary: Generate version information
|
||||||
|
cmds:
|
||||||
|
- '{{if eq OS "windows"}}cmd /c ".\scripts\version.bat"{{else}}bash ./scripts/version.sh{{end}}'
|
||||||
|
sources:
|
||||||
|
- scripts/version.bat
|
||||||
|
- scripts/version.sh
|
||||||
|
generates:
|
||||||
|
- version.txt
|
||||||
|
|
||||||
build:
|
build:
|
||||||
summary: Builds the application
|
summary: Builds the application
|
||||||
|
deps: [version]
|
||||||
cmds:
|
cmds:
|
||||||
- task: "{{OS}}:build"
|
- task: "{{OS}}:build"
|
||||||
|
|
||||||
package:
|
package:
|
||||||
summary: Packages a production build of the application
|
summary: Packages a production build of the application
|
||||||
|
deps: [version]
|
||||||
cmds:
|
cmds:
|
||||||
- task: "{{OS}}:package"
|
- task: "{{OS}}:package"
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ version: '3'
|
|||||||
|
|
||||||
# This information is used to generate the build assets.
|
# This information is used to generate the build assets.
|
||||||
info:
|
info:
|
||||||
companyName: "Voidraft" # The name of the company
|
companyName: "voidraft" # The name of the company
|
||||||
productName: "Voidraft" # The name of the application
|
productName: "voidraft" # The name of the application
|
||||||
productIdentifier: "landaiqing" # The unique product identifier
|
productIdentifier: "landaiqing" # The unique product identifier
|
||||||
description: "Voidraft" # The application description
|
description: "voidraft" # The application description
|
||||||
copyright: "© 2025 Voidraft. All rights reserved." # Copyright text
|
copyright: "© 2025 voidraft. All rights reserved." # Copyright text
|
||||||
comments: "Voidraft" # Comments
|
comments: "voidraft" # Comments
|
||||||
version: "0.0.1.0" # The application version
|
version: "0.0.1.0" # The application version
|
||||||
|
|
||||||
# Dev mode configuration
|
# Dev mode configuration
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>landaiqing</string>
|
<string>landaiqing</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.0.1.0</string>
|
<string>0.0.1.0</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.0.1.0</string>
|
<string>0.0.1.0</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<string>true</string>
|
<string>true</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>© 2025 Voidraft. All rights reserved.</string>
|
<string>© 2025 voidraft. All rights reserved.</string>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
|
|||||||
@@ -4,15 +4,15 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>landaiqing</string>
|
<string>landaiqing</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.0.1.0</string>
|
<string>0.0.1.0</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>Voidraft</string>
|
<string>voidraft</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.0.1.0</string>
|
<string>0.0.1.0</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
@@ -22,6 +22,6 @@
|
|||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<string>true</string>
|
<string>true</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>© 2025 Voidraft. All rights reserved.</string>
|
<string>© 2025 voidraft. All rights reserved.</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -11,9 +11,12 @@ tasks:
|
|||||||
- task: common:build:frontend
|
- task: common:build:frontend
|
||||||
- task: common:generate:icons
|
- task: common:generate:icons
|
||||||
cmds:
|
cmds:
|
||||||
- go build {{.BUILD_FLAGS}} -o {{.OUTPUT}}
|
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.OUTPUT}}
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
||||||
|
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s{{else}}{{end}}'
|
||||||
|
VERSION_FLAGS:
|
||||||
|
sh: 'grep "VERSION=" version.txt | cut -d"=" -f2 | xargs -I {} echo "-X voidraft/internal/version.Version={}"'
|
||||||
DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}'
|
DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}'
|
||||||
OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}'
|
OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}'
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ tasks:
|
|||||||
- task: common:build:frontend
|
- task: common:build:frontend
|
||||||
- task: common:generate:icons
|
- task: common:generate:icons
|
||||||
cmds:
|
cmds:
|
||||||
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
|
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.BIN_DIR}}/{{.APP_NAME}}
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
||||||
|
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s{{else}}{{end}}'
|
||||||
|
VERSION_FLAGS:
|
||||||
|
sh: 'grep "VERSION=" version.txt | cut -d"=" -f2 | xargs -I {} echo "-X voidraft/internal/version.Version={}"'
|
||||||
env:
|
env:
|
||||||
GOOS: linux
|
GOOS: linux
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
|
|||||||
@@ -3,26 +3,26 @@
|
|||||||
#
|
#
|
||||||
# The lines below are called `modelines`. See `:help modeline`
|
# The lines below are called `modelines`. See `:help modeline`
|
||||||
|
|
||||||
name: "Voidraft"
|
name: "voidraft"
|
||||||
arch: ${GOARCH}
|
arch: ${GOARCH}
|
||||||
platform: "linux"
|
platform: "linux"
|
||||||
version: "0.0.1.0"
|
version: "0.0.1.0"
|
||||||
section: "default"
|
section: "default"
|
||||||
priority: "extra"
|
priority: "extra"
|
||||||
maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>
|
maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>
|
||||||
description: "Voidraft"
|
description: "voidraft"
|
||||||
vendor: "Voidraft"
|
vendor: "voidraft"
|
||||||
homepage: "https://wails.io"
|
homepage: "https://voidraft.landaiqing.cn"
|
||||||
license: "MIT"
|
license: "MIT"
|
||||||
release: "1"
|
release: "1"
|
||||||
|
|
||||||
contents:
|
contents:
|
||||||
- src: "./bin/Voidraft"
|
- src: "./bin/voidraft"
|
||||||
dst: "/usr/local/bin/Voidraft"
|
dst: "/usr/local/bin/voidraft"
|
||||||
- src: "./build/appicon.png"
|
- src: "./build/appicon.png"
|
||||||
dst: "/usr/share/icons/hicolor/128x128/apps/Voidraft.png"
|
dst: "/usr/share/icons/hicolor/128x128/apps/voidraft.png"
|
||||||
- src: "./build/linux/Voidraft.desktop"
|
- src: "./build/linux/voidraft.desktop"
|
||||||
dst: "/usr/share/applications/Voidraft.desktop"
|
dst: "/usr/share/applications/voidraft.desktop"
|
||||||
|
|
||||||
depends:
|
depends:
|
||||||
- gtk3
|
- gtk3
|
||||||
|
|||||||
@@ -14,13 +14,16 @@ tasks:
|
|||||||
- task: common:generate:icons
|
- task: common:generate:icons
|
||||||
cmds:
|
cmds:
|
||||||
- task: generate:syso
|
- task: generate:syso
|
||||||
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe
|
- go build {{.BUILD_FLAGS}} -ldflags="{{.LDFLAGS}} {{.VERSION_FLAGS}}" -o {{.BIN_DIR}}/{{.APP_NAME}}.exe
|
||||||
- cmd: powershell Remove-item *.syso
|
- cmd: powershell Remove-item *.syso
|
||||||
platforms: [windows]
|
platforms: [windows]
|
||||||
- cmd: rm -f *.syso
|
- cmd: rm -f *.syso
|
||||||
platforms: [linux, darwin]
|
platforms: [linux, darwin]
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false{{else}}-buildvcs=false -gcflags=all="-l"{{end}}'
|
||||||
|
LDFLAGS: '{{if eq .PRODUCTION "true"}}-w -s -H windowsgui{{else}}{{end}}'
|
||||||
|
VERSION_FLAGS:
|
||||||
|
sh: 'powershell -Command "(Get-Content version.txt) -replace ''VERSION='', ''-X voidraft/internal/version.Version=''"'
|
||||||
env:
|
env:
|
||||||
GOOS: windows
|
GOOS: windows
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"0000": {
|
"0000": {
|
||||||
"ProductVersion": "0.0.1.0",
|
"ProductVersion": "0.0.1.0",
|
||||||
"CompanyName": "Voidraft",
|
"CompanyName": "voidraft",
|
||||||
"FileDescription": "Voidraft",
|
"FileDescription": "voidraft",
|
||||||
"LegalCopyright": "© 2025 Voidraft. All rights reserved.",
|
"LegalCopyright": "© 2025 voidraft. All rights reserved.",
|
||||||
"ProductName": "Voidraft",
|
"ProductName": "voidraft",
|
||||||
"Comments": "Voidraft"
|
"Comments": "voidraft"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,19 +5,19 @@
|
|||||||
!include "FileFunc.nsh"
|
!include "FileFunc.nsh"
|
||||||
|
|
||||||
!ifndef INFO_PROJECTNAME
|
!ifndef INFO_PROJECTNAME
|
||||||
!define INFO_PROJECTNAME "Voidraft"
|
!define INFO_PROJECTNAME "voidraft"
|
||||||
!endif
|
!endif
|
||||||
!ifndef INFO_COMPANYNAME
|
!ifndef INFO_COMPANYNAME
|
||||||
!define INFO_COMPANYNAME "Voidraft"
|
!define INFO_COMPANYNAME "voidraft"
|
||||||
!endif
|
!endif
|
||||||
!ifndef INFO_PRODUCTNAME
|
!ifndef INFO_PRODUCTNAME
|
||||||
!define INFO_PRODUCTNAME "Voidraft"
|
!define INFO_PRODUCTNAME "voidraft"
|
||||||
!endif
|
!endif
|
||||||
!ifndef INFO_PRODUCTVERSION
|
!ifndef INFO_PRODUCTVERSION
|
||||||
!define INFO_PRODUCTVERSION "0.0.1.0"
|
!define INFO_PRODUCTVERSION "0.0.1.0"
|
||||||
!endif
|
!endif
|
||||||
!ifndef INFO_COPYRIGHT
|
!ifndef INFO_COPYRIGHT
|
||||||
!define INFO_COPYRIGHT "© 2025 Voidraft. All rights reserved."
|
!define INFO_COPYRIGHT "© 2025 voidraft. All rights reserved."
|
||||||
!endif
|
!endif
|
||||||
!ifndef PRODUCT_EXECUTABLE
|
!ifndef PRODUCT_EXECUTABLE
|
||||||
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
|
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>VoidRaft - Changelog</title>
|
<title>voidraft - Changelog</title>
|
||||||
<link rel="stylesheet" href="css/styles.css">
|
<link rel="stylesheet" href="css/styles.css">
|
||||||
<link rel="stylesheet" href="css/changelog.css">
|
<link rel="stylesheet" href="css/changelog.css">
|
||||||
<link rel="icon" href="img/favicon.ico">
|
<link rel="icon" href="img/favicon.ico">
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<!-- 主卡片 -->
|
<!-- 主卡片 -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h1 class="card-title" data-en="VoidRaft Changelog" data-zh="VoidRaft 更新日志">VoidRaft Changelog</h1>
|
<h1 class="card-title" data-en="voidraft Changelog" data-zh="voidraft 更新日志">voidraft Changelog</h1>
|
||||||
<div class="card-controls">
|
<div class="card-controls">
|
||||||
<button id="theme-toggle" class="btn btn-secondary" title="切换主题">
|
<button id="theme-toggle" class="btn btn-secondary" title="切换主题">
|
||||||
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
|
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
<!-- 页脚 -->
|
<!-- 页脚 -->
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<p class="footer-text" data-en="© 2025 VoidRaft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 VoidRaft - 专为开发者打造的优雅文本片段记录工具">© 2023-2024 VoidRaft - An elegant text snippet recording tool designed for developers</p>
|
<p class="footer-text" data-en="© 2025 voidraft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 voidraft - 专为开发者打造的优雅文本片段记录工具">© 2023-2024 voidraft - An elegant text snippet recording tool designed for developers</p>
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
|
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
|
||||||
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>
|
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>VoidRaft - An elegant text snippet recording tool designed for developers.</title>
|
<title>voidraft - An elegant text snippet recording tool designed for developers.</title>
|
||||||
<meta name="description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
<meta name="description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
||||||
<meta name="keywords" content="text editor, code snippets, developer tools, syntax highlighting, code formatting, multi-language, VoidRaft">
|
<meta name="keywords" content="text editor, code snippets, developer tools, syntax highlighting, code formatting, multi-language, voidraft">
|
||||||
<meta name="author" content="VoidRaft Team">
|
<meta name="author" content="voidraft Team">
|
||||||
<meta name="robots" content="index, follow">
|
<meta name="robots" content="index, follow">
|
||||||
<link rel="canonical" href="https://landaiqing.github.io/voidraft/">
|
<link rel="canonical" href="https://landaiqing.github.io/voidraft/">
|
||||||
|
|
||||||
@@ -18,16 +18,16 @@
|
|||||||
<!-- Open Graph / Facebook -->
|
<!-- Open Graph / Facebook -->
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:url" content="https://landaiqing.github.io/voidraft/">
|
<meta property="og:url" content="https://landaiqing.github.io/voidraft/">
|
||||||
<meta property="og:title" content="VoidRaft - An elegant text snippet recording tool designed for developers">
|
<meta property="og:title" content="voidraft - An elegant text snippet recording tool designed for developers">
|
||||||
<meta property="og:description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
<meta property="og:description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
||||||
<meta property="og:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
|
<meta property="og:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
|
||||||
<meta property="og:site_name" content="VoidRaft">
|
<meta property="og:site_name" content="voidraft">
|
||||||
|
|
||||||
<!-- Twitter -->
|
<!-- Twitter -->
|
||||||
<meta property="twitter:card" content="summary_large_image">
|
<meta property="twitter:card" content="summary_large_image">
|
||||||
<meta property="twitter:url" content="https://landaiqing.github.io/voidraft/">
|
<meta property="twitter:url" content="https://landaiqing.github.io/voidraft/">
|
||||||
<meta property="twitter:title" content="VoidRaft - An elegant text snippet recording tool designed for developers">
|
<meta property="twitter:title" content="voidraft - An elegant text snippet recording tool designed for developers">
|
||||||
<meta property="twitter:description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
<meta property="twitter:description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
|
||||||
<meta property="twitter:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
|
<meta property="twitter:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
|
||||||
|
|
||||||
<link rel="stylesheet" href="./css/styles.css">
|
<link rel="stylesheet" href="./css/styles.css">
|
||||||
@@ -39,13 +39,13 @@
|
|||||||
{
|
{
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "SoftwareApplication",
|
"@type": "SoftwareApplication",
|
||||||
"name": "VoidRaft",
|
"name": "voidraft",
|
||||||
"description": "An elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.",
|
"description": "An elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.",
|
||||||
"url": "https://landaiqing.github.io/voidraft/",
|
"url": "https://landaiqing.github.io/voidraft/",
|
||||||
"downloadUrl": "https://github.com/landaiqing/voidraft/releases",
|
"downloadUrl": "https://github.com/landaiqing/voidraft/releases",
|
||||||
"author": {
|
"author": {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": "VoidRaft"
|
"name": "voidraft"
|
||||||
},
|
},
|
||||||
"operatingSystem": ["Windows", "macOS", "Linux"],
|
"operatingSystem": ["Windows", "macOS", "Linux"],
|
||||||
"applicationCategory": "DeveloperApplication",
|
"applicationCategory": "DeveloperApplication",
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
<!-- 主卡片 -->
|
<!-- 主卡片 -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h1 class="card-title">VoidRaft</h1>
|
<h1 class="card-title">voidraft</h1>
|
||||||
<div class="card-controls">
|
<div class="card-controls">
|
||||||
<button id="theme-toggle" class="btn btn-secondary" title="切换主题">
|
<button id="theme-toggle" class="btn btn-secondary" title="切换主题">
|
||||||
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
|
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
|
||||||
@@ -81,9 +81,9 @@
|
|||||||
<!-- Logo和介绍 -->
|
<!-- Logo和介绍 -->
|
||||||
<div class="logo-container">
|
<div class="logo-container">
|
||||||
<div class="logo-frame">
|
<div class="logo-frame">
|
||||||
<img src="img/logo.png" alt="VoidRaft Logo" class="logo-image">
|
<img src="img/logo.png" alt="voidraft Logo" class="logo-image">
|
||||||
</div>
|
</div>
|
||||||
<h2 class="logo-text" data-en="VoidRaft" data-zh="VoidRaft">VoidRaft</h2>
|
<h2 class="logo-text" data-en="voidraft" data-zh="voidraft">voidraft</h2>
|
||||||
<p class="tagline" data-en="An elegant text snippet recording tool" data-zh="优雅的文本片段记录工具">An elegant text snippet recording tool</p>
|
<p class="tagline" data-en="An elegant text snippet recording tool" data-zh="优雅的文本片段记录工具">An elegant text snippet recording tool</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -195,15 +195,15 @@
|
|||||||
<div class="block-language">text</div>
|
<div class="block-language">text</div>
|
||||||
</div>
|
</div>
|
||||||
<pre class="code-block">
|
<pre class="code-block">
|
||||||
<span class="comment">// VoidRaft - An elegant text snippet recording tool</span>
|
<span class="comment">// voidraft - An elegant text snippet recording tool</span>
|
||||||
<span class="comment">// Multi-language support | Code formatting | Custom themes</span>
|
<span class="comment">// Multi-language support | Code formatting | Custom themes</span>
|
||||||
<span class="comment">// A modern text editor designed for developers</span></pre>
|
<span class="comment">// A modern text editor designed for developers</span></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-window">
|
<div class="preview-window">
|
||||||
<img src="img/screenshot-dark.png" alt="VoidRaft 界面预览" class="preview-image dark-theme-img">
|
<img src="img/screenshot-dark.png" alt="voidraft 界面预览" class="preview-image dark-theme-img">
|
||||||
<img src="img/screenshot-light.png" alt="VoidRaft 界面预览" class="preview-image light-theme-img" style="display: none;">
|
<img src="img/screenshot-light.png" alt="voidraft 界面预览" class="preview-image light-theme-img" style="display: none;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
|
|
||||||
<!-- 页脚 -->
|
<!-- 页脚 -->
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<p class="footer-text" data-en="© 2025 VoidRaft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 VoidRaft - 专为开发者打造的优雅文本片段记录工具">© 2025 VoidRaft - An elegant text snippet recording tool designed for developers</p>
|
<p class="footer-text" data-en="© 2025 voidraft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 voidraft - 专为开发者打造的优雅文本片段记录工具">© 2025 voidraft - An elegant text snippet recording tool designed for developers</p>
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
|
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
|
||||||
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>
|
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* VoidRaft - Changelog Script
|
* voidraft - Changelog Script
|
||||||
* 从GitHub API获取发布信息,支持Gitea备用源
|
* 从GitHub API获取发布信息,支持Gitea备用源
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* VoidRaft - Website Script
|
* voidraft - Website Script
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,14 +233,14 @@ class SEOManager {
|
|||||||
this.languageManager = languageManager;
|
this.languageManager = languageManager;
|
||||||
this.metaTexts = {
|
this.metaTexts = {
|
||||||
en: {
|
en: {
|
||||||
description: 'VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.',
|
description: 'voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.',
|
||||||
title: 'VoidRaft - An elegant text snippet recording tool designed for developers.',
|
title: 'voidraft - An elegant text snippet recording tool designed for developers.',
|
||||||
ogTitle: 'VoidRaft - An elegant text snippet recording tool designed for developers'
|
ogTitle: 'voidraft - An elegant text snippet recording tool designed for developers'
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
description: 'VoidRaft 是专为开发者打造的优雅文本片段记录工具。支持多语言代码块、语法高亮、代码格式化、自定义主题等功能。',
|
description: 'voidraft 是专为开发者打造的优雅文本片段记录工具。支持多语言代码块、语法高亮、代码格式化、自定义主题等功能。',
|
||||||
title: 'VoidRaft - 专为开发者打造的优雅文本片段记录工具',
|
title: 'voidraft - 专为开发者打造的优雅文本片段记录工具',
|
||||||
ogTitle: 'VoidRaft - 专为开发者打造的优雅文本片段记录工具'
|
ogTitle: 'voidraft - 专为开发者打造的优雅文本片段记录工具'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.init();
|
this.init();
|
||||||
@@ -371,9 +371,9 @@ class UIEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VoidRaft主应用类
|
* voidraft主应用类
|
||||||
*/
|
*/
|
||||||
class VoidRaftApp {
|
class voidraftApp {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.themeManager = null;
|
this.themeManager = null;
|
||||||
this.languageManager = null;
|
this.languageManager = null;
|
||||||
@@ -404,7 +404,7 @@ class VoidRaftApp {
|
|||||||
* 显示控制台品牌信息
|
* 显示控制台品牌信息
|
||||||
*/
|
*/
|
||||||
showConsoleBranding() {
|
showConsoleBranding() {
|
||||||
console.log('%c VoidRaft', 'color: #ff006e; font-size: 20px; font-family: "Space Mono", monospace;');
|
console.log('%c voidraft', 'color: #ff006e; font-size: 20px; font-family: "Space Mono", monospace;');
|
||||||
console.log('%c An elegant text snippet recording tool designed for developers.', 'color: #073B4C; font-family: "Space Mono", monospace;');
|
console.log('%c An elegant text snippet recording tool designed for developers.', 'color: #073B4C; font-family: "Space Mono", monospace;');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,5 +439,5 @@ class VoidRaftApp {
|
|||||||
|
|
||||||
// 当DOM加载完成时初始化应用
|
// 当DOM加载完成时初始化应用
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
window.voidRaftApp = new VoidRaftApp();
|
window.voidRaftApp = new voidraftApp();
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service represents the notifications service
|
||||||
|
* @module
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as application$0 from "../../application/models.js";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as $models from "./models.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RemoveBadge removes the badge label from the application icon.
|
||||||
|
*/
|
||||||
|
export function RemoveBadge(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2374916939) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceName returns the name of the service.
|
||||||
|
*/
|
||||||
|
export function ServiceName(): Promise<string> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2428202016) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceShutdown is called when the service is unloaded.
|
||||||
|
*/
|
||||||
|
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3893755233) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceStartup is called when the service is loaded.
|
||||||
|
*/
|
||||||
|
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(4078800764, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SetBadge sets the badge label on the application icon.
|
||||||
|
*/
|
||||||
|
export function SetBadge(label: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(784276339, label) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SetCustomBadge(label: string, options: $models.Options): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3058653106, label, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
import * as BadgeService from "./badgeservice.js";
|
||||||
|
export {
|
||||||
|
BadgeService
|
||||||
|
};
|
||||||
|
|
||||||
|
export * from "./models.js";
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as color$0 from "../../../../../../../image/color/models.js";
|
||||||
|
|
||||||
|
export class Options {
|
||||||
|
"TextColour": color$0.RGBA;
|
||||||
|
"BackgroundColour": color$0.RGBA;
|
||||||
|
"FontName": string;
|
||||||
|
"FontSize": number;
|
||||||
|
"SmallFontSize": number;
|
||||||
|
|
||||||
|
/** Creates a new Options instance. */
|
||||||
|
constructor($$source: Partial<Options> = {}) {
|
||||||
|
if (!("TextColour" in $$source)) {
|
||||||
|
this["TextColour"] = (new color$0.RGBA());
|
||||||
|
}
|
||||||
|
if (!("BackgroundColour" in $$source)) {
|
||||||
|
this["BackgroundColour"] = (new color$0.RGBA());
|
||||||
|
}
|
||||||
|
if (!("FontName" in $$source)) {
|
||||||
|
this["FontName"] = "";
|
||||||
|
}
|
||||||
|
if (!("FontSize" in $$source)) {
|
||||||
|
this["FontSize"] = 0;
|
||||||
|
}
|
||||||
|
if (!("SmallFontSize" in $$source)) {
|
||||||
|
this["SmallFontSize"] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Options instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): Options {
|
||||||
|
const $$createField0_0 = $$createType0;
|
||||||
|
const $$createField1_0 = $$createType0;
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
if ("TextColour" in $$parsedSource) {
|
||||||
|
$$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]);
|
||||||
|
}
|
||||||
|
if ("BackgroundColour" in $$parsedSource) {
|
||||||
|
$$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]);
|
||||||
|
}
|
||||||
|
return new Options($$parsedSource as Partial<Options>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private type creation functions
|
||||||
|
const $$createType0 = color$0.RGBA.createFrom;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
import * as NotificationService from "./notificationservice.js";
|
||||||
|
export {
|
||||||
|
NotificationService
|
||||||
|
};
|
||||||
|
|
||||||
|
export * from "./models.js";
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationAction represents an action button for a notification.
|
||||||
|
*/
|
||||||
|
export class NotificationAction {
|
||||||
|
"id"?: string;
|
||||||
|
"title"?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (macOS-specific)
|
||||||
|
*/
|
||||||
|
"destructive"?: boolean;
|
||||||
|
|
||||||
|
/** Creates a new NotificationAction instance. */
|
||||||
|
constructor($$source: Partial<NotificationAction> = {}) {
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NotificationAction instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): NotificationAction {
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
return new NotificationAction($$parsedSource as Partial<NotificationAction>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationCategory groups actions for notifications.
|
||||||
|
*/
|
||||||
|
export class NotificationCategory {
|
||||||
|
"id"?: string;
|
||||||
|
"actions"?: NotificationAction[];
|
||||||
|
"hasReplyField"?: boolean;
|
||||||
|
"replyPlaceholder"?: string;
|
||||||
|
"replyButtonTitle"?: string;
|
||||||
|
|
||||||
|
/** Creates a new NotificationCategory instance. */
|
||||||
|
constructor($$source: Partial<NotificationCategory> = {}) {
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NotificationCategory instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): NotificationCategory {
|
||||||
|
const $$createField1_0 = $$createType1;
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
if ("actions" in $$parsedSource) {
|
||||||
|
$$parsedSource["actions"] = $$createField1_0($$parsedSource["actions"]);
|
||||||
|
}
|
||||||
|
return new NotificationCategory($$parsedSource as Partial<NotificationCategory>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationOptions contains configuration for a notification
|
||||||
|
*/
|
||||||
|
export class NotificationOptions {
|
||||||
|
"id": string;
|
||||||
|
"title": string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (macOS and Linux only)
|
||||||
|
*/
|
||||||
|
"subtitle"?: string;
|
||||||
|
"body"?: string;
|
||||||
|
"categoryId"?: string;
|
||||||
|
"data"?: { [_: string]: any };
|
||||||
|
|
||||||
|
/** Creates a new NotificationOptions instance. */
|
||||||
|
constructor($$source: Partial<NotificationOptions> = {}) {
|
||||||
|
if (!("id" in $$source)) {
|
||||||
|
this["id"] = "";
|
||||||
|
}
|
||||||
|
if (!("title" in $$source)) {
|
||||||
|
this["title"] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NotificationOptions instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): NotificationOptions {
|
||||||
|
const $$createField5_0 = $$createType2;
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
if ("data" in $$parsedSource) {
|
||||||
|
$$parsedSource["data"] = $$createField5_0($$parsedSource["data"]);
|
||||||
|
}
|
||||||
|
return new NotificationOptions($$parsedSource as Partial<NotificationOptions>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private type creation functions
|
||||||
|
const $$createType0 = NotificationAction.createFrom;
|
||||||
|
const $$createType1 = $Create.Array($$createType0);
|
||||||
|
const $$createType2 = $Create.Map($Create.Any, $Create.Any);
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service represents the notifications service
|
||||||
|
* @module
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as application$0 from "../../application/models.js";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as $models from "./models.js";
|
||||||
|
|
||||||
|
export function CheckNotificationAuthorization(): Promise<boolean> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2216952893) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OnNotificationResponse registers a callback function that will be called when
|
||||||
|
* a notification response is received from the user.
|
||||||
|
*/
|
||||||
|
export function OnNotificationResponse(callback: any): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(1642697808, callback) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RegisterNotificationCategory(category: $models.NotificationCategory): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2917562919, category) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemoveAllDeliveredNotifications(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3956282340) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemoveAllPendingNotifications(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(108821341) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemoveDeliveredNotification(identifier: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(975691940, identifier) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemoveNotification(identifier: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3966653866, identifier) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemoveNotificationCategory(categoryID: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2032615554, categoryID) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RemovePendingNotification(identifier: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3729049703, identifier) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public methods that delegate to the implementation.
|
||||||
|
*/
|
||||||
|
export function RequestNotificationAuthorization(): Promise<boolean> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3933442950) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SendNotification(options: $models.NotificationOptions): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3968228732, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SendNotificationWithActions(options: $models.NotificationOptions): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(1886542847, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceName returns the name of the service.
|
||||||
|
*/
|
||||||
|
export function ServiceName(): Promise<string> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2704532675) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceShutdown is called when the service is unloaded.
|
||||||
|
*/
|
||||||
|
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2550195434) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceStartup is called when the service is loaded.
|
||||||
|
*/
|
||||||
|
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(4047820929, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
4
frontend/bindings/image/color/index.ts
Normal file
4
frontend/bindings/image/color/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export * from "./models.js";
|
||||||
46
frontend/bindings/image/color/models.ts
Normal file
46
frontend/bindings/image/color/models.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RGBA represents a traditional 32-bit alpha-premultiplied color, having 8
|
||||||
|
* bits for each of red, green, blue and alpha.
|
||||||
|
*
|
||||||
|
* An alpha-premultiplied color component C has been scaled by alpha (A), so
|
||||||
|
* has valid values 0 <= C <= A.
|
||||||
|
*/
|
||||||
|
export class RGBA {
|
||||||
|
"R": number;
|
||||||
|
"G": number;
|
||||||
|
"B": number;
|
||||||
|
"A": number;
|
||||||
|
|
||||||
|
/** Creates a new RGBA instance. */
|
||||||
|
constructor($$source: Partial<RGBA> = {}) {
|
||||||
|
if (!("R" in $$source)) {
|
||||||
|
this["R"] = 0;
|
||||||
|
}
|
||||||
|
if (!("G" in $$source)) {
|
||||||
|
this["G"] = 0;
|
||||||
|
}
|
||||||
|
if (!("B" in $$source)) {
|
||||||
|
this["B"] = 0;
|
||||||
|
}
|
||||||
|
if (!("A" in $$source)) {
|
||||||
|
this["A"] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RGBA instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): RGBA {
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
return new RGBA($$parsedSource as Partial<RGBA>);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -467,6 +467,12 @@ export class GeneralConfig {
|
|||||||
*/
|
*/
|
||||||
"startAtLogin": boolean;
|
"startAtLogin": boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 窗口吸附设置
|
||||||
|
* 是否启用窗口吸附功能(阈值现在是自适应的)
|
||||||
|
*/
|
||||||
|
"enableWindowSnap": boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局热键设置
|
* 全局热键设置
|
||||||
* 是否启用全局热键
|
* 是否启用全局热键
|
||||||
@@ -478,6 +484,12 @@ export class GeneralConfig {
|
|||||||
*/
|
*/
|
||||||
"globalHotkey": HotkeyCombo;
|
"globalHotkey": HotkeyCombo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 界面设置
|
||||||
|
* 是否启用加载动画
|
||||||
|
*/
|
||||||
|
"enableLoadingAnimation": boolean;
|
||||||
|
|
||||||
/** Creates a new GeneralConfig instance. */
|
/** Creates a new GeneralConfig instance. */
|
||||||
constructor($$source: Partial<GeneralConfig> = {}) {
|
constructor($$source: Partial<GeneralConfig> = {}) {
|
||||||
if (!("alwaysOnTop" in $$source)) {
|
if (!("alwaysOnTop" in $$source)) {
|
||||||
@@ -492,12 +504,18 @@ export class GeneralConfig {
|
|||||||
if (!("startAtLogin" in $$source)) {
|
if (!("startAtLogin" in $$source)) {
|
||||||
this["startAtLogin"] = false;
|
this["startAtLogin"] = false;
|
||||||
}
|
}
|
||||||
|
if (!("enableWindowSnap" in $$source)) {
|
||||||
|
this["enableWindowSnap"] = false;
|
||||||
|
}
|
||||||
if (!("enableGlobalHotkey" in $$source)) {
|
if (!("enableGlobalHotkey" in $$source)) {
|
||||||
this["enableGlobalHotkey"] = false;
|
this["enableGlobalHotkey"] = false;
|
||||||
}
|
}
|
||||||
if (!("globalHotkey" in $$source)) {
|
if (!("globalHotkey" in $$source)) {
|
||||||
this["globalHotkey"] = (new HotkeyCombo());
|
this["globalHotkey"] = (new HotkeyCombo());
|
||||||
}
|
}
|
||||||
|
if (!("enableLoadingAnimation" in $$source)) {
|
||||||
|
this["enableLoadingAnimation"] = false;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(this, $$source);
|
Object.assign(this, $$source);
|
||||||
}
|
}
|
||||||
@@ -506,10 +524,10 @@ export class GeneralConfig {
|
|||||||
* Creates a new GeneralConfig instance from a string or object.
|
* Creates a new GeneralConfig instance from a string or object.
|
||||||
*/
|
*/
|
||||||
static createFrom($$source: any = {}): GeneralConfig {
|
static createFrom($$source: any = {}): GeneralConfig {
|
||||||
const $$createField5_0 = $$createType8;
|
const $$createField6_0 = $$createType8;
|
||||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
if ("globalHotkey" in $$parsedSource) {
|
if ("globalHotkey" in $$parsedSource) {
|
||||||
$$parsedSource["globalHotkey"] = $$createField5_0($$parsedSource["globalHotkey"]);
|
$$parsedSource["globalHotkey"] = $$createField6_0($$parsedSource["globalHotkey"]);
|
||||||
}
|
}
|
||||||
return new GeneralConfig($$parsedSource as Partial<GeneralConfig>);
|
return new GeneralConfig($$parsedSource as Partial<GeneralConfig>);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,30 @@ export function GetConfig(): Promise<models$0.AppConfig | null> & { cancel(): vo
|
|||||||
return $typingPromise;
|
return $typingPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetConfigDir 获取配置目录
|
||||||
|
*/
|
||||||
|
export function GetConfigDir(): Promise<string> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2275626561) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetSettingsPath 获取设置文件路径
|
||||||
|
*/
|
||||||
|
export function GetSettingsPath(): Promise<string> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2175583370) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MigrateConfig 执行配置迁移
|
||||||
|
*/
|
||||||
|
export function MigrateConfig(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(434292783) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResetConfig 强制重置所有配置为默认值
|
* ResetConfig 强制重置所有配置为默认值
|
||||||
*/
|
*/
|
||||||
@@ -82,6 +106,14 @@ export function SetHotkeyChangeCallback(callback: any): Promise<void> & { cancel
|
|||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SetWindowSnapConfigChangeCallback 设置窗口吸附配置变更回调
|
||||||
|
*/
|
||||||
|
export function SetWindowSnapConfigChangeCallback(callback: any): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2324961653, callback) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
// Private type creation functions
|
// Private type creation functions
|
||||||
const $$createType0 = models$0.AppConfig.createFrom;
|
const $$createType0 = models$0.AppConfig.createFrom;
|
||||||
const $$createType1 = $Create.Nullable($$createType0);
|
const $$createType1 = $Create.Nullable($$createType0);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import * as MigrationService from "./migrationservice.js";
|
|||||||
import * as SelfUpdateService from "./selfupdateservice.js";
|
import * as SelfUpdateService from "./selfupdateservice.js";
|
||||||
import * as StartupService from "./startupservice.js";
|
import * as StartupService from "./startupservice.js";
|
||||||
import * as SystemService from "./systemservice.js";
|
import * as SystemService from "./systemservice.js";
|
||||||
|
import * as TestService from "./testservice.js";
|
||||||
import * as ThemeService from "./themeservice.js";
|
import * as ThemeService from "./themeservice.js";
|
||||||
import * as TranslationService from "./translationservice.js";
|
import * as TranslationService from "./translationservice.js";
|
||||||
import * as TrayService from "./trayservice.js";
|
import * as TrayService from "./trayservice.js";
|
||||||
@@ -30,6 +31,7 @@ export {
|
|||||||
SelfUpdateService,
|
SelfUpdateService,
|
||||||
StartupService,
|
StartupService,
|
||||||
SystemService,
|
SystemService,
|
||||||
|
TestService,
|
||||||
ThemeService,
|
ThemeService,
|
||||||
TranslationService,
|
TranslationService,
|
||||||
TrayService,
|
TrayService,
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ export class SelfUpdateResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WindowInfo 窗口信息
|
* WindowInfo 窗口信息(简化版)
|
||||||
*/
|
*/
|
||||||
export class WindowInfo {
|
export class WindowInfo {
|
||||||
"Window": application$0.WebviewWindow | null;
|
"Window": application$0.WebviewWindow | null;
|
||||||
@@ -238,6 +238,26 @@ export class WindowInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WindowSnapService 窗口吸附服务
|
||||||
|
*/
|
||||||
|
export class WindowSnapService {
|
||||||
|
|
||||||
|
/** Creates a new WindowSnapService instance. */
|
||||||
|
constructor($$source: Partial<WindowSnapService> = {}) {
|
||||||
|
|
||||||
|
Object.assign(this, $$source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new WindowSnapService instance from a string or object.
|
||||||
|
*/
|
||||||
|
static createFrom($$source: any = {}): WindowSnapService {
|
||||||
|
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||||
|
return new WindowSnapService($$parsedSource as Partial<WindowSnapService>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Private type creation functions
|
// Private type creation functions
|
||||||
const $$createType0 = application$0.WebviewWindow.createFrom;
|
const $$createType0 = application$0.WebviewWindow.createFrom;
|
||||||
const $$createType1 = $Create.Nullable($$createType0);
|
const $$createType1 = $Create.Nullable($$createType0);
|
||||||
|
|||||||
55
frontend/bindings/voidraft/internal/services/testservice.ts
Normal file
55
frontend/bindings/voidraft/internal/services/testservice.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestService 测试服务 - 仅在开发环境使用
|
||||||
|
* @module
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore: Unused imports
|
||||||
|
import * as application$0 from "../../../github.com/wailsapp/wails/v3/pkg/application/models.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClearAll 清除所有测试状态
|
||||||
|
*/
|
||||||
|
export function ClearAll(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(2179720854) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceStartup 服务启动时调用
|
||||||
|
*/
|
||||||
|
export function ServiceStartup(options: application$0.ServiceOptions): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(617408198, options) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestBadge 测试Badge功能
|
||||||
|
*/
|
||||||
|
export function TestBadge(text: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(4242952145, text) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestNotification 测试通知功能
|
||||||
|
*/
|
||||||
|
export function TestNotification(title: string, subtitle: string, body: string): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(1697553289, title, subtitle, body) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestUpdateNotification 测试更新通知
|
||||||
|
*/
|
||||||
|
export function TestUpdateNotification(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3091730060) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WindowService 窗口管理服务
|
* WindowService 窗口管理服务(专注于窗口生命周期管理)
|
||||||
* @module
|
* @module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -46,6 +46,14 @@ export function OpenDocumentWindow(documentID: number): Promise<void> & { cancel
|
|||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceShutdown 实现服务关闭接口
|
||||||
|
*/
|
||||||
|
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(202192783) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SetAppReferences 设置应用和主窗口引用
|
* SetAppReferences 设置应用和主窗口引用
|
||||||
*/
|
*/
|
||||||
@@ -54,6 +62,14 @@ export function SetAppReferences(app: application$0.App | null, mainWindow: appl
|
|||||||
return $resultPromise;
|
return $resultPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SetWindowSnapService 设置窗口吸附服务引用
|
||||||
|
*/
|
||||||
|
export function SetWindowSnapService(snapService: $models.WindowSnapService | null): Promise<void> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(1105193745, snapService) as any;
|
||||||
|
return $resultPromise;
|
||||||
|
}
|
||||||
|
|
||||||
// Private type creation functions
|
// Private type creation functions
|
||||||
const $$createType0 = $models.WindowInfo.createFrom;
|
const $$createType0 = $models.WindowInfo.createFrom;
|
||||||
const $$createType1 = $Create.Array($$createType0);
|
const $$createType1 = $Create.Array($$createType0);
|
||||||
|
|||||||
@@ -9,5 +9,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
<script src="/math.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
2509
frontend/package-lock.json
generated
2509
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,20 +5,20 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host --mode development",
|
"dev": "vite --host --mode development",
|
||||||
"build:dev": "vue-tsc && vite build --minify false --mode development",
|
"build:dev": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vue-tsc && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vite build --minify false --mode development",
|
||||||
"build": "vue-tsc && vite build --mode production",
|
"build": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vue-tsc && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" vite build --mode production",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint",
|
"lint": "eslint",
|
||||||
"lint:fix": "eslint --fix"
|
"lint:fix": "eslint --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.18.6",
|
"@codemirror/autocomplete": "^6.18.7",
|
||||||
"@codemirror/commands": "^6.8.1",
|
"@codemirror/commands": "^6.8.1",
|
||||||
"@codemirror/lang-angular": "^0.1.4",
|
"@codemirror/lang-angular": "^0.1.4",
|
||||||
"@codemirror/lang-cpp": "^6.0.3",
|
"@codemirror/lang-cpp": "^6.0.3",
|
||||||
"@codemirror/lang-css": "^6.3.1",
|
"@codemirror/lang-css": "^6.3.1",
|
||||||
"@codemirror/lang-go": "^6.0.1",
|
"@codemirror/lang-go": "^6.0.1",
|
||||||
"@codemirror/lang-html": "^6.4.9",
|
"@codemirror/lang-html": "^6.4.10",
|
||||||
"@codemirror/lang-java": "^6.0.2",
|
"@codemirror/lang-java": "^6.0.2",
|
||||||
"@codemirror/lang-javascript": "^6.2.4",
|
"@codemirror/lang-javascript": "^6.2.4",
|
||||||
"@codemirror/lang-json": "^6.0.2",
|
"@codemirror/lang-json": "^6.0.2",
|
||||||
@@ -33,7 +33,6 @@
|
|||||||
"@codemirror/lang-sql": "^6.9.1",
|
"@codemirror/lang-sql": "^6.9.1",
|
||||||
"@codemirror/lang-vue": "^0.1.3",
|
"@codemirror/lang-vue": "^0.1.3",
|
||||||
"@codemirror/lang-wast": "^6.0.2",
|
"@codemirror/lang-wast": "^6.0.2",
|
||||||
"@codemirror/lang-xml": "^6.1.0",
|
|
||||||
"@codemirror/lang-yaml": "^6.1.2",
|
"@codemirror/lang-yaml": "^6.1.2",
|
||||||
"@codemirror/language": "^6.11.3",
|
"@codemirror/language": "^6.11.3",
|
||||||
"@codemirror/language-data": "^6.5.1",
|
"@codemirror/language-data": "^6.5.1",
|
||||||
@@ -41,41 +40,53 @@
|
|||||||
"@codemirror/lint": "^6.8.5",
|
"@codemirror/lint": "^6.8.5",
|
||||||
"@codemirror/search": "^6.5.11",
|
"@codemirror/search": "^6.5.11",
|
||||||
"@codemirror/state": "^6.5.2",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@codemirror/view": "^6.38.1",
|
"@codemirror/view": "^6.38.2",
|
||||||
|
"@cospaia/prettier-plugin-clojure": "^0.0.2",
|
||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@lezer/lr": "^1.4.2",
|
"@lezer/lr": "^1.4.2",
|
||||||
|
"@prettier/plugin-xml": "^3.4.2",
|
||||||
|
"@reteps/dockerfmt": "^0.3.6",
|
||||||
|
"@toml-tools/lexer": "^1.0.0",
|
||||||
|
"@toml-tools/parser": "^1.0.0",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
"codemirror-lang-elixir": "^4.0.0",
|
"codemirror-lang-elixir": "^4.0.0",
|
||||||
"colors-named": "^1.0.2",
|
"colors-named": "^1.0.2",
|
||||||
"colors-named-hex": "^1.0.2",
|
"colors-named-hex": "^1.0.2",
|
||||||
"franc-min": "^6.2.0",
|
"franc-min": "^6.2.0",
|
||||||
|
"groovy-beautify": "^0.0.17",
|
||||||
"hsl-matcher": "^1.2.4",
|
"hsl-matcher": "^1.2.4",
|
||||||
"lezer": "^0.13.5",
|
"java-parser": "^3.0.1",
|
||||||
|
"jsox": "^1.2.123",
|
||||||
|
"linguist-languages": "^9.0.0",
|
||||||
|
"php-parser": "^3.2.5",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
"pinia-plugin-persistedstate": "^4.5.0",
|
"pinia-plugin-persistedstate": "^4.5.0",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"remarkable": "^2.0.1",
|
"remarkable": "^2.0.1",
|
||||||
"sass": "^1.90.0",
|
"sass": "^1.92.1",
|
||||||
"vue": "^3.5.18",
|
"sh-syntax": "^0.5.8",
|
||||||
"vue-i18n": "^11.1.11",
|
"vue": "^3.5.21",
|
||||||
|
"vue-i18n": "^11.1.12",
|
||||||
"vue-pick-colors": "^1.8.0",
|
"vue-pick-colors": "^1.8.0",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.33.0",
|
"@eslint/js": "^9.35.0",
|
||||||
"@lezer/generator": "^1.8.0",
|
"@lezer/generator": "^1.8.0",
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^24.3.1",
|
||||||
"@types/remarkable": "^2.0.8",
|
"@types/remarkable": "^2.0.8",
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@wailsio/runtime": "latest",
|
"@wailsio/runtime": "latest",
|
||||||
"eslint": "^9.33.0",
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^9.35.0",
|
||||||
"eslint-plugin-vue": "^10.4.0",
|
"eslint-plugin-vue": "^10.4.0",
|
||||||
"globals": "^16.3.0",
|
"globals": "^16.4.0",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"typescript-eslint": "^8.39.1",
|
"typescript-eslint": "^8.43.0",
|
||||||
"unplugin-vue-components": "^29.0.0",
|
"unplugin-vue-components": "^29.0.0",
|
||||||
"vite": "^7.1.2",
|
"vite": "^7.1.5",
|
||||||
|
"vite-plugin-node-polyfills": "^0.24.0",
|
||||||
"vue-eslint-parser": "^10.2.0",
|
"vue-eslint-parser": "^10.2.0",
|
||||||
"vue-tsc": "^3.0.5"
|
"vue-tsc": "^3.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
importScripts("guesslang.min.js")
|
importScripts("guesslang.min.js")
|
||||||
|
|
||||||
const LANGUAGES = ["json", "py", "html", "sql", "md", "java", "php", "css", "xml", "cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj", "ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"]
|
|
||||||
|
|
||||||
const guessLang = new self.GuessLang()
|
const guessLang = new self.GuessLang()
|
||||||
|
|
||||||
function sendResult(language, confidence, idx) {
|
function sendResult(language, confidence, idx) {
|
||||||
@@ -27,20 +25,13 @@ onmessage = (event) => {
|
|||||||
|
|
||||||
guessLang.runModel(content).then((result) => {
|
guessLang.runModel(content).then((result) => {
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
const lang = result[0]
|
// 返回置信度最高的结果
|
||||||
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.15) {
|
const bestResult = result[0]
|
||||||
sendResult(lang.languageId, lang.confidence, idx)
|
if (bestResult.confidence > 0.15) {
|
||||||
|
sendResult(bestResult.languageId, bestResult.confidence, idx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let lang of result) {
|
|
||||||
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.5) {
|
|
||||||
sendResult(lang.languageId, lang.confidence, idx)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendResult("text", 0.0, idx)
|
sendResult("text", 0.0, idx)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
sendResult("text", 0.0, idx)
|
sendResult("text", 0.0, idx)
|
||||||
|
|||||||
3
frontend/public/math.js
Normal file
3
frontend/public/math.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
frontend/src/common/prettier/plugins/clang/clang-format-cli.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/clang/clang-format-cli.wasm
Normal file
Binary file not shown.
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./clang-format.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./clang-format.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function (init = fs.readFile(wasm)) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./clang-format.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./clang-format.js";
|
||||||
|
import wasm from "./clang-format.wasm?url";
|
||||||
|
|
||||||
|
export default function (input = wasm) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./clang-format.js";
|
||||||
155
frontend/src/common/prettier/plugins/clang/clang-format.js
Normal file
155
frontend/src/common/prettier/plugins/clang/clang-format.js
Normal file
File diff suppressed because one or more lines are too long
BIN
frontend/src/common/prettier/plugins/clang/clang-format.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/clang/clang-format.wasm
Normal file
Binary file not shown.
3
frontend/src/common/prettier/plugins/clang/cli-pre.js
Normal file
3
frontend/src/common/prettier/plugins/clang/cli-pre.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Module.preRun = function customPreRun() {
|
||||||
|
ENV.PWD = process.cwd();
|
||||||
|
}
|
||||||
858
frontend/src/common/prettier/plugins/clang/git-clang-format
Normal file
858
frontend/src/common/prettier/plugins/clang/git-clang-format
Normal file
@@ -0,0 +1,858 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# ===- git-clang-format - ClangFormat Git Integration -------*- python -*--=== #
|
||||||
|
#
|
||||||
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
# See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
#
|
||||||
|
# ===----------------------------------------------------------------------=== #
|
||||||
|
|
||||||
|
r"""
|
||||||
|
clang-format git integration
|
||||||
|
============================
|
||||||
|
|
||||||
|
This file provides a clang-format integration for git. Put it somewhere in your
|
||||||
|
path and ensure that it is executable. Then, "git clang-format" will invoke
|
||||||
|
clang-format on the changes in current files or a specific commit.
|
||||||
|
|
||||||
|
For further details, run:
|
||||||
|
git clang-format -h
|
||||||
|
|
||||||
|
Requires Python version >=3.8
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
import argparse
|
||||||
|
import collections
|
||||||
|
import contextlib
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
usage = "git clang-format [OPTIONS] [<commit>] [<commit>|--staged] [--] [<file>...]"
|
||||||
|
|
||||||
|
desc = """
|
||||||
|
If zero or one commits are given, run clang-format on all lines that differ
|
||||||
|
between the working directory and <commit>, which defaults to HEAD. Changes are
|
||||||
|
only applied to the working directory, or in the stage/index.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
To format staged changes, i.e everything that's been `git add`ed:
|
||||||
|
git clang-format
|
||||||
|
|
||||||
|
To also format everything touched in the most recent commit:
|
||||||
|
git clang-format HEAD~1
|
||||||
|
|
||||||
|
If you're on a branch off main, to format everything touched on your branch:
|
||||||
|
git clang-format main
|
||||||
|
|
||||||
|
If two commits are given (requires --diff), run clang-format on all lines in the
|
||||||
|
second <commit> that differ from the first <commit>.
|
||||||
|
|
||||||
|
The following git-config settings set the default of the corresponding option:
|
||||||
|
clangFormat.binary
|
||||||
|
clangFormat.commit
|
||||||
|
clangFormat.extensions
|
||||||
|
clangFormat.style
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Name of the temporary index file in which save the output of clang-format.
|
||||||
|
# This file is created within the .git directory.
|
||||||
|
temp_index_basename = "clang-format-index"
|
||||||
|
|
||||||
|
|
||||||
|
Range = collections.namedtuple("Range", "start, count")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config = load_git_config()
|
||||||
|
|
||||||
|
# In order to keep '--' yet allow options after positionals, we need to
|
||||||
|
# check for '--' ourselves. (Setting nargs='*' throws away the '--', while
|
||||||
|
# nargs=argparse.REMAINDER disallows options after positionals.)
|
||||||
|
argv = sys.argv[1:]
|
||||||
|
try:
|
||||||
|
idx = argv.index("--")
|
||||||
|
except ValueError:
|
||||||
|
dash_dash = []
|
||||||
|
else:
|
||||||
|
dash_dash = argv[idx:]
|
||||||
|
argv = argv[:idx]
|
||||||
|
|
||||||
|
default_extensions = ",".join(
|
||||||
|
[
|
||||||
|
# From clang/lib/Frontend/FrontendOptions.cpp, all lower case
|
||||||
|
"c",
|
||||||
|
"h", # C
|
||||||
|
"m", # ObjC
|
||||||
|
"mm", # ObjC++
|
||||||
|
"cc",
|
||||||
|
"cp",
|
||||||
|
"cpp",
|
||||||
|
"c++",
|
||||||
|
"cxx",
|
||||||
|
"hh",
|
||||||
|
"hpp",
|
||||||
|
"hxx",
|
||||||
|
"inc", # C++
|
||||||
|
"ccm",
|
||||||
|
"cppm",
|
||||||
|
"cxxm",
|
||||||
|
"c++m", # C++ Modules
|
||||||
|
"cu",
|
||||||
|
"cuh", # CUDA
|
||||||
|
"cl", # OpenCL
|
||||||
|
# Other languages that clang-format supports
|
||||||
|
"proto",
|
||||||
|
"protodevel", # Protocol Buffers
|
||||||
|
"java", # Java
|
||||||
|
"js",
|
||||||
|
"mjs",
|
||||||
|
"cjs", # JavaScript
|
||||||
|
"ts", # TypeScript
|
||||||
|
"cs", # C Sharp
|
||||||
|
"json",
|
||||||
|
"ipynb", # Json
|
||||||
|
"sv",
|
||||||
|
"svh",
|
||||||
|
"v",
|
||||||
|
"vh", # Verilog
|
||||||
|
"td", # TableGen
|
||||||
|
"txtpb",
|
||||||
|
"textpb",
|
||||||
|
"pb.txt",
|
||||||
|
"textproto",
|
||||||
|
"asciipb", # TextProto
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
p = argparse.ArgumentParser(
|
||||||
|
usage=usage,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=desc,
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--binary",
|
||||||
|
default=config.get("clangformat.binary", "clang-format"),
|
||||||
|
help="path to clang-format",
|
||||||
|
),
|
||||||
|
p.add_argument(
|
||||||
|
"--commit",
|
||||||
|
default=config.get("clangformat.commit", "HEAD"),
|
||||||
|
help="default commit to use if none is specified",
|
||||||
|
),
|
||||||
|
p.add_argument(
|
||||||
|
"--diff",
|
||||||
|
action="store_true",
|
||||||
|
help="print a diff instead of applying the changes",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--diffstat",
|
||||||
|
action="store_true",
|
||||||
|
help="print a diffstat instead of applying the changes",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--extensions",
|
||||||
|
default=config.get("clangformat.extensions", default_extensions),
|
||||||
|
help=(
|
||||||
|
"comma-separated list of file extensions to format, "
|
||||||
|
"excluding the period and case-insensitive"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
p.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--force",
|
||||||
|
action="store_true",
|
||||||
|
help="allow changes to unstaged files",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"-p", "--patch", action="store_true", help="select hunks interactively"
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"-q",
|
||||||
|
"--quiet",
|
||||||
|
action="count",
|
||||||
|
default=0,
|
||||||
|
help="print less information",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--staged",
|
||||||
|
"--cached",
|
||||||
|
action="store_true",
|
||||||
|
help="format lines in the stage instead of the working dir",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--style",
|
||||||
|
default=config.get("clangformat.style", None),
|
||||||
|
help="passed to clang-format",
|
||||||
|
),
|
||||||
|
p.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
action="count",
|
||||||
|
default=0,
|
||||||
|
help="print extra information",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--diff_from_common_commit",
|
||||||
|
action="store_true",
|
||||||
|
help=(
|
||||||
|
"diff from the last common commit for commits in "
|
||||||
|
"separate branches rather than the exact point of the "
|
||||||
|
"commits"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
# We gather all the remaining positional arguments into 'args' since we need
|
||||||
|
# to use some heuristics to determine whether or not <commit> was present.
|
||||||
|
# However, to print pretty messages, we make use of metavar and help.
|
||||||
|
p.add_argument(
|
||||||
|
"args",
|
||||||
|
nargs="*",
|
||||||
|
metavar="<commit>",
|
||||||
|
help="revision from which to compute the diff",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"ignored",
|
||||||
|
nargs="*",
|
||||||
|
metavar="<file>...",
|
||||||
|
help="if specified, only consider differences in these files",
|
||||||
|
)
|
||||||
|
opts = p.parse_args(argv)
|
||||||
|
|
||||||
|
opts.verbose -= opts.quiet
|
||||||
|
del opts.quiet
|
||||||
|
|
||||||
|
commits, files = interpret_args(opts.args, dash_dash, opts.commit)
|
||||||
|
if len(commits) > 2:
|
||||||
|
die("at most two commits allowed; %d given" % len(commits))
|
||||||
|
if len(commits) == 2:
|
||||||
|
if opts.staged:
|
||||||
|
die("--staged is not allowed when two commits are given")
|
||||||
|
if not opts.diff:
|
||||||
|
die("--diff is required when two commits are given")
|
||||||
|
elif opts.diff_from_common_commit:
|
||||||
|
die("--diff_from_common_commit is only allowed when two commits are given")
|
||||||
|
|
||||||
|
if os.path.dirname(opts.binary):
|
||||||
|
opts.binary = os.path.abspath(opts.binary)
|
||||||
|
|
||||||
|
changed_lines = compute_diff_and_extract_lines(
|
||||||
|
commits, files, opts.staged, opts.diff_from_common_commit
|
||||||
|
)
|
||||||
|
if opts.verbose >= 1:
|
||||||
|
ignored_files = set(changed_lines)
|
||||||
|
filter_by_extension(changed_lines, opts.extensions.lower().split(","))
|
||||||
|
# The computed diff outputs absolute paths, so we must cd before accessing
|
||||||
|
# those files.
|
||||||
|
cd_to_toplevel()
|
||||||
|
filter_symlinks(changed_lines)
|
||||||
|
filter_ignored_files(changed_lines, binary=opts.binary)
|
||||||
|
if opts.verbose >= 1:
|
||||||
|
ignored_files.difference_update(changed_lines)
|
||||||
|
if ignored_files:
|
||||||
|
print(
|
||||||
|
"Ignoring the following files (wrong extension, symlink, or "
|
||||||
|
"ignored by clang-format):"
|
||||||
|
)
|
||||||
|
for filename in ignored_files:
|
||||||
|
print(" %s" % filename)
|
||||||
|
if changed_lines:
|
||||||
|
print("Running clang-format on the following files:")
|
||||||
|
for filename in changed_lines:
|
||||||
|
print(" %s" % filename)
|
||||||
|
|
||||||
|
if not changed_lines:
|
||||||
|
if opts.verbose >= 0:
|
||||||
|
print("no modified files to format")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if len(commits) > 1:
|
||||||
|
old_tree = commits[1]
|
||||||
|
revision = old_tree
|
||||||
|
elif opts.staged:
|
||||||
|
old_tree = create_tree_from_index(changed_lines)
|
||||||
|
revision = ""
|
||||||
|
else:
|
||||||
|
old_tree = create_tree_from_workdir(changed_lines)
|
||||||
|
revision = None
|
||||||
|
new_tree = run_clang_format_and_save_to_tree(
|
||||||
|
changed_lines, revision, binary=opts.binary, style=opts.style
|
||||||
|
)
|
||||||
|
if opts.verbose >= 1:
|
||||||
|
print("old tree: %s" % old_tree)
|
||||||
|
print("new tree: %s" % new_tree)
|
||||||
|
|
||||||
|
if old_tree == new_tree:
|
||||||
|
if opts.verbose >= 0:
|
||||||
|
print("clang-format did not modify any files")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if opts.diff:
|
||||||
|
return print_diff(old_tree, new_tree)
|
||||||
|
if opts.diffstat:
|
||||||
|
return print_diffstat(old_tree, new_tree)
|
||||||
|
|
||||||
|
changed_files = apply_changes(
|
||||||
|
old_tree, new_tree, force=opts.force, patch_mode=opts.patch
|
||||||
|
)
|
||||||
|
if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
|
||||||
|
print("changed files:")
|
||||||
|
for filename in changed_files:
|
||||||
|
print(" %s" % filename)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def load_git_config(non_string_options=None):
|
||||||
|
"""Return the git configuration as a dictionary.
|
||||||
|
|
||||||
|
All options are assumed to be strings unless in `non_string_options`, in
|
||||||
|
which is a dictionary mapping option name (in lower case) to either "--bool"
|
||||||
|
or "--int"."""
|
||||||
|
if non_string_options is None:
|
||||||
|
non_string_options = {}
|
||||||
|
out = {}
|
||||||
|
for entry in run("git", "config", "--list", "--null").split("\0"):
|
||||||
|
if entry:
|
||||||
|
if "\n" in entry:
|
||||||
|
name, value = entry.split("\n", 1)
|
||||||
|
else:
|
||||||
|
# A setting with no '=' ('\n' with --null) is implicitly 'true'
|
||||||
|
name = entry
|
||||||
|
value = "true"
|
||||||
|
if name in non_string_options:
|
||||||
|
value = run("git", "config", non_string_options[name], name)
|
||||||
|
out[name] = value
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def interpret_args(args, dash_dash, default_commit):
|
||||||
|
"""Interpret `args` as "[commits] [--] [files]" and return (commits, files).
|
||||||
|
|
||||||
|
It is assumed that "--" and everything that follows has been removed from
|
||||||
|
args and placed in `dash_dash`.
|
||||||
|
|
||||||
|
If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its
|
||||||
|
left (if present) are taken as commits. Otherwise, the arguments are
|
||||||
|
checked from left to right if they are commits or files. If commits are not
|
||||||
|
given, a list with `default_commit` is used."""
|
||||||
|
if dash_dash:
|
||||||
|
if len(args) == 0:
|
||||||
|
commits = [default_commit]
|
||||||
|
else:
|
||||||
|
commits = args
|
||||||
|
for commit in commits:
|
||||||
|
object_type = get_object_type(commit)
|
||||||
|
if object_type not in ("commit", "tag"):
|
||||||
|
if object_type is None:
|
||||||
|
die("'%s' is not a commit" % commit)
|
||||||
|
else:
|
||||||
|
die(
|
||||||
|
"'%s' is a %s, but a commit was expected"
|
||||||
|
% (commit, object_type)
|
||||||
|
)
|
||||||
|
files = dash_dash[1:]
|
||||||
|
elif args:
|
||||||
|
commits = []
|
||||||
|
while args:
|
||||||
|
if not disambiguate_revision(args[0]):
|
||||||
|
break
|
||||||
|
commits.append(args.pop(0))
|
||||||
|
if not commits:
|
||||||
|
commits = [default_commit]
|
||||||
|
files = args
|
||||||
|
else:
|
||||||
|
commits = [default_commit]
|
||||||
|
files = []
|
||||||
|
return commits, files
|
||||||
|
|
||||||
|
|
||||||
|
def disambiguate_revision(value):
|
||||||
|
"""Returns True if `value` is a revision, False if it is a file, or dies."""
|
||||||
|
# If `value` is ambiguous (neither a commit nor a file), the following
|
||||||
|
# command will die with an appropriate error message.
|
||||||
|
run("git", "rev-parse", value, verbose=False)
|
||||||
|
object_type = get_object_type(value)
|
||||||
|
if object_type is None:
|
||||||
|
return False
|
||||||
|
if object_type in ("commit", "tag"):
|
||||||
|
return True
|
||||||
|
die("`%s` is a %s, but a commit or filename was expected" % (value, object_type))
|
||||||
|
|
||||||
|
|
||||||
|
def get_object_type(value):
|
||||||
|
"""Returns a string description of an object's type, or None if it is not
|
||||||
|
a valid git object."""
|
||||||
|
cmd = ["git", "cat-file", "-t", value]
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
if p.returncode != 0:
|
||||||
|
return None
|
||||||
|
return convert_string(stdout.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit):
|
||||||
|
"""Calls compute_diff() followed by extract_lines()."""
|
||||||
|
diff_process = compute_diff(commits, files, staged, diff_common_commit)
|
||||||
|
changed_lines = extract_lines(diff_process.stdout)
|
||||||
|
diff_process.stdout.close()
|
||||||
|
diff_process.wait()
|
||||||
|
if diff_process.returncode != 0:
|
||||||
|
# Assume error was already printed to stderr.
|
||||||
|
sys.exit(2)
|
||||||
|
return changed_lines
|
||||||
|
|
||||||
|
|
||||||
|
def compute_diff(commits, files, staged, diff_common_commit):
|
||||||
|
"""Return a subprocess object producing the diff from `commits`.
|
||||||
|
|
||||||
|
The return value's `stdin` file object will produce a patch with the
|
||||||
|
differences between the working directory (or stage if --staged is used) and
|
||||||
|
the first commit if a single one was specified, or the difference between
|
||||||
|
both specified commits, filtered on `files` (if non-empty).
|
||||||
|
Zero context lines are used in the patch."""
|
||||||
|
git_tool = "diff-index"
|
||||||
|
extra_args = []
|
||||||
|
if len(commits) == 2:
|
||||||
|
git_tool = "diff-tree"
|
||||||
|
if diff_common_commit:
|
||||||
|
commits = [f"{commits[0]}...{commits[1]}"]
|
||||||
|
elif staged:
|
||||||
|
extra_args += ["--cached"]
|
||||||
|
|
||||||
|
cmd = ["git", git_tool, "-p", "-U0"] + extra_args + commits + ["--"]
|
||||||
|
cmd.extend(files)
|
||||||
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
p.stdin.close()
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def extract_lines(patch_file):
|
||||||
|
"""Extract the changed lines in `patch_file`.
|
||||||
|
|
||||||
|
The return value is a dictionary mapping filename to a list of (start_line,
|
||||||
|
line_count) pairs.
|
||||||
|
|
||||||
|
The input must have been produced with ``-U0``, meaning unidiff format with
|
||||||
|
zero lines of context. The return value is a dict mapping filename to a
|
||||||
|
list of line `Range`s."""
|
||||||
|
matches = {}
|
||||||
|
for line in patch_file:
|
||||||
|
line = convert_string(line)
|
||||||
|
match = re.search(r"^\+\+\+\ [^/]+/(.*)", line)
|
||||||
|
if match:
|
||||||
|
filename = match.group(1).rstrip("\r\n\t")
|
||||||
|
match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line)
|
||||||
|
if match:
|
||||||
|
start_line = int(match.group(1))
|
||||||
|
line_count = 1
|
||||||
|
if match.group(3):
|
||||||
|
line_count = int(match.group(3))
|
||||||
|
if line_count == 0:
|
||||||
|
line_count = 1
|
||||||
|
if start_line == 0:
|
||||||
|
continue
|
||||||
|
matches.setdefault(filename, []).append(Range(start_line, line_count))
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
|
def filter_by_extension(dictionary, allowed_extensions):
|
||||||
|
"""Delete every key in `dictionary` that doesn't have an allowed extension.
|
||||||
|
|
||||||
|
`allowed_extensions` must be a collection of lowercase file extensions,
|
||||||
|
excluding the period."""
|
||||||
|
allowed_extensions = frozenset(allowed_extensions)
|
||||||
|
for filename in list(dictionary.keys()):
|
||||||
|
base_ext = filename.rsplit(".", 1)
|
||||||
|
if len(base_ext) == 1 and "" in allowed_extensions:
|
||||||
|
continue
|
||||||
|
if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
|
||||||
|
del dictionary[filename]
|
||||||
|
|
||||||
|
|
||||||
|
def filter_symlinks(dictionary):
|
||||||
|
"""Delete every key in `dictionary` that is a symlink."""
|
||||||
|
for filename in list(dictionary.keys()):
|
||||||
|
if os.path.islink(filename):
|
||||||
|
del dictionary[filename]
|
||||||
|
|
||||||
|
|
||||||
|
def filter_ignored_files(dictionary, binary):
|
||||||
|
"""Delete every key in `dictionary` that is ignored by clang-format."""
|
||||||
|
ignored_files = run(binary, "-list-ignored", *dictionary.keys())
|
||||||
|
if not ignored_files:
|
||||||
|
return
|
||||||
|
ignored_files = ignored_files.split("\n")
|
||||||
|
for filename in ignored_files:
|
||||||
|
del dictionary[filename]
|
||||||
|
|
||||||
|
|
||||||
|
def cd_to_toplevel():
|
||||||
|
"""Change to the top level of the git repository."""
|
||||||
|
toplevel = run("git", "rev-parse", "--show-toplevel")
|
||||||
|
os.chdir(toplevel)
|
||||||
|
|
||||||
|
|
||||||
|
def create_tree_from_workdir(filenames):
|
||||||
|
"""Create a new git tree with the given files from the working directory.
|
||||||
|
|
||||||
|
Returns the object ID (SHA-1) of the created tree."""
|
||||||
|
return create_tree(filenames, "--stdin")
|
||||||
|
|
||||||
|
|
||||||
|
def create_tree_from_index(filenames):
|
||||||
|
# Copy the environment, because the files have to be read from the original
|
||||||
|
# index.
|
||||||
|
env = os.environ.copy()
|
||||||
|
|
||||||
|
def index_contents_generator():
|
||||||
|
for filename in filenames:
|
||||||
|
git_ls_files_cmd = [
|
||||||
|
"git",
|
||||||
|
"ls-files",
|
||||||
|
"--stage",
|
||||||
|
"-z",
|
||||||
|
"--",
|
||||||
|
filename,
|
||||||
|
]
|
||||||
|
git_ls_files = subprocess.Popen(
|
||||||
|
git_ls_files_cmd,
|
||||||
|
env=env,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
stdout = git_ls_files.communicate()[0]
|
||||||
|
yield convert_string(stdout.split(b"\0")[0])
|
||||||
|
|
||||||
|
return create_tree(index_contents_generator(), "--index-info")
|
||||||
|
|
||||||
|
|
||||||
|
def run_clang_format_and_save_to_tree(
|
||||||
|
changed_lines, revision=None, binary="clang-format", style=None
|
||||||
|
):
|
||||||
|
"""Run clang-format on each file and save the result to a git tree.
|
||||||
|
|
||||||
|
Returns the object ID (SHA-1) of the created tree."""
|
||||||
|
# Copy the environment when formatting the files in the index, because the
|
||||||
|
# files have to be read from the original index.
|
||||||
|
env = os.environ.copy() if revision == "" else None
|
||||||
|
|
||||||
|
def iteritems(container):
|
||||||
|
try:
|
||||||
|
return container.iteritems() # Python 2
|
||||||
|
except AttributeError:
|
||||||
|
return container.items() # Python 3
|
||||||
|
|
||||||
|
def index_info_generator():
|
||||||
|
for filename, line_ranges in iteritems(changed_lines):
|
||||||
|
if revision is not None:
|
||||||
|
if len(revision) > 0:
|
||||||
|
git_metadata_cmd = [
|
||||||
|
"git",
|
||||||
|
"ls-tree",
|
||||||
|
"%s:%s" % (revision, os.path.dirname(filename)),
|
||||||
|
os.path.basename(filename),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
git_metadata_cmd = [
|
||||||
|
"git",
|
||||||
|
"ls-files",
|
||||||
|
"--stage",
|
||||||
|
"--",
|
||||||
|
filename,
|
||||||
|
]
|
||||||
|
git_metadata = subprocess.Popen(
|
||||||
|
git_metadata_cmd,
|
||||||
|
env=env,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
stdout = git_metadata.communicate()[0]
|
||||||
|
mode = oct(int(stdout.split()[0], 8))
|
||||||
|
else:
|
||||||
|
mode = oct(os.stat(filename).st_mode)
|
||||||
|
# Adjust python3 octal format so that it matches what git expects
|
||||||
|
if mode.startswith("0o"):
|
||||||
|
mode = "0" + mode[2:]
|
||||||
|
blob_id = clang_format_to_blob(
|
||||||
|
filename,
|
||||||
|
line_ranges,
|
||||||
|
revision=revision,
|
||||||
|
binary=binary,
|
||||||
|
style=style,
|
||||||
|
env=env,
|
||||||
|
)
|
||||||
|
yield "%s %s\t%s" % (mode, blob_id, filename)
|
||||||
|
|
||||||
|
return create_tree(index_info_generator(), "--index-info")
|
||||||
|
|
||||||
|
|
||||||
|
def create_tree(input_lines, mode):
|
||||||
|
"""Create a tree object from the given input.
|
||||||
|
|
||||||
|
If mode is '--stdin', it must be a list of filenames. If mode is
|
||||||
|
'--index-info' is must be a list of values suitable for "git update-index
|
||||||
|
--index-info", such as "<mode> <SP> <sha1> <TAB> <filename>". Any other
|
||||||
|
mode is invalid."""
|
||||||
|
assert mode in ("--stdin", "--index-info")
|
||||||
|
cmd = ["git", "update-index", "--add", "-z", mode]
|
||||||
|
with temporary_index_file():
|
||||||
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
||||||
|
for line in input_lines:
|
||||||
|
p.stdin.write(to_bytes("%s\0" % line))
|
||||||
|
p.stdin.close()
|
||||||
|
if p.wait() != 0:
|
||||||
|
die("`%s` failed" % " ".join(cmd))
|
||||||
|
tree_id = run("git", "write-tree")
|
||||||
|
return tree_id
|
||||||
|
|
||||||
|
|
||||||
|
def clang_format_to_blob(
|
||||||
|
filename,
|
||||||
|
line_ranges,
|
||||||
|
revision=None,
|
||||||
|
binary="clang-format",
|
||||||
|
style=None,
|
||||||
|
env=None,
|
||||||
|
):
|
||||||
|
"""Run clang-format on the given file and save the result to a git blob.
|
||||||
|
|
||||||
|
Runs on the file in `revision` if not None, or on the file in the working
|
||||||
|
directory if `revision` is None. Revision can be set to an empty string to
|
||||||
|
run clang-format on the file in the index.
|
||||||
|
|
||||||
|
Returns the object ID (SHA-1) of the created blob."""
|
||||||
|
clang_format_cmd = [binary]
|
||||||
|
if style:
|
||||||
|
clang_format_cmd.extend(["--style=" + style])
|
||||||
|
clang_format_cmd.extend(
|
||||||
|
[
|
||||||
|
"--lines=%s:%s" % (start_line, start_line + line_count - 1)
|
||||||
|
for start_line, line_count in line_ranges
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if revision is not None:
|
||||||
|
clang_format_cmd.extend(["--assume-filename=" + filename])
|
||||||
|
git_show_cmd = [
|
||||||
|
"git",
|
||||||
|
"cat-file",
|
||||||
|
"blob",
|
||||||
|
"%s:%s" % (revision, filename),
|
||||||
|
]
|
||||||
|
git_show = subprocess.Popen(
|
||||||
|
git_show_cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
git_show.stdin.close()
|
||||||
|
clang_format_stdin = git_show.stdout
|
||||||
|
else:
|
||||||
|
clang_format_cmd.extend([filename])
|
||||||
|
git_show = None
|
||||||
|
clang_format_stdin = subprocess.PIPE
|
||||||
|
try:
|
||||||
|
clang_format = subprocess.Popen(
|
||||||
|
clang_format_cmd, stdin=clang_format_stdin, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
if clang_format_stdin == subprocess.PIPE:
|
||||||
|
clang_format_stdin = clang_format.stdin
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
die('cannot find executable "%s"' % binary)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
clang_format_stdin.close()
|
||||||
|
hash_object_cmd = [
|
||||||
|
"git",
|
||||||
|
"hash-object",
|
||||||
|
"-w",
|
||||||
|
"--path=" + filename,
|
||||||
|
"--stdin",
|
||||||
|
]
|
||||||
|
hash_object = subprocess.Popen(
|
||||||
|
hash_object_cmd, stdin=clang_format.stdout, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
clang_format.stdout.close()
|
||||||
|
stdout = hash_object.communicate()[0]
|
||||||
|
if hash_object.returncode != 0:
|
||||||
|
die("`%s` failed" % " ".join(hash_object_cmd))
|
||||||
|
if clang_format.wait() != 0:
|
||||||
|
die("`%s` failed" % " ".join(clang_format_cmd))
|
||||||
|
if git_show and git_show.wait() != 0:
|
||||||
|
die("`%s` failed" % " ".join(git_show_cmd))
|
||||||
|
return convert_string(stdout).rstrip("\r\n")
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def temporary_index_file(tree=None):
|
||||||
|
"""Context manager for setting GIT_INDEX_FILE to a temporary file and
|
||||||
|
deleting the file afterward."""
|
||||||
|
index_path = create_temporary_index(tree)
|
||||||
|
old_index_path = os.environ.get("GIT_INDEX_FILE")
|
||||||
|
os.environ["GIT_INDEX_FILE"] = index_path
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
if old_index_path is None:
|
||||||
|
del os.environ["GIT_INDEX_FILE"]
|
||||||
|
else:
|
||||||
|
os.environ["GIT_INDEX_FILE"] = old_index_path
|
||||||
|
os.remove(index_path)
|
||||||
|
|
||||||
|
|
||||||
|
def create_temporary_index(tree=None):
|
||||||
|
"""Create a temporary index file and return the created file's path.
|
||||||
|
|
||||||
|
If `tree` is not None, use that as the tree to read in. Otherwise, an
|
||||||
|
empty index is created."""
|
||||||
|
gitdir = run("git", "rev-parse", "--git-dir")
|
||||||
|
path = os.path.join(gitdir, temp_index_basename)
|
||||||
|
if tree is None:
|
||||||
|
tree = "--empty"
|
||||||
|
run("git", "read-tree", "--index-output=" + path, tree)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def print_diff(old_tree, new_tree):
|
||||||
|
"""Print the diff between the two trees to stdout."""
|
||||||
|
# We use the porcelain 'diff' and not plumbing 'diff-tree' because the
|
||||||
|
# output is expected to be viewed by the user, and only the former does nice
|
||||||
|
# things like color and pagination.
|
||||||
|
#
|
||||||
|
# We also only print modified files since `new_tree` only contains the files
|
||||||
|
# that were modified, so unmodified files would show as deleted without the
|
||||||
|
# filter.
|
||||||
|
return subprocess.run(
|
||||||
|
["git", "diff", "--diff-filter=M", "--exit-code", old_tree, new_tree]
|
||||||
|
).returncode
|
||||||
|
|
||||||
|
|
||||||
|
def print_diffstat(old_tree, new_tree):
|
||||||
|
"""Print the diffstat between the two trees to stdout."""
|
||||||
|
# We use the porcelain 'diff' and not plumbing 'diff-tree' because the
|
||||||
|
# output is expected to be viewed by the user, and only the former does nice
|
||||||
|
# things like color and pagination.
|
||||||
|
#
|
||||||
|
# We also only print modified files since `new_tree` only contains the files
|
||||||
|
# that were modified, so unmodified files would show as deleted without the
|
||||||
|
# filter.
|
||||||
|
return subprocess.run(
|
||||||
|
[
|
||||||
|
"git",
|
||||||
|
"diff",
|
||||||
|
"--diff-filter=M",
|
||||||
|
"--exit-code",
|
||||||
|
"--stat",
|
||||||
|
old_tree,
|
||||||
|
new_tree,
|
||||||
|
]
|
||||||
|
).returncode
|
||||||
|
|
||||||
|
|
||||||
|
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
|
||||||
|
"""Apply the changes in `new_tree` to the working directory.
|
||||||
|
|
||||||
|
Bails if there are local changes in those files and not `force`. If
|
||||||
|
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
|
||||||
|
changed_files = (
|
||||||
|
run(
|
||||||
|
"git",
|
||||||
|
"diff-tree",
|
||||||
|
"--diff-filter=M",
|
||||||
|
"-r",
|
||||||
|
"-z",
|
||||||
|
"--name-only",
|
||||||
|
old_tree,
|
||||||
|
new_tree,
|
||||||
|
)
|
||||||
|
.rstrip("\0")
|
||||||
|
.split("\0")
|
||||||
|
)
|
||||||
|
if not force:
|
||||||
|
unstaged_files = run("git", "diff-files", "--name-status", *changed_files)
|
||||||
|
if unstaged_files:
|
||||||
|
print(
|
||||||
|
"The following files would be modified but have unstaged changes:",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
print(unstaged_files, file=sys.stderr)
|
||||||
|
print("Please commit, stage, or stash them first.", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
if patch_mode:
|
||||||
|
# In patch mode, we could just as well create an index from the new tree
|
||||||
|
# and checkout from that, but then the user will be presented with a
|
||||||
|
# message saying "Discard ... from worktree". Instead, we use the old
|
||||||
|
# tree as the index and checkout from new_tree, which gives the slightly
|
||||||
|
# better message, "Apply ... to index and worktree". This is not quite
|
||||||
|
# right, since it won't be applied to the user's index, but oh well.
|
||||||
|
with temporary_index_file(old_tree):
|
||||||
|
subprocess.run(["git", "checkout", "--patch", new_tree], check=True)
|
||||||
|
index_tree = old_tree
|
||||||
|
else:
|
||||||
|
with temporary_index_file(new_tree):
|
||||||
|
run("git", "checkout-index", "-f", "--", *changed_files)
|
||||||
|
return changed_files
|
||||||
|
|
||||||
|
|
||||||
|
def run(*args, **kwargs):
|
||||||
|
stdin = kwargs.pop("stdin", "")
|
||||||
|
verbose = kwargs.pop("verbose", True)
|
||||||
|
strip = kwargs.pop("strip", True)
|
||||||
|
for name in kwargs:
|
||||||
|
raise TypeError("run() got an unexpected keyword argument '%s'" % name)
|
||||||
|
p = subprocess.Popen(
|
||||||
|
args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
stdout, stderr = p.communicate(input=stdin)
|
||||||
|
|
||||||
|
stdout = convert_string(stdout)
|
||||||
|
stderr = convert_string(stderr)
|
||||||
|
|
||||||
|
if p.returncode == 0:
|
||||||
|
if stderr:
|
||||||
|
if verbose:
|
||||||
|
print("`%s` printed to stderr:" % " ".join(args), file=sys.stderr)
|
||||||
|
print(stderr.rstrip(), file=sys.stderr)
|
||||||
|
if strip:
|
||||||
|
stdout = stdout.rstrip("\r\n")
|
||||||
|
return stdout
|
||||||
|
if verbose:
|
||||||
|
print("`%s` returned %s" % (" ".join(args), p.returncode), file=sys.stderr)
|
||||||
|
if stderr:
|
||||||
|
print(stderr.rstrip(), file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
def die(message):
|
||||||
|
print("error:", message, file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
def to_bytes(str_input):
|
||||||
|
# Encode to UTF-8 to get binary data.
|
||||||
|
if isinstance(str_input, bytes):
|
||||||
|
return str_input
|
||||||
|
return str_input.encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def to_string(bytes_input):
|
||||||
|
if isinstance(bytes_input, str):
|
||||||
|
return bytes_input
|
||||||
|
return bytes_input.encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def convert_string(bytes_input):
|
||||||
|
try:
|
||||||
|
return to_string(bytes_input.decode("utf-8"))
|
||||||
|
except AttributeError: # 'str' object has no attribute 'decode'.
|
||||||
|
return str(bytes_input)
|
||||||
|
except UnicodeError:
|
||||||
|
return str(bytes_input)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
216
frontend/src/common/prettier/plugins/clang/index.ts
Normal file
216
frontend/src/common/prettier/plugins/clang/index.ts
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for C/C++/C#/Java/Protobuf formatting using clang-format WebAssembly
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting multiple languages using the clang-format WASM implementation.
|
||||||
|
* Supported languages:
|
||||||
|
* - C / C++
|
||||||
|
* - Objective-C / Objective-C++
|
||||||
|
* - C#
|
||||||
|
* - Java
|
||||||
|
* - Protocol Buffer (Protobuf)
|
||||||
|
*
|
||||||
|
* It supports various file extensions and common clang-format styles.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer } from 'prettier';
|
||||||
|
|
||||||
|
// Import the clang-format WASM module
|
||||||
|
import clangFormatInit, { format } from './clang-format-vite.js';
|
||||||
|
|
||||||
|
const parserName = 'clang-format';
|
||||||
|
|
||||||
|
// Language configuration
|
||||||
|
const languages = [
|
||||||
|
{
|
||||||
|
name: 'C',
|
||||||
|
aliases: ['c'],
|
||||||
|
parsers: ['c'],
|
||||||
|
extensions: ['.c', '.h'],
|
||||||
|
filenames: ['*.c', '*.h'],
|
||||||
|
aceMode: 'c_cpp',
|
||||||
|
tmScope: 'source.c',
|
||||||
|
linguistLanguageId: 50,
|
||||||
|
vscodeLanguageIds: ['c']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'C++',
|
||||||
|
aliases: ['cpp', 'cxx', 'cc'],
|
||||||
|
parsers: ['cpp'],
|
||||||
|
extensions: ['.cpp', '.cxx', '.cc', '.hpp', '.hxx', '.hh', '.C', '.H'],
|
||||||
|
filenames: ['*.cpp', '*.cxx', '*.cc', '*.hpp', '*.hxx', '*.hh', '*.C', '*.H'],
|
||||||
|
aceMode: 'c_cpp',
|
||||||
|
tmScope: 'source.cpp',
|
||||||
|
linguistLanguageId: 43,
|
||||||
|
vscodeLanguageIds: ['cpp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Objective-C',
|
||||||
|
aliases: ['objc', 'objectivec'],
|
||||||
|
parsers: ['objective-c'],
|
||||||
|
extensions: ['.m'],
|
||||||
|
filenames: ['*.m'],
|
||||||
|
aceMode: 'objectivec',
|
||||||
|
tmScope: 'source.objc',
|
||||||
|
linguistLanguageId: 259,
|
||||||
|
vscodeLanguageIds: ['objective-c']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Objective-C++',
|
||||||
|
aliases: ['objcpp', 'objectivecpp'],
|
||||||
|
parsers: ['objective-cpp'],
|
||||||
|
extensions: ['.mm'],
|
||||||
|
filenames: ['*.mm'],
|
||||||
|
aceMode: 'objectivec',
|
||||||
|
tmScope: 'source.objcpp',
|
||||||
|
linguistLanguageId: 260,
|
||||||
|
vscodeLanguageIds: ['objective-cpp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'C#',
|
||||||
|
aliases: ['csharp', 'cs'],
|
||||||
|
parsers: ['cs'],
|
||||||
|
extensions: ['.cs'],
|
||||||
|
filenames: ['*.cs'],
|
||||||
|
aceMode: 'csharp',
|
||||||
|
tmScope: 'source.cs',
|
||||||
|
linguistLanguageId: 42,
|
||||||
|
vscodeLanguageIds: ['csharp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Java',
|
||||||
|
aliases: ['java'],
|
||||||
|
parsers: ['java'],
|
||||||
|
extensions: ['.java'],
|
||||||
|
filenames: ['*.java'],
|
||||||
|
aceMode: 'java',
|
||||||
|
tmScope: 'source.java',
|
||||||
|
linguistLanguageId: 181,
|
||||||
|
vscodeLanguageIds: ['java']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Protocol Buffer',
|
||||||
|
aliases: ['protobuf', 'proto'],
|
||||||
|
parsers: ['proto'],
|
||||||
|
extensions: ['.proto'],
|
||||||
|
filenames: ['*.proto'],
|
||||||
|
aceMode: 'protobuf',
|
||||||
|
tmScope: 'source.proto',
|
||||||
|
linguistLanguageId: 297,
|
||||||
|
vscodeLanguageIds: ['proto']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Parser configuration
|
||||||
|
const clangParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (node: string) => node.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lazy initialize clang-format WASM module
|
||||||
|
let initPromise: Promise<void> | null = null;
|
||||||
|
let isInitialized = false;
|
||||||
|
|
||||||
|
function initClangFormat(): Promise<void> {
|
||||||
|
if (isInitialized) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initPromise) {
|
||||||
|
initPromise = (async () => {
|
||||||
|
try {
|
||||||
|
await clangFormatInit();
|
||||||
|
isInitialized = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to initialize clang-format WASM module:', error);
|
||||||
|
initPromise = null;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printer configuration
|
||||||
|
const clangPrinter: Printer<string> = {
|
||||||
|
// @ts-expect-error -- Support async printer like shell plugin
|
||||||
|
async print(path, options) {
|
||||||
|
try {
|
||||||
|
// Wait for initialization to complete
|
||||||
|
await initClangFormat();
|
||||||
|
|
||||||
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
const style = getClangStyle(options);
|
||||||
|
|
||||||
|
// Format using clang-format (synchronous call)
|
||||||
|
const formatted = format(text, options.filename, style);
|
||||||
|
|
||||||
|
return formatted.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('clang-format failed:', error);
|
||||||
|
// Return original text if formatting fails
|
||||||
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function to determine clang-format style
|
||||||
|
function getClangStyle(options: any): string {
|
||||||
|
// You can extend this to support more options
|
||||||
|
const style = options.clangStyle || 'LLVM';
|
||||||
|
|
||||||
|
// Support common styles
|
||||||
|
const validStyles = ['LLVM', 'Google', 'Chromium', 'Mozilla', 'WebKit', 'Microsoft', 'GNU'];
|
||||||
|
if (validStyles.includes(style)) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to LLVM style
|
||||||
|
return 'LLVM';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin options
|
||||||
|
const options = {
|
||||||
|
clangStyle: {
|
||||||
|
since: '0.0.1',
|
||||||
|
category: 'Format' as const,
|
||||||
|
type: 'choice' as const,
|
||||||
|
default: 'LLVM',
|
||||||
|
description: 'The clang-format style to use',
|
||||||
|
choices: [
|
||||||
|
{ value: 'LLVM', description: 'LLVM coding standards' },
|
||||||
|
{ value: 'Google', description: "Google's C++ style guide" },
|
||||||
|
{ value: 'Chromium', description: "Chromium's style guide" },
|
||||||
|
{ value: 'Mozilla', description: "Mozilla's style guide" },
|
||||||
|
{ value: 'WebKit', description: "WebKit's style guide" },
|
||||||
|
{ value: 'Microsoft', description: "Microsoft's style guide" },
|
||||||
|
{ value: 'GNU', description: 'GNU coding standards' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
filename: {
|
||||||
|
// since: '0.1.0',
|
||||||
|
category: 'Config',
|
||||||
|
type: 'string',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Custom filename to use for web_fmt processing (affects language detection)',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Plugin object
|
||||||
|
const clangPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers: {
|
||||||
|
[parserName]: clangParser,
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
[parserName]: clangPrinter,
|
||||||
|
},
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default clangPlugin;
|
||||||
|
export { languages };
|
||||||
|
export const parsers = clangPlugin.parsers;
|
||||||
|
export const printers = clangPlugin.printers;
|
||||||
105
frontend/src/common/prettier/plugins/clang/src/CMakeLists.txt
Normal file
105
frontend/src/common/prettier/plugins/clang/src/CMakeLists.txt
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
project(clang-format-wasm)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Set Emscripten flags for WASM
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
set(CMAKE_EXECUTABLE_SUFFIX ".js")
|
||||||
|
|
||||||
|
# Common Emscripten flags
|
||||||
|
set(EMSCRIPTEN_FLAGS
|
||||||
|
-O3
|
||||||
|
-sWASM=1
|
||||||
|
-sEXPORTED_RUNTIME_METHODS=['ccall','cwrap']
|
||||||
|
-sALLOW_MEMORY_GROWTH=1
|
||||||
|
-sMODULARIZE=1
|
||||||
|
-sEXPORT_NAME='Module'
|
||||||
|
-sENVIRONMENT=web,webview,worker
|
||||||
|
-sUSE_ES6_IMPORT_META=0
|
||||||
|
--no-entry
|
||||||
|
)
|
||||||
|
|
||||||
|
# Library-specific flags
|
||||||
|
set(LIB_EMSCRIPTEN_FLAGS
|
||||||
|
${EMSCRIPTEN_FLAGS}
|
||||||
|
-sEXPORTED_FUNCTIONS=['_malloc','_free']
|
||||||
|
--bind
|
||||||
|
)
|
||||||
|
|
||||||
|
# CLI-specific flags
|
||||||
|
set(CLI_EMSCRIPTEN_FLAGS
|
||||||
|
${EMSCRIPTEN_FLAGS}
|
||||||
|
-sEXPORTED_FUNCTIONS=['_main']
|
||||||
|
-sINVOKE_RUN=0
|
||||||
|
-sNODERAWFS=1
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find LLVM
|
||||||
|
find_package(LLVM REQUIRED CONFIG)
|
||||||
|
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||||
|
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||||
|
|
||||||
|
# Include LLVM headers
|
||||||
|
include_directories(${LLVM_INCLUDE_DIRS})
|
||||||
|
add_definitions(${LLVM_DEFINITIONS})
|
||||||
|
|
||||||
|
# Find Clang
|
||||||
|
find_package(Clang REQUIRED CONFIG)
|
||||||
|
|
||||||
|
# Get LLVM components
|
||||||
|
llvm_map_components_to_libnames(llvm_libs support core)
|
||||||
|
|
||||||
|
# Define source files
|
||||||
|
set(LIB_SOURCES
|
||||||
|
lib.cc
|
||||||
|
lib.h
|
||||||
|
binding.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CLI_SOURCES
|
||||||
|
cli.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create library target
|
||||||
|
add_executable(clang-format-wasm ${LIB_SOURCES})
|
||||||
|
|
||||||
|
# Link against Clang and LLVM libraries
|
||||||
|
target_link_libraries(clang-format-wasm
|
||||||
|
clangFormat
|
||||||
|
clangToolingCore
|
||||||
|
clangBasic
|
||||||
|
clangRewrite
|
||||||
|
${llvm_libs}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create CLI target
|
||||||
|
add_executable(clang-format-cli ${CLI_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(clang-format-cli
|
||||||
|
clangFormat
|
||||||
|
clangToolingCore
|
||||||
|
clangBasic
|
||||||
|
clangRewrite
|
||||||
|
${llvm_libs}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set Emscripten flags
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
# Configure library target
|
||||||
|
set_target_properties(clang-format-wasm PROPERTIES
|
||||||
|
COMPILE_FLAGS "${LIB_EMSCRIPTEN_FLAGS}"
|
||||||
|
LINK_FLAGS "${LIB_EMSCRIPTEN_FLAGS}"
|
||||||
|
OUTPUT_NAME "clang-format-esm"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configure CLI target
|
||||||
|
set_target_properties(clang-format-cli PROPERTIES
|
||||||
|
COMPILE_FLAGS "${CLI_EMSCRIPTEN_FLAGS}"
|
||||||
|
LINK_FLAGS "${CLI_EMSCRIPTEN_FLAGS}"
|
||||||
|
OUTPUT_NAME "clang-format-cli"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
#include "CustomFileSystem.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace llvm::vfs;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool isRunningOnWindows() {
|
||||||
|
return EM_ASM_INT({return process.platform == 'win32' ? 1 : 0}) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code current_path(SmallVectorImpl<char> &result) {
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
const char *pwd = ::getenv("PWD");
|
||||||
|
result.append(pwd, pwd + strlen(pwd));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace vfs {
|
||||||
|
|
||||||
|
sys::path::Style getPathStyle() {
|
||||||
|
static sys::path::Style cachedStyle = sys::path::Style::native;
|
||||||
|
|
||||||
|
if (cachedStyle == sys::path::Style::native) {
|
||||||
|
cachedStyle = isRunningOnWindows() ? sys::path::Style::windows
|
||||||
|
: sys::path::Style::posix;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_absolute(const Twine ¤t_directory,
|
||||||
|
SmallVectorImpl<char> &path) {
|
||||||
|
StringRef p(path.data(), path.size());
|
||||||
|
|
||||||
|
auto pathStyle = getPathStyle();
|
||||||
|
|
||||||
|
bool rootDirectory = sys::path::has_root_directory(p, pathStyle);
|
||||||
|
bool rootName = sys::path::has_root_name(p, pathStyle);
|
||||||
|
|
||||||
|
// Already absolute.
|
||||||
|
if ((rootName || is_style_posix(pathStyle)) && rootDirectory)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// All of the following conditions will need the current directory.
|
||||||
|
SmallString<128> current_dir;
|
||||||
|
current_directory.toVector(current_dir);
|
||||||
|
|
||||||
|
// Relative path. Prepend the current directory.
|
||||||
|
if (!rootName && !rootDirectory) {
|
||||||
|
// Append path to the current directory.
|
||||||
|
sys::path::append(current_dir, pathStyle, p);
|
||||||
|
// Set path to the result.
|
||||||
|
path.swap(current_dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rootName && rootDirectory) {
|
||||||
|
StringRef cdrn = sys::path::root_name(current_dir, pathStyle);
|
||||||
|
SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
|
||||||
|
sys::path::append(curDirRootName, pathStyle, p);
|
||||||
|
// Set path to the result.
|
||||||
|
path.swap(curDirRootName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootName && !rootDirectory) {
|
||||||
|
StringRef pRootName = sys::path::root_name(p, pathStyle);
|
||||||
|
StringRef bRootDirectory =
|
||||||
|
sys::path::root_directory(current_dir, pathStyle);
|
||||||
|
StringRef bRelativePath = sys::path::relative_path(current_dir, pathStyle);
|
||||||
|
StringRef pRelativePath = sys::path::relative_path(p, pathStyle);
|
||||||
|
|
||||||
|
SmallString<128> res;
|
||||||
|
sys::path::append(res, pathStyle, pRootName, bRootDirectory, bRelativePath,
|
||||||
|
pRelativePath);
|
||||||
|
path.swap(res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_unreachable("All rootName and rootDirectory combinations should have "
|
||||||
|
"occurred above!");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code make_absolute(SmallVectorImpl<char> &path) {
|
||||||
|
if (sys::path::is_absolute(path, getPathStyle()))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
SmallString<128> current_dir;
|
||||||
|
if (std::error_code ec = current_path(current_dir))
|
||||||
|
return ec;
|
||||||
|
|
||||||
|
make_absolute(current_dir, path);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomFileSystem::CustomFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
|
||||||
|
: ProxyFileSystem(std::move(FS)) {}
|
||||||
|
|
||||||
|
std::error_code
|
||||||
|
CustomFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
|
||||||
|
return make_absolute(Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vfs
|
||||||
|
} // namespace llvm
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef CUSTOM_FILE_SYSTEM_H
|
||||||
|
#define CUSTOM_FILE_SYSTEM_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/Support/ErrorOr.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
#include "llvm/Support/VirtualFileSystem.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace vfs {
|
||||||
|
|
||||||
|
sys::path::Style getPathStyle();
|
||||||
|
std::error_code make_absolute(SmallVectorImpl<char> &path);
|
||||||
|
|
||||||
|
class CustomFileSystem : public ProxyFileSystem {
|
||||||
|
public:
|
||||||
|
CustomFileSystem(IntrusiveRefCntPtr<FileSystem> FS);
|
||||||
|
|
||||||
|
std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vfs
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
|
#endif // CUSTOM_FILE_SYSTEM_H
|
||||||
100
frontend/src/common/prettier/plugins/clang/src/README.md
Normal file
100
frontend/src/common/prettier/plugins/clang/src/README.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Clang Format WASM Plugin
|
||||||
|
|
||||||
|
这是一个基于 clang-format WebAssembly 的 Prettier 插件,支持格式化 C/C++/C#/Java/Protobuf 代码。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
clang/
|
||||||
|
├── src/ # 源码目录
|
||||||
|
│ ├── scripts/ # 构建和工具脚本
|
||||||
|
│ │ ├── build.sh # 主构建脚本
|
||||||
|
│ │ ├── gen_patch.sh # 补丁生成脚本
|
||||||
|
│ │ └── cli.patch # CLI 修改补丁
|
||||||
|
│ ├── *.cc # C++ 源文件
|
||||||
|
│ ├── *.h # C++ 头文件
|
||||||
|
│ ├── CMakeLists.txt # CMake 构建配置
|
||||||
|
│ ├── package.json # NPM 包配置
|
||||||
|
│ ├── clang-format.d.ts # TypeScript 类型定义
|
||||||
|
│ ├── template.js # JavaScript 模板
|
||||||
|
│ └── clang-format-diff.py # Python 差异工具
|
||||||
|
├── *.js # 编译后的 JavaScript 文件
|
||||||
|
├── *.wasm # 编译后的 WebAssembly 文件
|
||||||
|
├── *.cjs # CommonJS 格式的 CLI 工具
|
||||||
|
├── git-clang-format # Git 集成工具
|
||||||
|
└── index.ts # 插件入口文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 构建说明
|
||||||
|
|
||||||
|
### 前提条件
|
||||||
|
|
||||||
|
- Install LLVM and Clang (version 18 or later)
|
||||||
|
- Install CMake (version 3.27 or later)
|
||||||
|
- Install Ninja (version 1.11 or later)
|
||||||
|
|
||||||
|
### 构建步骤
|
||||||
|
|
||||||
|
1. Clone this repository
|
||||||
|
|
||||||
|
2. 进入源码目录:
|
||||||
|
```bash
|
||||||
|
cd src
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 运行构建脚本:
|
||||||
|
```bash
|
||||||
|
./scripts/build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
构建脚本会:
|
||||||
|
- 创建 `build` 目录并编译源码
|
||||||
|
- 将编译结果复制到上级目录(插件目录)
|
||||||
|
- 生成 WebAssembly 文件和 JavaScript 绑定
|
||||||
|
- 复制必要的工具和类型定义文件
|
||||||
|
|
||||||
|
### 输出文件
|
||||||
|
|
||||||
|
构建完成后,插件目录下会包含:
|
||||||
|
- `clang-format.wasm` - WebAssembly 库文件
|
||||||
|
- `clang-format.js` - JavaScript 绑定文件
|
||||||
|
- `clang-format-cli.cjs` - CLI 工具
|
||||||
|
- `clang-format-cli.wasm` - CLI WebAssembly 文件
|
||||||
|
- `git-clang-format` - Git 集成工具
|
||||||
|
- `clang-format-diff.py` - 差异工具
|
||||||
|
|
||||||
|
## 开发说明
|
||||||
|
|
||||||
|
### 修改源码
|
||||||
|
|
||||||
|
- C++ 源文件位于 `src/` 目录下
|
||||||
|
- 修改后运行 `./scripts/build.sh` 重新构建
|
||||||
|
- 类型定义文件 `src/clang-format.d.ts` 需要与实际 API 保持同步
|
||||||
|
|
||||||
|
### 生成补丁
|
||||||
|
|
||||||
|
如果修改了 CLI 相关代码,可以使用:
|
||||||
|
```bash
|
||||||
|
./scripts/gen_patch.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
生成补丁文件 `scripts/cli.patch`。
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
插件会自动加载编译后的 WebAssembly 文件,支持以下语言:
|
||||||
|
- C/C++
|
||||||
|
- Objective-C/C++
|
||||||
|
- C#
|
||||||
|
- Java
|
||||||
|
- Protocol Buffer
|
||||||
|
|
||||||
|
支持的 clang-format 样式:
|
||||||
|
- LLVM
|
||||||
|
- Google
|
||||||
|
- Chromium
|
||||||
|
- Mozilla
|
||||||
|
- WebKit
|
||||||
|
- Microsoft
|
||||||
|
- GNU
|
||||||
|
- 自定义样式
|
||||||
26
frontend/src/common/prettier/plugins/clang/src/binding.cc
Normal file
26
frontend/src/common/prettier/plugins/clang/src/binding.cc
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "lib.h"
|
||||||
|
#include <emscripten/bind.h>
|
||||||
|
|
||||||
|
using namespace emscripten;
|
||||||
|
|
||||||
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
|
register_vector<unsigned>("RangeList");
|
||||||
|
|
||||||
|
value_object<Result>("Result")
|
||||||
|
.field("error", &Result::error)
|
||||||
|
.field("content", &Result::content);
|
||||||
|
|
||||||
|
function<std::string>("version", &version);
|
||||||
|
function<Result, const std::string, const std::string, const std::string>(
|
||||||
|
"format", &format);
|
||||||
|
function<Result, const std::string, const std::string, const std::string,
|
||||||
|
const std::vector<unsigned>>("format_byte", &format_byte);
|
||||||
|
function<Result, const std::string, const std::string, const std::string,
|
||||||
|
const std::vector<unsigned>>("format_line", &format_line);
|
||||||
|
function<void, const std::string>("set_fallback_style", &set_fallback_style);
|
||||||
|
function<void, bool>("set_sort_includes", &set_sort_includes);
|
||||||
|
function<Result, const std::string, const std::string, const std::string>(
|
||||||
|
"dump_config", &dump_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# ===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- python -*--===#
|
||||||
|
#
|
||||||
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
# See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
#
|
||||||
|
# ===------------------------------------------------------------------------===#
|
||||||
|
|
||||||
|
"""
|
||||||
|
This script reads input from a unified diff and reformats all the changed
|
||||||
|
lines. This is useful to reformat all the lines touched by a specific patch.
|
||||||
|
Example usage for git/svn users:
|
||||||
|
|
||||||
|
git diff -U0 --no-color --relative HEAD^ | {clang_format_diff} -p1 -i
|
||||||
|
svn diff --diff-cmd=diff -x-U0 | {clang_format_diff} -i
|
||||||
|
|
||||||
|
It should be noted that the filename contained in the diff is used unmodified
|
||||||
|
to determine the source file to update. Users calling this script directly
|
||||||
|
should be careful to ensure that the path in the diff is correct relative to the
|
||||||
|
current working directory.
|
||||||
|
"""
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import difflib
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info.major >= 3:
|
||||||
|
from io import StringIO
|
||||||
|
else:
|
||||||
|
from io import BytesIO as StringIO
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description=__doc__.format(clang_format_diff="%(prog)s"),
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-i",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="apply edits to files instead of displaying a diff",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-p",
|
||||||
|
metavar="NUM",
|
||||||
|
default=0,
|
||||||
|
help="strip the smallest prefix containing P slashes",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-regex",
|
||||||
|
metavar="PATTERN",
|
||||||
|
default=None,
|
||||||
|
help="custom pattern selecting file paths to reformat "
|
||||||
|
"(case sensitive, overrides -iregex)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-iregex",
|
||||||
|
metavar="PATTERN",
|
||||||
|
default=r".*\.(?:cpp|cc|c\+\+|cxx|cppm|ccm|cxxm|c\+\+m|c|cl|h|hh|hpp"
|
||||||
|
r"|hxx|m|mm|inc|js|ts|proto|protodevel|java|cs|json|ipynb|s?vh?)",
|
||||||
|
help="custom pattern selecting file paths to reformat "
|
||||||
|
"(case insensitive, overridden by -regex)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-sort-includes",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="let clang-format sort include blocks",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
action="store_true",
|
||||||
|
help="be more verbose, ineffective without -i",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-style",
|
||||||
|
help="formatting style to apply (LLVM, GNU, Google, Chromium, "
|
||||||
|
"Microsoft, Mozilla, WebKit)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-fallback-style",
|
||||||
|
help="The name of the predefined style used as a"
|
||||||
|
"fallback in case clang-format is invoked with"
|
||||||
|
"-style=file, but can not find the .clang-format"
|
||||||
|
"file to use.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-binary",
|
||||||
|
default="clang-format",
|
||||||
|
help="location of binary to use for clang-format",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Extract changed lines for each file.
|
||||||
|
filename = None
|
||||||
|
lines_by_file = {}
|
||||||
|
for line in sys.stdin:
|
||||||
|
match = re.search(r"^\+\+\+\ (.*?/){%s}(.+)" % args.p, line.rstrip())
|
||||||
|
if match:
|
||||||
|
filename = match.group(2)
|
||||||
|
if filename is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if args.regex is not None:
|
||||||
|
if not re.match("^%s$" % args.regex, filename):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if not re.match("^%s$" % args.iregex, filename, re.IGNORECASE):
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = re.search(r"^@@.*\+(\d+)(?:,(\d+))?", line)
|
||||||
|
if match:
|
||||||
|
start_line = int(match.group(1))
|
||||||
|
line_count = 1
|
||||||
|
if match.group(2):
|
||||||
|
line_count = int(match.group(2))
|
||||||
|
# The input is something like
|
||||||
|
#
|
||||||
|
# @@ -1, +0,0 @@
|
||||||
|
#
|
||||||
|
# which means no lines were added.
|
||||||
|
if line_count == 0:
|
||||||
|
continue
|
||||||
|
# Also format lines range if line_count is 0 in case of deleting
|
||||||
|
# surrounding statements.
|
||||||
|
end_line = start_line
|
||||||
|
if line_count != 0:
|
||||||
|
end_line += line_count - 1
|
||||||
|
lines_by_file.setdefault(filename, []).extend(
|
||||||
|
["--lines", str(start_line) + ":" + str(end_line)]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reformat files containing changes in place.
|
||||||
|
has_diff = False
|
||||||
|
for filename, lines in lines_by_file.items():
|
||||||
|
if args.i and args.verbose:
|
||||||
|
print("Formatting {}".format(filename))
|
||||||
|
command = [args.binary, filename]
|
||||||
|
if args.i:
|
||||||
|
command.append("-i")
|
||||||
|
if args.sort_includes:
|
||||||
|
command.append("--sort-includes")
|
||||||
|
command.extend(lines)
|
||||||
|
if args.style:
|
||||||
|
command.extend(["--style", args.style])
|
||||||
|
if args.fallback_style:
|
||||||
|
command.extend(["--fallback-style", args.fallback_style])
|
||||||
|
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=None,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
universal_newlines=True,
|
||||||
|
)
|
||||||
|
except OSError as e:
|
||||||
|
# Give the user more context when clang-format isn't
|
||||||
|
# found/isn't executable, etc.
|
||||||
|
raise RuntimeError(
|
||||||
|
'Failed to run "%s" - %s"' % (" ".join(command), e.strerror)
|
||||||
|
)
|
||||||
|
|
||||||
|
stdout, _stderr = p.communicate()
|
||||||
|
if p.returncode != 0:
|
||||||
|
return p.returncode
|
||||||
|
|
||||||
|
if not args.i:
|
||||||
|
with open(filename) as f:
|
||||||
|
code = f.readlines()
|
||||||
|
formatted_code = StringIO(stdout).readlines()
|
||||||
|
diff = difflib.unified_diff(
|
||||||
|
code,
|
||||||
|
formatted_code,
|
||||||
|
filename,
|
||||||
|
filename,
|
||||||
|
"(before formatting)",
|
||||||
|
"(after formatting)",
|
||||||
|
)
|
||||||
|
diff_string = "".join(diff)
|
||||||
|
if len(diff_string) > 0:
|
||||||
|
has_diff = True
|
||||||
|
sys.stdout.write(diff_string)
|
||||||
|
|
||||||
|
if has_diff:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
175
frontend/src/common/prettier/plugins/clang/src/clang-format.d.ts
vendored
Normal file
175
frontend/src/common/prettier/plugins/clang/src/clang-format.d.ts
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
export type InitInput =
|
||||||
|
| RequestInfo
|
||||||
|
| URL
|
||||||
|
| Response
|
||||||
|
| BufferSource
|
||||||
|
| WebAssembly.Module;
|
||||||
|
|
||||||
|
export default function init(input?: InitInput): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The style to use for formatting.
|
||||||
|
* Supported style values are:
|
||||||
|
* - `LLVM` - A style complying with the LLVM coding standards.
|
||||||
|
* - `Google` - A style complying with Google’s C++ style guide.
|
||||||
|
* - `Chromium` - A style complying with Chromium’s style guide.
|
||||||
|
* - `Mozilla` - A style complying with Mozilla’s style guide.
|
||||||
|
* - `WebKit` - A style complying with WebKit’s style guide.
|
||||||
|
* - `Microsoft` - A style complying with Microsoft’s style guide.
|
||||||
|
* - `GNU` - A style complying with the GNU coding standards.
|
||||||
|
* - A string starting with `{`, for example: `{BasedOnStyle: Chromium, IndentWidth: 4, ...}`.
|
||||||
|
* - A string which represents `.clang-format` content.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type Style =
|
||||||
|
| "LLVM"
|
||||||
|
| "Google"
|
||||||
|
| "Chromium"
|
||||||
|
| "Mozilla"
|
||||||
|
| "WebKit"
|
||||||
|
| "Microsoft"
|
||||||
|
| "GNU"
|
||||||
|
| (string & {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filename to use for determining the language.
|
||||||
|
*/
|
||||||
|
export type Filename =
|
||||||
|
| "main.c"
|
||||||
|
| "main.cc"
|
||||||
|
| "main.cxx"
|
||||||
|
| "main.cpp"
|
||||||
|
| "main.java"
|
||||||
|
| "main.js"
|
||||||
|
| "main.mjs"
|
||||||
|
| "main.ts"
|
||||||
|
| "main.json"
|
||||||
|
| "main.m"
|
||||||
|
| "main.mm"
|
||||||
|
| "main.proto"
|
||||||
|
| "main.cs"
|
||||||
|
| (string & {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the given content using the specified style.
|
||||||
|
*
|
||||||
|
* @param {string} content - The content to format.
|
||||||
|
* @param {Filename} filename - The filename to use for determining the language.
|
||||||
|
* @param {Style} style - The style to use for formatting.
|
||||||
|
* Supported style values are:
|
||||||
|
* - `LLVM` - A style complying with the LLVM coding standards.
|
||||||
|
* - `Google` - A style complying with Google’s C++ style guide.
|
||||||
|
* - `Chromium` - A style complying with Chromium’s style guide.
|
||||||
|
* - `Mozilla` - A style complying with Mozilla’s style guide.
|
||||||
|
* - `WebKit` - A style complying with WebKit’s style guide.
|
||||||
|
* - `Microsoft` - A style complying with Microsoft’s style guide.
|
||||||
|
* - `GNU` - A style complying with the GNU coding standards.
|
||||||
|
* - A string starting with `{`, for example: `{BasedOnStyle: Chromium, IndentWidth: 4, ...}`.
|
||||||
|
* - A string which represents `.clang-format` content.
|
||||||
|
*
|
||||||
|
* @returns {string} The formatted content.
|
||||||
|
* @throws {Error}
|
||||||
|
*
|
||||||
|
* @see {@link https://clang.llvm.org/docs/ClangFormatStyleOptions.html}
|
||||||
|
*/
|
||||||
|
export declare function format(
|
||||||
|
content: string,
|
||||||
|
filename?: Filename,
|
||||||
|
style?: Style,
|
||||||
|
): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Both the startLine and endLine are 1-based.
|
||||||
|
*/
|
||||||
|
export type LineRange = [startLine: number, endLine: number];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Both the offset and length are measured in bytes.
|
||||||
|
*/
|
||||||
|
export type ByteRange = [offset: number, length: number];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the specified range of lines in the given content using the specified style.
|
||||||
|
*
|
||||||
|
* @param {string} content - The content to format.
|
||||||
|
* @param {LineRange[]} range - Array<[startLine, endLine]> - The range of lines to format.
|
||||||
|
* Both startLine and endLine are 1-based.
|
||||||
|
* Multiple ranges can be formatted by specifying several lines arguments.
|
||||||
|
* @param {Filename} filename - The filename to use for determining the language.
|
||||||
|
* @param {Style} style - The style to use for formatting.
|
||||||
|
* Supported style values are:
|
||||||
|
* - `LLVM` - A style complying with the LLVM coding standards.
|
||||||
|
* - `Google` - A style complying with Google’s C++ style guide.
|
||||||
|
* - `Chromium` - A style complying with Chromium’s style guide.
|
||||||
|
* - `Mozilla` - A style complying with Mozilla’s style guide.
|
||||||
|
* - `WebKit` - A style complying with WebKit’s style guide.
|
||||||
|
* - `Microsoft` - A style complying with Microsoft’s style guide.
|
||||||
|
* - `GNU` - A style complying with the GNU coding standards.
|
||||||
|
* - A string starting with `{`, for example: `{BasedOnStyle: Chromium, IndentWidth: 4, ...}`.
|
||||||
|
* - A string which represents `.clang-format` content.
|
||||||
|
*
|
||||||
|
* @returns {string} The formatted content.
|
||||||
|
* @throws {Error}
|
||||||
|
*
|
||||||
|
* @see {@link https://clang.llvm.org/docs/ClangFormatStyleOptions.html}
|
||||||
|
*/
|
||||||
|
export declare function format_line_range(
|
||||||
|
content: string,
|
||||||
|
range: ByteRange[] | [[offset: number]],
|
||||||
|
filename?: Filename,
|
||||||
|
style?: Style,
|
||||||
|
): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `format_line_range` instead.
|
||||||
|
*/
|
||||||
|
export declare function formatLineRange(
|
||||||
|
content: string,
|
||||||
|
range: ByteRange[] | [[offset: number]],
|
||||||
|
filename?: Filename,
|
||||||
|
style?: Style,
|
||||||
|
): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the specified range of bytes in the given content using the specified style.
|
||||||
|
*
|
||||||
|
* @param {string} content - The content to format.
|
||||||
|
* @param {ByteRange[]} range - Array<[offset, length]> - The range of bytes to format.
|
||||||
|
* @param {Filename} filename - The filename to use for determining the language.
|
||||||
|
* @param {Style} style - The style to use for formatting.
|
||||||
|
* Supported style values are:
|
||||||
|
* - `LLVM` - A style complying with the LLVM coding standards.
|
||||||
|
* - `Google` - A style complying with Google’s C++ style guide.
|
||||||
|
* - `Chromium` - A style complying with Chromium’s style guide.
|
||||||
|
* - `Mozilla` - A style complying with Mozilla’s style guide.
|
||||||
|
* - `WebKit` - A style complying with WebKit’s style guide.
|
||||||
|
* - `Microsoft` - A style complying with Microsoft’s style guide.
|
||||||
|
* - `GNU` - A style complying with the GNU coding standards.
|
||||||
|
* - A string starting with `{`, for example: `{BasedOnStyle: Chromium, IndentWidth: 4, ...}`.
|
||||||
|
* - A string which represents `.clang-format` content.
|
||||||
|
*
|
||||||
|
* @returns {string} The formatted content.
|
||||||
|
* @throws {Error}
|
||||||
|
*
|
||||||
|
* @see {@link https://clang.llvm.org/docs/ClangFormatStyleOptions.html}
|
||||||
|
*/
|
||||||
|
export declare function format_byte_range(
|
||||||
|
content: string,
|
||||||
|
range: LineRange[],
|
||||||
|
filename?: Filename,
|
||||||
|
style?: Style,
|
||||||
|
): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `format_byte_range` instead.
|
||||||
|
*/
|
||||||
|
export declare function formatByteRange(
|
||||||
|
content: string,
|
||||||
|
range: LineRange[],
|
||||||
|
filename?: Filename,
|
||||||
|
style?: Style,
|
||||||
|
): string;
|
||||||
|
|
||||||
|
export declare function version(): string;
|
||||||
|
|
||||||
|
export declare function set_fallback_style(style: Style): void;
|
||||||
748
frontend/src/common/prettier/plugins/clang/src/cli.cc
Normal file
748
frontend/src/common/prettier/plugins/clang/src/cli.cc
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// This file implements a clang-format tool that automatically formats
|
||||||
|
/// (fragments of) C++ code.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "clang/../../lib/Format/MatchFilePath.h"
|
||||||
|
#include "clang/Basic/Diagnostic.h"
|
||||||
|
#include "clang/Basic/DiagnosticOptions.h"
|
||||||
|
#include "clang/Basic/FileManager.h"
|
||||||
|
#include "clang/Basic/SourceManager.h"
|
||||||
|
#include "clang/Basic/Version.h"
|
||||||
|
#include "clang/Format/Format.h"
|
||||||
|
#include "clang/Rewrite/Core/Rewriter.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/FileSystem.h"
|
||||||
|
#include "llvm/Support/InitLLVM.h"
|
||||||
|
#include "llvm/Support/Process.h"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "CustomFileSystem.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using clang::tooling::Replacements;
|
||||||
|
|
||||||
|
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
|
||||||
|
|
||||||
|
// Mark all our options with this category, everything else (except for -version
|
||||||
|
// and -help) will be hidden.
|
||||||
|
static cl::OptionCategory ClangFormatCategory("Clang-format options");
|
||||||
|
|
||||||
|
static cl::list<unsigned>
|
||||||
|
Offsets("offset",
|
||||||
|
cl::desc("Format a range starting at this byte offset.\n"
|
||||||
|
"Multiple ranges can be formatted by specifying\n"
|
||||||
|
"several -offset and -length pairs.\n"
|
||||||
|
"Can only be used with one input file."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::list<unsigned>
|
||||||
|
Lengths("length",
|
||||||
|
cl::desc("Format a range of this length (in bytes).\n"
|
||||||
|
"Multiple ranges can be formatted by specifying\n"
|
||||||
|
"several -offset and -length pairs.\n"
|
||||||
|
"When only a single -offset is specified without\n"
|
||||||
|
"-length, clang-format will format up to the end\n"
|
||||||
|
"of the file.\n"
|
||||||
|
"Can only be used with one input file."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::list<std::string>
|
||||||
|
LineRanges("lines",
|
||||||
|
cl::desc("<start line>:<end line> - format a range of\n"
|
||||||
|
"lines (both 1-based).\n"
|
||||||
|
"Multiple ranges can be formatted by specifying\n"
|
||||||
|
"several -lines arguments.\n"
|
||||||
|
"Can't be used with -offset and -length.\n"
|
||||||
|
"Can only be used with one input file."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::opt<std::string>
|
||||||
|
Style("style", cl::desc(clang::format::StyleOptionHelpDescription),
|
||||||
|
cl::init(clang::format::DefaultFormatStyle),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::opt<std::string>
|
||||||
|
FallbackStyle("fallback-style",
|
||||||
|
cl::desc("The name of the predefined style used as a\n"
|
||||||
|
"fallback in case clang-format is invoked with\n"
|
||||||
|
"-style=file, but can not find the .clang-format\n"
|
||||||
|
"file to use. Defaults to 'LLVM'.\n"
|
||||||
|
"Use -fallback-style=none to skip formatting."),
|
||||||
|
cl::init(clang::format::DefaultFallbackStyle),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<std::string> AssumeFileName(
|
||||||
|
"assume-filename",
|
||||||
|
cl::desc("Set filename used to determine the language and to find\n"
|
||||||
|
".clang-format file.\n"
|
||||||
|
"Only used when reading from stdin.\n"
|
||||||
|
"If this is not passed, the .clang-format file is searched\n"
|
||||||
|
"relative to the current working directory when reading stdin.\n"
|
||||||
|
"Unrecognized filenames are treated as C++.\n"
|
||||||
|
"supported:\n"
|
||||||
|
" CSharp: .cs\n"
|
||||||
|
" Java: .java\n"
|
||||||
|
" JavaScript: .js .mjs .cjs .ts\n"
|
||||||
|
" Json: .json .ipynb\n"
|
||||||
|
" Objective-C: .m .mm\n"
|
||||||
|
" Proto: .proto .protodevel\n"
|
||||||
|
" TableGen: .td\n"
|
||||||
|
" TextProto: .txtpb .textpb .pb.txt .textproto .asciipb\n"
|
||||||
|
" Verilog: .sv .svh .v .vh"),
|
||||||
|
cl::init("<stdin>"), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool> Inplace("i",
|
||||||
|
cl::desc("Inplace edit <file>s, if specified."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool> OutputXML("output-replacements-xml",
|
||||||
|
cl::desc("Output replacements as XML."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::opt<bool>
|
||||||
|
DumpConfig("dump-config",
|
||||||
|
cl::desc("Dump configuration options to stdout and exit.\n"
|
||||||
|
"Can be used with -style option."),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
static cl::opt<unsigned>
|
||||||
|
Cursor("cursor",
|
||||||
|
cl::desc("The position of the cursor when invoking\n"
|
||||||
|
"clang-format from an editor integration"),
|
||||||
|
cl::init(0), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
SortIncludes("sort-includes",
|
||||||
|
cl::desc("If set, overrides the include sorting behavior\n"
|
||||||
|
"determined by the SortIncludes style flag"),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<std::string> QualifierAlignment(
|
||||||
|
"qualifier-alignment",
|
||||||
|
cl::desc("If set, overrides the qualifier alignment style\n"
|
||||||
|
"determined by the QualifierAlignment style flag"),
|
||||||
|
cl::init(""), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<std::string> Files(
|
||||||
|
"files",
|
||||||
|
cl::desc("A file containing a list of files to process, one per line."),
|
||||||
|
cl::value_desc("filename"), cl::init(""), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
Verbose("verbose", cl::desc("If set, shows the list of processed files"),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
// Use --dry-run to match other LLVM tools when you mean do it but don't
|
||||||
|
// actually do it
|
||||||
|
static cl::opt<bool>
|
||||||
|
DryRun("dry-run",
|
||||||
|
cl::desc("If set, do not actually make the formatting changes"),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
// Use -n as a common command as an alias for --dry-run. (git and make use -n)
|
||||||
|
static cl::alias DryRunShort("n", cl::desc("Alias for --dry-run"),
|
||||||
|
cl::cat(ClangFormatCategory), cl::aliasopt(DryRun),
|
||||||
|
cl::NotHidden);
|
||||||
|
|
||||||
|
// Emulate being able to turn on/off the warning.
|
||||||
|
static cl::opt<bool>
|
||||||
|
WarnFormat("Wclang-format-violations",
|
||||||
|
cl::desc("Warnings about individual formatting changes needed. "
|
||||||
|
"Used only with --dry-run or -n"),
|
||||||
|
cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
NoWarnFormat("Wno-clang-format-violations",
|
||||||
|
cl::desc("Do not warn about individual formatting changes "
|
||||||
|
"needed. Used only with --dry-run or -n"),
|
||||||
|
cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
|
||||||
|
|
||||||
|
static cl::opt<unsigned> ErrorLimit(
|
||||||
|
"ferror-limit",
|
||||||
|
cl::desc("Set the maximum number of clang-format errors to emit\n"
|
||||||
|
"before stopping (0 = no limit).\n"
|
||||||
|
"Used only with --dry-run or -n"),
|
||||||
|
cl::init(0), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
WarningsAsErrors("Werror",
|
||||||
|
cl::desc("If set, changes formatting warnings to errors"),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum class WNoError { Unknown };
|
||||||
|
}
|
||||||
|
|
||||||
|
static cl::bits<WNoError> WNoErrorList(
|
||||||
|
"Wno-error",
|
||||||
|
cl::desc("If set, don't error out on the specified warning type."),
|
||||||
|
cl::values(
|
||||||
|
clEnumValN(WNoError::Unknown, "unknown",
|
||||||
|
"If set, unknown format options are only warned about.\n"
|
||||||
|
"This can be used to enable formatting, even if the\n"
|
||||||
|
"configuration contains unknown (newer) options.\n"
|
||||||
|
"Use with caution, as this might lead to dramatically\n"
|
||||||
|
"differing format depending on an option being\n"
|
||||||
|
"supported or not.")),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
ShowColors("fcolor-diagnostics",
|
||||||
|
cl::desc("If set, and on a color-capable terminal controls "
|
||||||
|
"whether or not to print diagnostics in color"),
|
||||||
|
cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
NoShowColors("fno-color-diagnostics",
|
||||||
|
cl::desc("If set, and on a color-capable terminal controls "
|
||||||
|
"whether or not to print diagnostics in color"),
|
||||||
|
cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
|
||||||
|
|
||||||
|
static cl::list<std::string> FileNames(cl::Positional,
|
||||||
|
cl::desc("[@<file>] [<file> ...]"),
|
||||||
|
cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool> FailOnIncompleteFormat(
|
||||||
|
"fail-on-incomplete-format",
|
||||||
|
cl::desc("If set, fail with exit code 1 on incomplete format."),
|
||||||
|
cl::init(false), cl::cat(ClangFormatCategory));
|
||||||
|
|
||||||
|
static cl::opt<bool> ListIgnored("list-ignored",
|
||||||
|
cl::desc("List ignored files."),
|
||||||
|
cl::cat(ClangFormatCategory), cl::Hidden);
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
namespace format {
|
||||||
|
|
||||||
|
static FileID createInMemoryFile(StringRef FileName, MemoryBufferRef Source,
|
||||||
|
SourceManager &Sources, FileManager &Files,
|
||||||
|
llvm::vfs::InMemoryFileSystem *MemFS) {
|
||||||
|
MemFS->addFileNoOwn(FileName, 0, Source);
|
||||||
|
auto File = Files.getOptionalFileRef(FileName);
|
||||||
|
assert(File && "File not added to MemFS?");
|
||||||
|
return Sources.createFileID(*File, SourceLocation(), SrcMgr::C_User);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses <start line>:<end line> input to a pair of line numbers.
|
||||||
|
// Returns true on error.
|
||||||
|
static bool parseLineRange(StringRef Input, unsigned &FromLine,
|
||||||
|
unsigned &ToLine) {
|
||||||
|
std::pair<StringRef, StringRef> LineRange = Input.split(':');
|
||||||
|
return LineRange.first.getAsInteger(0, FromLine) ||
|
||||||
|
LineRange.second.getAsInteger(0, ToLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool fillRanges(MemoryBuffer *Code,
|
||||||
|
std::vector<tooling::Range> &Ranges) {
|
||||||
|
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
|
||||||
|
new llvm::vfs::InMemoryFileSystem);
|
||||||
|
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
|
||||||
|
DiagnosticOptions DiagOpts;
|
||||||
|
DiagnosticsEngine Diagnostics(
|
||||||
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts);
|
||||||
|
SourceManager Sources(Diagnostics, Files);
|
||||||
|
const auto ID = createInMemoryFile("<irrelevant>", *Code, Sources, Files,
|
||||||
|
InMemoryFileSystem.get());
|
||||||
|
if (!LineRanges.empty()) {
|
||||||
|
if (!Offsets.empty() || !Lengths.empty()) {
|
||||||
|
errs() << "error: cannot use -lines with -offset/-length\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &LineRange : LineRanges) {
|
||||||
|
unsigned FromLine, ToLine;
|
||||||
|
if (parseLineRange(LineRange, FromLine, ToLine)) {
|
||||||
|
errs() << "error: invalid <start line>:<end line> pair\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (FromLine < 1) {
|
||||||
|
errs() << "error: start line should be at least 1\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (FromLine > ToLine) {
|
||||||
|
errs() << "error: start line should not exceed end line\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto Start = Sources.translateLineCol(ID, FromLine, 1);
|
||||||
|
const auto End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
|
||||||
|
if (Start.isInvalid() || End.isInvalid())
|
||||||
|
return true;
|
||||||
|
const auto Offset = Sources.getFileOffset(Start);
|
||||||
|
const auto Length = Sources.getFileOffset(End) - Offset;
|
||||||
|
Ranges.push_back(tooling::Range(Offset, Length));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Offsets.empty())
|
||||||
|
Offsets.push_back(0);
|
||||||
|
const bool EmptyLengths = Lengths.empty();
|
||||||
|
unsigned Length = 0;
|
||||||
|
if (Offsets.size() == 1 && EmptyLengths) {
|
||||||
|
Length = Sources.getFileOffset(Sources.getLocForEndOfFile(ID)) - Offsets[0];
|
||||||
|
} else if (Offsets.size() != Lengths.size()) {
|
||||||
|
errs() << "error: number of -offset and -length arguments must match.\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (unsigned I = 0, E = Offsets.size(), CodeSize = Code->getBufferSize();
|
||||||
|
I < E; ++I) {
|
||||||
|
const auto Offset = Offsets[I];
|
||||||
|
if (Offset >= CodeSize) {
|
||||||
|
errs() << "error: offset " << Offset << " is outside the file\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!EmptyLengths)
|
||||||
|
Length = Lengths[I];
|
||||||
|
if (Offset + Length > CodeSize) {
|
||||||
|
errs() << "error: invalid length " << Length << ", offset + length ("
|
||||||
|
<< Offset + Length << ") is outside the file.\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Ranges.push_back(tooling::Range(Offset, Length));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputReplacementXML(StringRef Text) {
|
||||||
|
// FIXME: When we sort includes, we need to make sure the stream is correct
|
||||||
|
// utf-8.
|
||||||
|
size_t From = 0;
|
||||||
|
size_t Index;
|
||||||
|
while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) {
|
||||||
|
outs() << Text.substr(From, Index - From);
|
||||||
|
switch (Text[Index]) {
|
||||||
|
case '\n':
|
||||||
|
outs() << " ";
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
outs() << " ";
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
outs() << "<";
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
outs() << "&";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unexpected character encountered!");
|
||||||
|
}
|
||||||
|
From = Index + 1;
|
||||||
|
}
|
||||||
|
outs() << Text.substr(From);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputReplacementsXML(const Replacements &Replaces) {
|
||||||
|
for (const auto &R : Replaces) {
|
||||||
|
outs() << "<replacement "
|
||||||
|
<< "offset='" << R.getOffset() << "' "
|
||||||
|
<< "length='" << R.getLength() << "'>";
|
||||||
|
outputReplacementXML(R.getReplacementText());
|
||||||
|
outs() << "</replacement>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
emitReplacementWarnings(const Replacements &Replaces, StringRef AssumedFileName,
|
||||||
|
const std::unique_ptr<llvm::MemoryBuffer> &Code) {
|
||||||
|
unsigned Errors = 0;
|
||||||
|
if (WarnFormat && !NoWarnFormat) {
|
||||||
|
SourceMgr Mgr;
|
||||||
|
const char *StartBuf = Code->getBufferStart();
|
||||||
|
|
||||||
|
Mgr.AddNewSourceBuffer(
|
||||||
|
MemoryBuffer::getMemBuffer(StartBuf, AssumedFileName), SMLoc());
|
||||||
|
for (const auto &R : Replaces) {
|
||||||
|
SMDiagnostic Diag = Mgr.GetMessage(
|
||||||
|
SMLoc::getFromPointer(StartBuf + R.getOffset()),
|
||||||
|
WarningsAsErrors ? SourceMgr::DiagKind::DK_Error
|
||||||
|
: SourceMgr::DiagKind::DK_Warning,
|
||||||
|
"code should be clang-formatted [-Wclang-format-violations]");
|
||||||
|
|
||||||
|
Diag.print(nullptr, llvm::errs(), ShowColors && !NoShowColors);
|
||||||
|
if (ErrorLimit && ++Errors >= ErrorLimit)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return WarningsAsErrors;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputXML(const Replacements &Replaces,
|
||||||
|
const Replacements &FormatChanges,
|
||||||
|
const FormattingAttemptStatus &Status,
|
||||||
|
const cl::opt<unsigned> &Cursor,
|
||||||
|
unsigned CursorPosition) {
|
||||||
|
outs() << "<?xml version='1.0'?>\n<replacements "
|
||||||
|
"xml:space='preserve' incomplete_format='"
|
||||||
|
<< (Status.FormatComplete ? "false" : "true") << "'";
|
||||||
|
if (!Status.FormatComplete)
|
||||||
|
outs() << " line='" << Status.Line << "'";
|
||||||
|
outs() << ">\n";
|
||||||
|
if (Cursor.getNumOccurrences() != 0) {
|
||||||
|
outs() << "<cursor>" << FormatChanges.getShiftedCodePosition(CursorPosition)
|
||||||
|
<< "</cursor>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
outputReplacementsXML(Replaces);
|
||||||
|
outs() << "</replacements>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClangFormatDiagConsumer : public DiagnosticConsumer {
|
||||||
|
virtual void anchor() {}
|
||||||
|
|
||||||
|
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
|
||||||
|
const Diagnostic &Info) override {
|
||||||
|
|
||||||
|
SmallVector<char, 16> vec;
|
||||||
|
Info.FormatDiagnostic(vec);
|
||||||
|
errs() << "clang-format error:" << vec << "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns true on error.
|
||||||
|
static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) {
|
||||||
|
const bool IsSTDIN = FileName == "-";
|
||||||
|
if (!OutputXML && Inplace && IsSTDIN) {
|
||||||
|
errs() << "error: cannot use -i when reading from stdin.\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// On Windows, overwriting a file with an open file mapping doesn't work,
|
||||||
|
// so read the whole file into memory when formatting in-place.
|
||||||
|
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
|
||||||
|
!OutputXML && Inplace
|
||||||
|
? MemoryBuffer::getFileAsStream(FileName)
|
||||||
|
: MemoryBuffer::getFileOrSTDIN(FileName, /*IsText=*/true);
|
||||||
|
if (std::error_code EC = CodeOrErr.getError()) {
|
||||||
|
errs() << FileName << ": " << EC.message() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
|
||||||
|
if (Code->getBufferSize() == 0)
|
||||||
|
return false; // Empty files are formatted correctly.
|
||||||
|
|
||||||
|
StringRef BufStr = Code->getBuffer();
|
||||||
|
|
||||||
|
const char *InvalidBOM = SrcMgr::ContentCache::getInvalidBOM(BufStr);
|
||||||
|
|
||||||
|
if (InvalidBOM) {
|
||||||
|
errs() << "error: encoding with unsupported byte order mark \""
|
||||||
|
<< InvalidBOM << "\" detected";
|
||||||
|
if (!IsSTDIN)
|
||||||
|
errs() << " in file '" << FileName << "'";
|
||||||
|
errs() << ".\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<tooling::Range> Ranges;
|
||||||
|
if (fillRanges(Code.get(), Ranges))
|
||||||
|
return true;
|
||||||
|
StringRef AssumedFileName = IsSTDIN ? AssumeFileName : FileName;
|
||||||
|
if (AssumedFileName.empty()) {
|
||||||
|
llvm::errs() << "error: empty filenames are not allowed\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto RealFS = vfs::getRealFileSystem();
|
||||||
|
auto CustomFS = new vfs::CustomFileSystem(RealFS);
|
||||||
|
IntrusiveRefCntPtr<vfs::FileSystem> CustomFSPtr(CustomFS);
|
||||||
|
Expected<FormatStyle> FormatStyle =
|
||||||
|
getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer(),
|
||||||
|
CustomFSPtr.get(), WNoErrorList.isSet(WNoError::Unknown));
|
||||||
|
if (!FormatStyle) {
|
||||||
|
llvm::errs() << toString(FormatStyle.takeError()) << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef QualifierAlignmentOrder = QualifierAlignment;
|
||||||
|
|
||||||
|
FormatStyle->QualifierAlignment =
|
||||||
|
StringSwitch<FormatStyle::QualifierAlignmentStyle>(
|
||||||
|
QualifierAlignmentOrder.lower())
|
||||||
|
.Case("right", FormatStyle::QAS_Right)
|
||||||
|
.Case("left", FormatStyle::QAS_Left)
|
||||||
|
.Default(FormatStyle->QualifierAlignment);
|
||||||
|
|
||||||
|
if (FormatStyle->QualifierAlignment == FormatStyle::QAS_Left) {
|
||||||
|
FormatStyle->QualifierOrder = {"const", "volatile", "type"};
|
||||||
|
} else if (FormatStyle->QualifierAlignment == FormatStyle::QAS_Right) {
|
||||||
|
FormatStyle->QualifierOrder = {"type", "const", "volatile"};
|
||||||
|
} else if (QualifierAlignmentOrder.contains("type")) {
|
||||||
|
FormatStyle->QualifierAlignment = FormatStyle::QAS_Custom;
|
||||||
|
SmallVector<StringRef> Qualifiers;
|
||||||
|
QualifierAlignmentOrder.split(Qualifiers, " ", /*MaxSplit=*/-1,
|
||||||
|
/*KeepEmpty=*/false);
|
||||||
|
FormatStyle->QualifierOrder = {Qualifiers.begin(), Qualifiers.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SortIncludes.getNumOccurrences() != 0) {
|
||||||
|
FormatStyle->SortIncludes = {};
|
||||||
|
if (SortIncludes)
|
||||||
|
FormatStyle->SortIncludes.Enabled = true;
|
||||||
|
}
|
||||||
|
unsigned CursorPosition = Cursor;
|
||||||
|
Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges,
|
||||||
|
AssumedFileName, &CursorPosition);
|
||||||
|
|
||||||
|
const bool IsJson = FormatStyle->isJson();
|
||||||
|
|
||||||
|
// To format JSON insert a variable to trick the code into thinking its
|
||||||
|
// JavaScript.
|
||||||
|
if (IsJson && !FormatStyle->DisableFormat) {
|
||||||
|
auto Err =
|
||||||
|
Replaces.add(tooling::Replacement(AssumedFileName, 0, 0, "x = "));
|
||||||
|
if (Err)
|
||||||
|
llvm::errs() << "Bad Json variable insertion\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces);
|
||||||
|
if (!ChangedCode) {
|
||||||
|
llvm::errs() << toString(ChangedCode.takeError()) << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Get new affected ranges after sorting `#includes`.
|
||||||
|
Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
|
||||||
|
FormattingAttemptStatus Status;
|
||||||
|
Replacements FormatChanges =
|
||||||
|
reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
|
||||||
|
Replaces = Replaces.merge(FormatChanges);
|
||||||
|
if (DryRun) {
|
||||||
|
return Replaces.size() > (IsJson ? 1u : 0u) &&
|
||||||
|
emitReplacementWarnings(Replaces, AssumedFileName, Code);
|
||||||
|
}
|
||||||
|
if (OutputXML) {
|
||||||
|
outputXML(Replaces, FormatChanges, Status, Cursor, CursorPosition);
|
||||||
|
} else {
|
||||||
|
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
|
||||||
|
new llvm::vfs::InMemoryFileSystem);
|
||||||
|
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
|
||||||
|
|
||||||
|
DiagnosticOptions DiagOpts;
|
||||||
|
ClangFormatDiagConsumer IgnoreDiagnostics;
|
||||||
|
DiagnosticsEngine Diagnostics(
|
||||||
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts,
|
||||||
|
&IgnoreDiagnostics, false);
|
||||||
|
SourceManager Sources(Diagnostics, Files);
|
||||||
|
FileID ID = createInMemoryFile(AssumedFileName, *Code, Sources, Files,
|
||||||
|
InMemoryFileSystem.get());
|
||||||
|
Rewriter Rewrite(Sources, LangOptions());
|
||||||
|
tooling::applyAllReplacements(Replaces, Rewrite);
|
||||||
|
if (Inplace) {
|
||||||
|
if (Rewrite.overwriteChangedFiles())
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (Cursor.getNumOccurrences() != 0) {
|
||||||
|
outs() << "{ \"Cursor\": "
|
||||||
|
<< FormatChanges.getShiftedCodePosition(CursorPosition)
|
||||||
|
<< ", \"IncompleteFormat\": "
|
||||||
|
<< (Status.FormatComplete ? "false" : "true");
|
||||||
|
if (!Status.FormatComplete)
|
||||||
|
outs() << ", \"Line\": " << Status.Line;
|
||||||
|
outs() << " }\n";
|
||||||
|
}
|
||||||
|
Rewrite.getEditBuffer(ID).write(outs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ErrorOnIncompleteFormat && !Status.FormatComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace format
|
||||||
|
} // namespace clang
|
||||||
|
|
||||||
|
static void PrintVersion(raw_ostream &OS) {
|
||||||
|
OS << clang::getClangToolFullVersion("clang-format") << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump the configuration.
|
||||||
|
static int dumpConfig() {
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> Code;
|
||||||
|
// We can't read the code to detect the language if there's no file name.
|
||||||
|
if (!FileNames.empty()) {
|
||||||
|
// Read in the code in case the filename alone isn't enough to detect the
|
||||||
|
// language.
|
||||||
|
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
|
||||||
|
MemoryBuffer::getFileOrSTDIN(FileNames[0], /*IsText=*/true);
|
||||||
|
if (std::error_code EC = CodeOrErr.getError()) {
|
||||||
|
llvm::errs() << EC.message() << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Code = std::move(CodeOrErr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto RealFS = vfs::getRealFileSystem();
|
||||||
|
auto CustomFS = new vfs::CustomFileSystem(RealFS);
|
||||||
|
IntrusiveRefCntPtr<vfs::FileSystem> CustomFSPtr(CustomFS);
|
||||||
|
|
||||||
|
Expected<clang::format::FormatStyle> FormatStyle = clang::format::getStyle(
|
||||||
|
Style,
|
||||||
|
FileNames.empty() || FileNames[0] == "-" ? AssumeFileName : FileNames[0],
|
||||||
|
FallbackStyle, Code ? Code->getBuffer() : "", CustomFSPtr.get());
|
||||||
|
if (!FormatStyle) {
|
||||||
|
llvm::errs() << toString(FormatStyle.takeError()) << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::string Config = clang::format::configurationAsText(*FormatStyle);
|
||||||
|
outs() << Config << "\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
using String = SmallString<128>;
|
||||||
|
static String IgnoreDir; // Directory of .clang-format-ignore file.
|
||||||
|
static String PrevDir; // Directory of previous `FilePath`.
|
||||||
|
static SmallVector<String> Patterns; // Patterns in .clang-format-ignore file.
|
||||||
|
|
||||||
|
// Check whether `FilePath` is ignored according to the nearest
|
||||||
|
// .clang-format-ignore file based on the rules below:
|
||||||
|
// - A blank line is skipped.
|
||||||
|
// - Leading and trailing spaces of a line are trimmed.
|
||||||
|
// - A line starting with a hash (`#`) is a comment.
|
||||||
|
// - A non-comment line is a single pattern.
|
||||||
|
// - The slash (`/`) is used as the directory separator.
|
||||||
|
// - A pattern is relative to the directory of the .clang-format-ignore file (or
|
||||||
|
// the root directory if the pattern starts with a slash).
|
||||||
|
// - A pattern is negated if it starts with a bang (`!`).
|
||||||
|
static bool isIgnored(StringRef FilePath) {
|
||||||
|
using namespace llvm::sys::fs;
|
||||||
|
if (!is_regular_file(FilePath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String Path;
|
||||||
|
String AbsPath{FilePath};
|
||||||
|
|
||||||
|
auto PathStyle = vfs::getPathStyle();
|
||||||
|
|
||||||
|
using namespace llvm::sys::path;
|
||||||
|
vfs::make_absolute(AbsPath);
|
||||||
|
remove_dots(AbsPath, /*remove_dot_dot=*/true, PathStyle);
|
||||||
|
|
||||||
|
if (StringRef Dir{parent_path(AbsPath, PathStyle)}; PrevDir != Dir) {
|
||||||
|
PrevDir = Dir;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
Path = Dir;
|
||||||
|
append(Path, PathStyle, ".clang-format-ignore");
|
||||||
|
if (is_regular_file(Path))
|
||||||
|
break;
|
||||||
|
Dir = parent_path(Dir, PathStyle);
|
||||||
|
if (Dir.empty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IgnoreDir = convert_to_slash(Dir, PathStyle);
|
||||||
|
|
||||||
|
std::ifstream IgnoreFile{Path.c_str()};
|
||||||
|
if (!IgnoreFile.good())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Patterns.clear();
|
||||||
|
|
||||||
|
for (std::string Line; std::getline(IgnoreFile, Line);) {
|
||||||
|
if (const auto Pattern{StringRef{Line}.trim()};
|
||||||
|
// Skip empty and comment lines.
|
||||||
|
!Pattern.empty() && Pattern[0] != '#') {
|
||||||
|
Patterns.push_back(Pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IgnoreDir.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto Pathname{convert_to_slash(AbsPath, PathStyle)};
|
||||||
|
for (const auto &Pat : Patterns) {
|
||||||
|
const bool IsNegated = Pat[0] == '!';
|
||||||
|
StringRef Pattern{Pat};
|
||||||
|
if (IsNegated)
|
||||||
|
Pattern = Pattern.drop_front();
|
||||||
|
|
||||||
|
if (Pattern.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Pattern = Pattern.ltrim();
|
||||||
|
|
||||||
|
// `Pattern` is relative to `IgnoreDir` unless it starts with a slash.
|
||||||
|
// This doesn't support patterns containing drive names (e.g. `C:`).
|
||||||
|
if (Pattern[0] != '/') {
|
||||||
|
Path = IgnoreDir;
|
||||||
|
append(Path, Style::posix, Pattern);
|
||||||
|
remove_dots(Path, /*remove_dot_dot=*/true, Style::posix);
|
||||||
|
Pattern = Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clang::format::matchFilePath(Pattern, Pathname) == !IsNegated)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
InitLLVM X(argc, argv);
|
||||||
|
|
||||||
|
cl::HideUnrelatedOptions(ClangFormatCategory);
|
||||||
|
|
||||||
|
cl::SetVersionPrinter(PrintVersion);
|
||||||
|
cl::ParseCommandLineOptions(
|
||||||
|
argc, argv,
|
||||||
|
"A tool to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# "
|
||||||
|
"code.\n\n"
|
||||||
|
"If no arguments are specified, it formats the code from standard input\n"
|
||||||
|
"and writes the result to the standard output.\n"
|
||||||
|
"If <file>s are given, it reformats the files. If -i is specified\n"
|
||||||
|
"together with <file>s, the files are edited in-place. Otherwise, the\n"
|
||||||
|
"result is written to the standard output.\n");
|
||||||
|
|
||||||
|
if (Help) {
|
||||||
|
cl::PrintHelpMessage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DumpConfig)
|
||||||
|
return dumpConfig();
|
||||||
|
|
||||||
|
if (!Files.empty()) {
|
||||||
|
std::ifstream ExternalFileOfFiles{std::string(Files)};
|
||||||
|
std::string Line;
|
||||||
|
unsigned LineNo = 1;
|
||||||
|
while (std::getline(ExternalFileOfFiles, Line)) {
|
||||||
|
FileNames.push_back(Line);
|
||||||
|
LineNo++;
|
||||||
|
}
|
||||||
|
errs() << "Clang-formatting " << LineNo << " files\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileNames.empty()) {
|
||||||
|
if (isIgnored(AssumeFileName))
|
||||||
|
return 0;
|
||||||
|
return clang::format::format("-", FailOnIncompleteFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileNames.size() > 1 &&
|
||||||
|
(!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) {
|
||||||
|
errs() << "error: -offset, -length and -lines can only be used for "
|
||||||
|
"single file.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned FileNo = 1;
|
||||||
|
bool Error = false;
|
||||||
|
for (const auto &FileName : FileNames) {
|
||||||
|
const bool Ignored = isIgnored(FileName);
|
||||||
|
if (ListIgnored) {
|
||||||
|
if (Ignored)
|
||||||
|
outs() << FileName << '\n';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Ignored)
|
||||||
|
continue;
|
||||||
|
if (Verbose) {
|
||||||
|
errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] "
|
||||||
|
<< FileName << "\n";
|
||||||
|
}
|
||||||
|
Error |= clang::format::format(FileName, FailOnIncompleteFormat);
|
||||||
|
}
|
||||||
|
return Error ? 1 : 0;
|
||||||
|
}
|
||||||
323
frontend/src/common/prettier/plugins/clang/src/lib.cc
Normal file
323
frontend/src/common/prettier/plugins/clang/src/lib.cc
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// This file implements a clang-format tool that automatically formats
|
||||||
|
/// (fragments of) C++ code.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "clang/Basic/FileManager.h"
|
||||||
|
#include "clang/Basic/SourceManager.h"
|
||||||
|
#include "clang/Basic/Version.h"
|
||||||
|
#include "clang/Format/Format.h"
|
||||||
|
#include "clang/Rewrite/Core/Rewriter.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using clang::tooling::Replacements;
|
||||||
|
|
||||||
|
static std::string FallbackStyle{clang::format::DefaultFallbackStyle};
|
||||||
|
|
||||||
|
static unsigned Cursor{0};
|
||||||
|
|
||||||
|
static bool SortIncludes{false};
|
||||||
|
|
||||||
|
static std::string QualifierAlignment{""};
|
||||||
|
|
||||||
|
static auto Ok(const std::string content) -> Result {
|
||||||
|
return {false, std::move(content)};
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto Err(const std::string content) -> Result {
|
||||||
|
return {true, std::move(content)};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
namespace format {
|
||||||
|
|
||||||
|
static FileID createInMemoryFile(StringRef FileName, MemoryBufferRef Source,
|
||||||
|
SourceManager &Sources, FileManager &Files,
|
||||||
|
llvm::vfs::InMemoryFileSystem *MemFS) {
|
||||||
|
MemFS->addFileNoOwn(FileName, 0, Source);
|
||||||
|
auto File = Files.getOptionalFileRef(FileName);
|
||||||
|
assert(File && "File not added to MemFS?");
|
||||||
|
return Sources.createFileID(*File, SourceLocation(), SrcMgr::C_User);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto fillRanges(MemoryBuffer *Code, std::vector<tooling::Range> &Ranges)
|
||||||
|
-> void {
|
||||||
|
Ranges.push_back(tooling::Range(0, Code->getBuffer().size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto isPredefinedStyle(StringRef style) -> bool {
|
||||||
|
return StringSwitch<bool>(style.lower())
|
||||||
|
.Cases("llvm", "chromium", "mozilla", "google", "webkit", "gnu",
|
||||||
|
"microsoft", "none", "file", true)
|
||||||
|
.Default(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto format_range(const std::unique_ptr<llvm::MemoryBuffer> code,
|
||||||
|
const std::string assumedFileName,
|
||||||
|
const std::string style,
|
||||||
|
std::vector<tooling::Range> ranges) -> Result {
|
||||||
|
StringRef BufStr = code->getBuffer();
|
||||||
|
|
||||||
|
const char *InvalidBOM = SrcMgr::ContentCache::getInvalidBOM(BufStr);
|
||||||
|
|
||||||
|
if (InvalidBOM) {
|
||||||
|
std::stringstream err;
|
||||||
|
err << "encoding with unsupported byte order mark \"" << InvalidBOM
|
||||||
|
<< "\" detected.";
|
||||||
|
|
||||||
|
return Err(err.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef AssumedFileName = assumedFileName;
|
||||||
|
if (AssumedFileName.empty())
|
||||||
|
AssumedFileName = "<stdin>";
|
||||||
|
|
||||||
|
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
|
||||||
|
new llvm::vfs::InMemoryFileSystem);
|
||||||
|
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
|
||||||
|
|
||||||
|
DiagnosticOptions DiagOpts;
|
||||||
|
DiagnosticsEngine Diagnostics(
|
||||||
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts);
|
||||||
|
SourceManager Sources(Diagnostics, Files);
|
||||||
|
|
||||||
|
StringRef _style = style;
|
||||||
|
|
||||||
|
if (!_style.starts_with("{") && !isPredefinedStyle(_style)) {
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> DotClangFormat =
|
||||||
|
MemoryBuffer::getMemBuffer(style);
|
||||||
|
|
||||||
|
createInMemoryFile(".clang-format", *DotClangFormat.get(), Sources, Files,
|
||||||
|
InMemoryFileSystem.get());
|
||||||
|
_style = "file:.clang-format";
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Expected<FormatStyle> FormatStyle =
|
||||||
|
getStyle(_style, AssumedFileName, FallbackStyle, code->getBuffer(),
|
||||||
|
InMemoryFileSystem.get(), false);
|
||||||
|
|
||||||
|
InMemoryFileSystem.reset();
|
||||||
|
|
||||||
|
if (!FormatStyle) {
|
||||||
|
std::string err = llvm::toString(FormatStyle.takeError());
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef QualifierAlignmentOrder = QualifierAlignment;
|
||||||
|
|
||||||
|
FormatStyle->QualifierAlignment =
|
||||||
|
StringSwitch<FormatStyle::QualifierAlignmentStyle>(
|
||||||
|
QualifierAlignmentOrder.lower())
|
||||||
|
.Case("right", FormatStyle::QAS_Right)
|
||||||
|
.Case("left", FormatStyle::QAS_Left)
|
||||||
|
.Default(FormatStyle->QualifierAlignment);
|
||||||
|
|
||||||
|
if (FormatStyle->QualifierAlignment == FormatStyle::QAS_Left) {
|
||||||
|
FormatStyle->QualifierOrder = {"const", "volatile", "type"};
|
||||||
|
} else if (FormatStyle->QualifierAlignment == FormatStyle::QAS_Right) {
|
||||||
|
FormatStyle->QualifierOrder = {"type", "const", "volatile"};
|
||||||
|
} else if (QualifierAlignmentOrder.contains("type")) {
|
||||||
|
FormatStyle->QualifierAlignment = FormatStyle::QAS_Custom;
|
||||||
|
SmallVector<StringRef> Qualifiers;
|
||||||
|
QualifierAlignmentOrder.split(Qualifiers, " ", /*MaxSplit=*/-1,
|
||||||
|
/*KeepEmpty=*/false);
|
||||||
|
FormatStyle->QualifierOrder = {Qualifiers.begin(), Qualifiers.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SortIncludes) {
|
||||||
|
FormatStyle->SortIncludes = {};
|
||||||
|
FormatStyle->SortIncludes.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned CursorPosition = Cursor;
|
||||||
|
Replacements Replaces = sortIncludes(*FormatStyle, code->getBuffer(), ranges,
|
||||||
|
AssumedFileName, &CursorPosition);
|
||||||
|
|
||||||
|
// To format JSON insert a variable to trick the code into thinking its
|
||||||
|
// JavaScript.
|
||||||
|
if (FormatStyle->isJson() && !FormatStyle->DisableFormat) {
|
||||||
|
auto err =
|
||||||
|
Replaces.add(tooling::Replacement(AssumedFileName, 0, 0, "x = "));
|
||||||
|
if (err)
|
||||||
|
return Err("Bad Json variable insertion");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ChangedCode =
|
||||||
|
cantFail(tooling::applyAllReplacements(code->getBuffer(), Replaces));
|
||||||
|
|
||||||
|
// Get new affected ranges after sorting `#includes`.
|
||||||
|
ranges = tooling::calculateRangesAfterReplacements(Replaces, ranges);
|
||||||
|
FormattingAttemptStatus Status;
|
||||||
|
Replacements FormatChanges =
|
||||||
|
reformat(*FormatStyle, ChangedCode, ranges, AssumedFileName, &Status);
|
||||||
|
Replaces = Replaces.merge(FormatChanges);
|
||||||
|
|
||||||
|
return Ok(
|
||||||
|
cantFail(tooling::applyAllReplacements(code->getBuffer(), Replaces)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto format_range(const std::string str,
|
||||||
|
const std::string assumedFileName,
|
||||||
|
const std::string style, const bool is_line_range,
|
||||||
|
const std::vector<unsigned> ranges) -> Result {
|
||||||
|
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
|
||||||
|
MemoryBuffer::getMemBuffer(str);
|
||||||
|
|
||||||
|
if (std::error_code EC = CodeOrErr.getError())
|
||||||
|
return Err(EC.message());
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
|
||||||
|
if (Code->getBufferSize() == 0)
|
||||||
|
return Ok(""); // Empty files are formatted correctly.
|
||||||
|
|
||||||
|
std::vector<tooling::Range> Ranges;
|
||||||
|
|
||||||
|
if (ranges.empty()) {
|
||||||
|
fillRanges(Code.get(), Ranges);
|
||||||
|
return format_range(std::move(Code), assumedFileName, style,
|
||||||
|
std::move(Ranges));
|
||||||
|
}
|
||||||
|
|
||||||
|
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
|
||||||
|
new llvm::vfs::InMemoryFileSystem);
|
||||||
|
FileManager Files(FileSystemOptions(), InMemoryFileSystem);
|
||||||
|
DiagnosticOptions DiagOpts;
|
||||||
|
DiagnosticsEngine Diagnostics(
|
||||||
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts);
|
||||||
|
SourceManager Sources(Diagnostics, Files);
|
||||||
|
FileID ID = createInMemoryFile("<irrelevant>", *Code, Sources, Files,
|
||||||
|
InMemoryFileSystem.get());
|
||||||
|
|
||||||
|
if (is_line_range) {
|
||||||
|
for (auto FromLine = begin(ranges); FromLine < end(ranges); FromLine += 2) {
|
||||||
|
auto ToLine = FromLine + 1;
|
||||||
|
|
||||||
|
SourceLocation Start = Sources.translateLineCol(ID, *FromLine, 1);
|
||||||
|
SourceLocation End = Sources.translateLineCol(ID, *ToLine, UINT_MAX);
|
||||||
|
if (Start.isInvalid() || End.isInvalid())
|
||||||
|
return Err("invalid line number");
|
||||||
|
unsigned Offset = Sources.getFileOffset(Start);
|
||||||
|
unsigned Length = Sources.getFileOffset(End) - Offset;
|
||||||
|
Ranges.push_back(tooling::Range(Offset, Length));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ranges.size() > 2 && ranges.size() % 2 != 0)
|
||||||
|
return Err("number of -offset and -length arguments must match");
|
||||||
|
|
||||||
|
if (ranges.size() == 1) {
|
||||||
|
auto offset = begin(ranges);
|
||||||
|
if (*offset >= Code->getBufferSize()) {
|
||||||
|
std::stringstream err;
|
||||||
|
err << "offset " << *offset << " is outside the file";
|
||||||
|
return Err(err.str());
|
||||||
|
}
|
||||||
|
SourceLocation Start =
|
||||||
|
Sources.getLocForStartOfFile(ID).getLocWithOffset(*offset);
|
||||||
|
SourceLocation End = Sources.getLocForEndOfFile(ID);
|
||||||
|
|
||||||
|
unsigned Offset = Sources.getFileOffset(Start);
|
||||||
|
unsigned Length = Sources.getFileOffset(End) - Offset;
|
||||||
|
|
||||||
|
Ranges.push_back(tooling::Range(Offset, Length));
|
||||||
|
} else {
|
||||||
|
for (auto offset = begin(ranges); offset < end(ranges); offset += 2) {
|
||||||
|
auto length = offset + 1;
|
||||||
|
|
||||||
|
if (*offset >= Code->getBufferSize()) {
|
||||||
|
std::stringstream err;
|
||||||
|
err << "offset " << *offset << " is outside the file";
|
||||||
|
return Err(err.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned end = *offset + *length;
|
||||||
|
if (end > Code->getBufferSize()) {
|
||||||
|
std::stringstream err;
|
||||||
|
err << "invalid length " << *length << ", offset + length (" << end
|
||||||
|
<< ") is outside the file.";
|
||||||
|
return Err(err.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceLocation Start =
|
||||||
|
Sources.getLocForStartOfFile(ID).getLocWithOffset(*offset);
|
||||||
|
SourceLocation End = Start.getLocWithOffset(*length);
|
||||||
|
|
||||||
|
unsigned Offset = Sources.getFileOffset(Start);
|
||||||
|
unsigned Length = Sources.getFileOffset(End) - Offset;
|
||||||
|
|
||||||
|
Ranges.push_back(tooling::Range(Offset, Length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return format_range(std::move(Code), assumedFileName, style,
|
||||||
|
std::move(Ranges));
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto format(const std::string str, const std::string assumedFileName,
|
||||||
|
const std::string style) -> Result {
|
||||||
|
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
|
||||||
|
MemoryBuffer::getMemBuffer(str);
|
||||||
|
|
||||||
|
if (std::error_code EC = CodeOrErr.getError())
|
||||||
|
return Err(EC.message());
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
|
||||||
|
if (Code->getBufferSize() == 0)
|
||||||
|
return Ok(""); // Empty files are formatted correctly.
|
||||||
|
|
||||||
|
std::vector<tooling::Range> Ranges;
|
||||||
|
fillRanges(Code.get(), Ranges);
|
||||||
|
|
||||||
|
return format_range(std::move(Code), assumedFileName, style,
|
||||||
|
std::move(Ranges));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace format
|
||||||
|
} // namespace clang
|
||||||
|
|
||||||
|
auto version() -> std::string {
|
||||||
|
return clang::getClangToolFullVersion("clang-format");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format(const std::string str, const std::string assumedFileName,
|
||||||
|
const std::string style) -> Result {
|
||||||
|
return clang::format::format(str, assumedFileName, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format_byte(const std::string str, const std::string assumedFileName,
|
||||||
|
const std::string style, const std::vector<unsigned> ranges)
|
||||||
|
-> Result {
|
||||||
|
return clang::format::format_range(str, assumedFileName, style, false,
|
||||||
|
std::move(ranges));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format_line(const std::string str, const std::string assumedFileName,
|
||||||
|
const std::string style, const std::vector<unsigned> ranges)
|
||||||
|
-> Result {
|
||||||
|
return clang::format::format_range(str, assumedFileName, style, true,
|
||||||
|
std::move(ranges));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto set_fallback_style(const std::string style) -> void {
|
||||||
|
FallbackStyle = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto set_sort_includes(const bool sort) -> void { SortIncludes = sort; }
|
||||||
|
|
||||||
|
auto dump_config(const std::string style, const std::string FileName,
|
||||||
|
const std::string code) -> Result {
|
||||||
|
llvm::Expected<clang::format::FormatStyle> FormatStyle =
|
||||||
|
clang::format::getStyle(style, FileName, FallbackStyle, code);
|
||||||
|
if (!FormatStyle)
|
||||||
|
return Err(llvm::toString(FormatStyle.takeError()));
|
||||||
|
std::string Config = clang::format::configurationAsText(*FormatStyle);
|
||||||
|
return Ok(Config);
|
||||||
|
}
|
||||||
24
frontend/src/common/prettier/plugins/clang/src/lib.h
Normal file
24
frontend/src/common/prettier/plugins/clang/src/lib.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef CLANG_FORMAT_WASM_LIB_H_
|
||||||
|
#define CLANG_FORMAT_WASM_LIB_H_
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
struct Result {
|
||||||
|
bool error;
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto version() -> std::string;
|
||||||
|
auto format(const std::string str, const std::string assumedFileName, const std::string style) -> Result;
|
||||||
|
auto format_byte(const std::string str,
|
||||||
|
const std::string assumedFileName,
|
||||||
|
const std::string style,
|
||||||
|
const std::vector<unsigned> ranges) -> Result;
|
||||||
|
auto format_line(const std::string str,
|
||||||
|
const std::string assumedFileName,
|
||||||
|
const std::string style,
|
||||||
|
const std::vector<unsigned> ranges) -> Result;
|
||||||
|
auto set_fallback_style(const std::string style) -> void;
|
||||||
|
auto set_sort_includes(const bool sort) -> void;
|
||||||
|
auto dump_config(const std::string style, const std::string FileName, const std::string code) -> Result;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
set -Eeo pipefail
|
||||||
|
|
||||||
|
cd $(dirname $0)/..
|
||||||
|
project_root=$(pwd)
|
||||||
|
|
||||||
|
rm -rf pkg
|
||||||
|
mkdir -p pkg build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
export CC=$(which clang)
|
||||||
|
export CXX=$(which clang++)
|
||||||
|
|
||||||
|
emcmake cmake -G Ninja ..
|
||||||
|
ninja clang-format-wasm
|
||||||
|
|
||||||
|
cd $project_root
|
||||||
|
|
||||||
|
if [[ ! -z "${WASM_OPT}" ]]; then
|
||||||
|
wasm-opt -Os build/clang-format-esm.wasm -o build/clang-format-esm-Os.wasm
|
||||||
|
wasm-opt -Oz build/clang-format-esm.wasm -o build/clang-format-esm-Oz.wasm
|
||||||
|
fi
|
||||||
|
|
||||||
|
SMALLEST_WASM=$(ls -Sr build/clang-format-e*.wasm | head -1)
|
||||||
|
|
||||||
|
cp $SMALLEST_WASM pkg/clang-format.wasm
|
||||||
|
cat src/template.js build/clang-format-esm.js >pkg/clang-format.js
|
||||||
|
|
||||||
|
# add shebang
|
||||||
|
echo '#!/usr/bin/env node' | cat - ./build/clang-format-cli.js >./pkg/clang-format-cli.cjs
|
||||||
|
cp ./build/clang-format-cli.wasm ./pkg/
|
||||||
|
|
||||||
|
cp ./src/clang-format.d.ts src/clang-format-*.js ./pkg/
|
||||||
|
cp ./package.json LICENSE README.md .npmignore ./pkg/
|
||||||
|
|
||||||
|
# copy git-clang-format and clang-format-diff.py
|
||||||
|
cp ./build/_deps/llvm_project-src/clang/tools/clang-format/git-clang-format ./pkg/
|
||||||
|
cp ./build/_deps/llvm_project-src/clang/tools/clang-format/clang-format-diff.py ./pkg/
|
||||||
|
|
||||||
|
ls -lh ./pkg
|
||||||
|
|
||||||
|
# make sure repo is clean
|
||||||
|
# git diff --exit-code
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
diff --git a/src/cli.cc b/src/cli.cc
|
||||||
|
index 2861005..69ec009 100644
|
||||||
|
--- a/src/cli.cc
|
||||||
|
+++ b/src/cli.cc
|
||||||
|
@@ -12,7 +12,7 @@
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
-#include "../../lib/Format/MatchFilePath.h"
|
||||||
|
+#include "clang/../../lib/Format/MatchFilePath.h"
|
||||||
|
#include "clang/Basic/Diagnostic.h"
|
||||||
|
#include "clang/Basic/DiagnosticOptions.h"
|
||||||
|
#include "clang/Basic/FileManager.h"
|
||||||
|
@@ -27,6 +27,8 @@
|
||||||
|
#include "llvm/Support/Process.h"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
+#include "CustomFileSystem.h"
|
||||||
|
+
|
||||||
|
using namespace llvm;
|
||||||
|
using clang::tooling::Replacements;
|
||||||
|
|
||||||
|
@@ -448,9 +450,12 @@ static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ auto RealFS = vfs::getRealFileSystem();
|
||||||
|
+ auto CustomFS = new vfs::CustomFileSystem(RealFS);
|
||||||
|
+ IntrusiveRefCntPtr<vfs::FileSystem> CustomFSPtr(CustomFS);
|
||||||
|
Expected<FormatStyle> FormatStyle =
|
||||||
|
getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer(),
|
||||||
|
- nullptr, WNoErrorList.isSet(WNoError::Unknown));
|
||||||
|
+ CustomFSPtr.get(), WNoErrorList.isSet(WNoError::Unknown));
|
||||||
|
if (!FormatStyle) {
|
||||||
|
llvm::errs() << toString(FormatStyle.takeError()) << "\n";
|
||||||
|
return true;
|
||||||
|
@@ -571,10 +576,15 @@ static int dumpConfig() {
|
||||||
|
}
|
||||||
|
Code = std::move(CodeOrErr.get());
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ auto RealFS = vfs::getRealFileSystem();
|
||||||
|
+ auto CustomFS = new vfs::CustomFileSystem(RealFS);
|
||||||
|
+ IntrusiveRefCntPtr<vfs::FileSystem> CustomFSPtr(CustomFS);
|
||||||
|
+
|
||||||
|
Expected<clang::format::FormatStyle> FormatStyle = clang::format::getStyle(
|
||||||
|
Style,
|
||||||
|
FileNames.empty() || FileNames[0] == "-" ? AssumeFileName : FileNames[0],
|
||||||
|
- FallbackStyle, Code ? Code->getBuffer() : "");
|
||||||
|
+ FallbackStyle, Code ? Code->getBuffer() : "", CustomFSPtr.get());
|
||||||
|
if (!FormatStyle) {
|
||||||
|
llvm::errs() << toString(FormatStyle.takeError()) << "\n";
|
||||||
|
return 1;
|
||||||
|
@@ -607,24 +617,26 @@ static bool isIgnored(StringRef FilePath) {
|
||||||
|
String Path;
|
||||||
|
String AbsPath{FilePath};
|
||||||
|
|
||||||
|
+ auto PathStyle = vfs::getPathStyle();
|
||||||
|
+
|
||||||
|
using namespace llvm::sys::path;
|
||||||
|
- make_absolute(AbsPath);
|
||||||
|
- remove_dots(AbsPath, /*remove_dot_dot=*/true);
|
||||||
|
+ vfs::make_absolute(AbsPath);
|
||||||
|
+ remove_dots(AbsPath, /*remove_dot_dot=*/true, PathStyle);
|
||||||
|
|
||||||
|
- if (StringRef Dir{parent_path(AbsPath)}; PrevDir != Dir) {
|
||||||
|
+ if (StringRef Dir{parent_path(AbsPath, PathStyle)}; PrevDir != Dir) {
|
||||||
|
PrevDir = Dir;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
Path = Dir;
|
||||||
|
- append(Path, ".clang-format-ignore");
|
||||||
|
+ append(Path, PathStyle, ".clang-format-ignore");
|
||||||
|
if (is_regular_file(Path))
|
||||||
|
break;
|
||||||
|
- Dir = parent_path(Dir);
|
||||||
|
+ Dir = parent_path(Dir, PathStyle);
|
||||||
|
if (Dir.empty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- IgnoreDir = convert_to_slash(Dir);
|
||||||
|
+ IgnoreDir = convert_to_slash(Dir, PathStyle);
|
||||||
|
|
||||||
|
std::ifstream IgnoreFile{Path.c_str()};
|
||||||
|
if (!IgnoreFile.good())
|
||||||
|
@@ -644,7 +656,7 @@ static bool isIgnored(StringRef FilePath) {
|
||||||
|
if (IgnoreDir.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
- const auto Pathname{convert_to_slash(AbsPath)};
|
||||||
|
+ const auto Pathname{convert_to_slash(AbsPath, PathStyle)};
|
||||||
|
for (const auto &Pat : Patterns) {
|
||||||
|
const bool IsNegated = Pat[0] == '!';
|
||||||
|
StringRef Pattern{Pat};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
current_dir=$(pwd)
|
||||||
|
tmp_dir=$(mktemp -d)
|
||||||
|
|
||||||
|
cd $tmp_dir
|
||||||
|
|
||||||
|
git init
|
||||||
|
|
||||||
|
cp $current_dir/build/_deps/llvm_project-src/clang/tools/clang-format/ClangFormat.cpp ./cli.cc
|
||||||
|
|
||||||
|
git add -f .
|
||||||
|
git commit -m "init"
|
||||||
|
|
||||||
|
cp $current_dir/src/cli.cc ./cli.cc
|
||||||
|
|
||||||
|
git add -f .
|
||||||
|
git diff \
|
||||||
|
--cached \
|
||||||
|
--no-color \
|
||||||
|
--ignore-space-at-eol \
|
||||||
|
--no-ext-diff \
|
||||||
|
--src-prefix=a/src/ \
|
||||||
|
--dst-prefix=b/src/ \
|
||||||
|
>$current_dir/scripts/cli.patch || true
|
||||||
|
|
||||||
|
rm -rf $tmp_dir
|
||||||
|
|
||||||
146
frontend/src/common/prettier/plugins/clang/src/template.js
Normal file
146
frontend/src/common/prettier/plugins/clang/src/template.js
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/* @ts-self-types="./clang-format.d.ts" */
|
||||||
|
async function load(module) {
|
||||||
|
if (typeof Response === "function" && module instanceof Response) {
|
||||||
|
if ("compileStreaming" in WebAssembly) {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.compileStreaming(module);
|
||||||
|
} catch (e) {
|
||||||
|
if (module.headers.get("Content-Type") !== "application/wasm") {
|
||||||
|
console.warn(
|
||||||
|
"`WebAssembly.compileStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return module.arrayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wasm;
|
||||||
|
export default async function initAsync(input) {
|
||||||
|
if (wasm !== undefined) {
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof input === "undefined") {
|
||||||
|
input = new URL("clang-format.wasm", import.meta.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof input === "string" ||
|
||||||
|
(typeof Request === "function" && input instanceof Request) ||
|
||||||
|
(typeof URL === "function" && input instanceof URL)
|
||||||
|
) {
|
||||||
|
input = fetch(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm = await load(await input).then((wasm) => Module({ wasm }));
|
||||||
|
assert_init = () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_init() {
|
||||||
|
throw new Error("uninit");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function version() {
|
||||||
|
assert_init();
|
||||||
|
return wasm.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function set_fallback_style(style) {
|
||||||
|
assert_init();
|
||||||
|
wasm.set_fallback_style(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function set_sort_includes(sort) {
|
||||||
|
assert_init();
|
||||||
|
wasm.set_sort_includes(sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unwrap(result) {
|
||||||
|
const { error, content } = result;
|
||||||
|
if (error) {
|
||||||
|
throw Error(content);
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function format(content, filename = "<stdin>", style = "LLVM") {
|
||||||
|
assert_init();
|
||||||
|
const result = wasm.format(content, filename, style);
|
||||||
|
return unwrap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function format_line_range(
|
||||||
|
content,
|
||||||
|
range,
|
||||||
|
filename = "<stdin>",
|
||||||
|
style = "LLVM",
|
||||||
|
) {
|
||||||
|
assert_init();
|
||||||
|
const rangeList = new wasm.RangeList();
|
||||||
|
for (const [fromLine, toLine] of range) {
|
||||||
|
if (fromLine < 1) {
|
||||||
|
throw Error("start line should be at least 1");
|
||||||
|
}
|
||||||
|
if (fromLine > toLine) {
|
||||||
|
throw Error("start line should not exceed end line");
|
||||||
|
}
|
||||||
|
rangeList.push_back(fromLine);
|
||||||
|
rangeList.push_back(toLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = wasm.format_line(content, filename, style, rangeList);
|
||||||
|
rangeList.delete();
|
||||||
|
return unwrap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function format_byte_range(
|
||||||
|
content,
|
||||||
|
range,
|
||||||
|
filename = "<stdin>",
|
||||||
|
style = "LLVM",
|
||||||
|
) {
|
||||||
|
assert_init();
|
||||||
|
const rangeList = new wasm.RangeList();
|
||||||
|
|
||||||
|
if (range.length === 1 && range[0].length === 1) {
|
||||||
|
rangeList.push_back(range[0][0]);
|
||||||
|
} else {
|
||||||
|
for (const [offset, length] of range) {
|
||||||
|
if (offset < 0) {
|
||||||
|
throw Error("start offset should be at least 0");
|
||||||
|
}
|
||||||
|
if (length < 0) {
|
||||||
|
throw Error("length should be at least 0");
|
||||||
|
}
|
||||||
|
rangeList.push_back(offset);
|
||||||
|
rangeList.push_back(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = wasm.format_byte(content, filename, style, rangeList);
|
||||||
|
rangeList.delete();
|
||||||
|
return unwrap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dump_config({
|
||||||
|
style = "file",
|
||||||
|
filename = "<stdin>",
|
||||||
|
code = "",
|
||||||
|
} = {}) {
|
||||||
|
assert_init();
|
||||||
|
const result = wasm.dump_config(style, filename, code);
|
||||||
|
return unwrap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
format_byte_range as formatByteRange,
|
||||||
|
format_line_range as formatLineRange,
|
||||||
|
};
|
||||||
32
frontend/src/common/prettier/plugins/dart/dart_fmt.d.ts
vendored
Normal file
32
frontend/src/common/prettier/plugins/dart/dart_fmt.d.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
export function format(input: string, filename: string, config?: LayoutConfig): string;
|
||||||
|
|
||||||
|
interface LayoutConfig {
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
language_version?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
export type InitOutput = unknown;
|
||||||
|
|
||||||
|
// export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||||
|
// /**
|
||||||
|
// * Instantiates the given `module`, which can either be bytes or
|
||||||
|
// * a precompiled `WebAssembly.Module`.
|
||||||
|
// *
|
||||||
|
// * @param {SyncInitInput} module
|
||||||
|
// *
|
||||||
|
// * @returns {InitOutput}
|
||||||
|
// */
|
||||||
|
// export function initSync(module: SyncInitInput): InitOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
|
*
|
||||||
|
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||||
|
*
|
||||||
|
* @returns {Promise<InitOutput>}
|
||||||
|
*/
|
||||||
|
export default function init(module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||||
84
frontend/src/common/prettier/plugins/dart/dart_fmt.js
Normal file
84
frontend/src/common/prettier/plugins/dart/dart_fmt.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { format as dart_fmt, instantiate, invoke } from "./dart_fmt.mjs";
|
||||||
|
|
||||||
|
let wasm;
|
||||||
|
|
||||||
|
function get_imports() {}
|
||||||
|
function init_memory() {}
|
||||||
|
|
||||||
|
function normalize(module) {
|
||||||
|
if (!(module instanceof WebAssembly.Module)) {
|
||||||
|
return new WebAssembly.Module(module);
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function (input) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
if (typeof input === "undefined") {
|
||||||
|
input = new URL("dart_fmt.wasm", import.meta.url);
|
||||||
|
}
|
||||||
|
const imports = get_imports();
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof input === "string" ||
|
||||||
|
(typeof Request === "function" && input instanceof Request) ||
|
||||||
|
(typeof URL === "function" && input instanceof URL)
|
||||||
|
) {
|
||||||
|
input = fetch(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_memory(imports);
|
||||||
|
|
||||||
|
wasm = await load(await input)
|
||||||
|
.then(normalize)
|
||||||
|
.then(instantiate);
|
||||||
|
|
||||||
|
invoke(wasm);
|
||||||
|
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function load(module) {
|
||||||
|
if (typeof Response === "function" && module instanceof Response) {
|
||||||
|
if ("compileStreaming" in WebAssembly) {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.compileStreaming(module);
|
||||||
|
} catch (e) {
|
||||||
|
if (module.headers.get("Content-Type") != "application/wasm") {
|
||||||
|
console.warn(
|
||||||
|
"`WebAssembly.compileStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return module.arrayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function format(source, filename = "stdin.dart", config = {}) {
|
||||||
|
const options = { lineEnding: "\n" };
|
||||||
|
if (config.line_width) {
|
||||||
|
options.pageWidth = config.line_width;
|
||||||
|
}
|
||||||
|
if (options.line_ending === "crlf") {
|
||||||
|
options.lineEnding = "\r\n";
|
||||||
|
}
|
||||||
|
if(options.language_version) {
|
||||||
|
options.languageVersion = options.language_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = dart_fmt(source, filename, JSON.stringify(options));
|
||||||
|
const err = result[0] === "x";
|
||||||
|
const output = result.slice(1);
|
||||||
|
if (err) {
|
||||||
|
throw new Error(output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
350
frontend/src/common/prettier/plugins/dart/dart_fmt.mjs
Normal file
350
frontend/src/common/prettier/plugins/dart/dart_fmt.mjs
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
|
||||||
|
// `modulePromise` is a promise to the `WebAssembly.module` object to be
|
||||||
|
// instantiated.
|
||||||
|
// `importObjectPromise` is a promise to an object that contains any additional
|
||||||
|
// imports needed by the module that aren't provided by the standard runtime.
|
||||||
|
// The fields on this object will be merged into the importObject with which
|
||||||
|
// the module will be instantiated.
|
||||||
|
// This function returns a promise to the instantiated module.
|
||||||
|
export const instantiate = async (modulePromise, importObjectPromise) => {
|
||||||
|
let dartInstance;
|
||||||
|
|
||||||
|
// Prints to the console
|
||||||
|
function printToConsole(value) {
|
||||||
|
if (typeof dartPrint == "function") {
|
||||||
|
dartPrint(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof console == "object" && typeof console.log != "undefined") {
|
||||||
|
console.log(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof print == "function") {
|
||||||
|
print(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "Unable to print message: " + js;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a Dart List to a JS array. Any Dart objects will be converted, but
|
||||||
|
// this will be cheap for JSValues.
|
||||||
|
function arrayFromDartList(constructor, list) {
|
||||||
|
const exports = dartInstance.exports;
|
||||||
|
const read = exports.$listRead;
|
||||||
|
const length = exports.$listLength(list);
|
||||||
|
const array = new constructor(length);
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
array[i] = read(list, i);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A special symbol attached to functions that wrap Dart functions.
|
||||||
|
const jsWrappedDartFunctionSymbol = Symbol("JSWrappedDartFunction");
|
||||||
|
|
||||||
|
function finalizeWrapper(dartFunction, wrapped) {
|
||||||
|
wrapped.dartFunction = dartFunction;
|
||||||
|
wrapped[jsWrappedDartFunctionSymbol] = true;
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports
|
||||||
|
const dart2wasm = {
|
||||||
|
|
||||||
|
_49: v => v.toString(),
|
||||||
|
_64: s => {
|
||||||
|
if (!/^\s*[+-]?(?:Infinity|NaN|(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(s)) {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
return parseFloat(s);
|
||||||
|
},
|
||||||
|
_65: () => {
|
||||||
|
let stackString = new Error().stack.toString();
|
||||||
|
let frames = stackString.split('\n');
|
||||||
|
let drop = 2;
|
||||||
|
if (frames[0] === 'Error') {
|
||||||
|
drop += 1;
|
||||||
|
}
|
||||||
|
return frames.slice(drop).join('\n');
|
||||||
|
},
|
||||||
|
_69: () => {
|
||||||
|
// On browsers return `globalThis.location.href`
|
||||||
|
if (globalThis.location != null) {
|
||||||
|
return globalThis.location.href;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
_70: () => {
|
||||||
|
return typeof process != "undefined" &&
|
||||||
|
Object.prototype.toString.call(process) == "[object process]" &&
|
||||||
|
process.platform == "win32"
|
||||||
|
},
|
||||||
|
_85: s => JSON.stringify(s),
|
||||||
|
_86: s => printToConsole(s),
|
||||||
|
_87: a => a.join(''),
|
||||||
|
_90: (s, t) => s.split(t),
|
||||||
|
_91: s => s.toLowerCase(),
|
||||||
|
_92: s => s.toUpperCase(),
|
||||||
|
_93: s => s.trim(),
|
||||||
|
_97: (s, p, i) => s.indexOf(p, i),
|
||||||
|
_98: (s, p, i) => s.lastIndexOf(p, i),
|
||||||
|
_100: Object.is,
|
||||||
|
_101: s => s.toUpperCase(),
|
||||||
|
_102: s => s.toLowerCase(),
|
||||||
|
_103: (a, i) => a.push(i),
|
||||||
|
_113: (a, b) => a == b ? 0 : (a > b ? 1 : -1),
|
||||||
|
_114: a => a.length,
|
||||||
|
_116: (a, i) => a[i],
|
||||||
|
_117: (a, i, v) => a[i] = v,
|
||||||
|
_120: (o, start, length) => new Uint8Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_121: (o, start, length) => new Int8Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_122: (o, start, length) => new Uint8ClampedArray(o.buffer, o.byteOffset + start, length),
|
||||||
|
_123: (o, start, length) => new Uint16Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_124: (o, start, length) => new Int16Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_125: (o, start, length) => new Uint32Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_126: (o, start, length) => new Int32Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_129: (o, start, length) => new Float32Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_130: (o, start, length) => new Float64Array(o.buffer, o.byteOffset + start, length),
|
||||||
|
_133: (o) => new DataView(o.buffer, o.byteOffset, o.byteLength),
|
||||||
|
_137: Function.prototype.call.bind(Object.getOwnPropertyDescriptor(DataView.prototype, 'byteLength').get),
|
||||||
|
_138: (b, o) => new DataView(b, o),
|
||||||
|
_140: Function.prototype.call.bind(DataView.prototype.getUint8),
|
||||||
|
_141: Function.prototype.call.bind(DataView.prototype.setUint8),
|
||||||
|
_142: Function.prototype.call.bind(DataView.prototype.getInt8),
|
||||||
|
_143: Function.prototype.call.bind(DataView.prototype.setInt8),
|
||||||
|
_144: Function.prototype.call.bind(DataView.prototype.getUint16),
|
||||||
|
_145: Function.prototype.call.bind(DataView.prototype.setUint16),
|
||||||
|
_146: Function.prototype.call.bind(DataView.prototype.getInt16),
|
||||||
|
_147: Function.prototype.call.bind(DataView.prototype.setInt16),
|
||||||
|
_148: Function.prototype.call.bind(DataView.prototype.getUint32),
|
||||||
|
_149: Function.prototype.call.bind(DataView.prototype.setUint32),
|
||||||
|
_150: Function.prototype.call.bind(DataView.prototype.getInt32),
|
||||||
|
_151: Function.prototype.call.bind(DataView.prototype.setInt32),
|
||||||
|
_156: Function.prototype.call.bind(DataView.prototype.getFloat32),
|
||||||
|
_157: Function.prototype.call.bind(DataView.prototype.setFloat32),
|
||||||
|
_158: Function.prototype.call.bind(DataView.prototype.getFloat64),
|
||||||
|
_159: Function.prototype.call.bind(DataView.prototype.setFloat64),
|
||||||
|
_165: x0 => format = x0,
|
||||||
|
_166: f => finalizeWrapper(f, function(x0,x1,x2) { return dartInstance.exports._166(f,arguments.length,x0,x1,x2) }),
|
||||||
|
_184: (c) =>
|
||||||
|
queueMicrotask(() => dartInstance.exports.$invokeCallback(c)),
|
||||||
|
_187: (s, m) => {
|
||||||
|
try {
|
||||||
|
return new RegExp(s, m);
|
||||||
|
} catch (e) {
|
||||||
|
return String(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_188: (x0,x1) => x0.exec(x1),
|
||||||
|
_189: (x0,x1) => x0.test(x1),
|
||||||
|
_190: (x0,x1) => x0.exec(x1),
|
||||||
|
_191: (x0,x1) => x0.exec(x1),
|
||||||
|
_192: x0 => x0.pop(),
|
||||||
|
_198: o => o === undefined,
|
||||||
|
_199: o => typeof o === 'boolean',
|
||||||
|
_200: o => typeof o === 'number',
|
||||||
|
_202: o => typeof o === 'string',
|
||||||
|
_205: o => o instanceof Int8Array,
|
||||||
|
_206: o => o instanceof Uint8Array,
|
||||||
|
_207: o => o instanceof Uint8ClampedArray,
|
||||||
|
_208: o => o instanceof Int16Array,
|
||||||
|
_209: o => o instanceof Uint16Array,
|
||||||
|
_210: o => o instanceof Int32Array,
|
||||||
|
_211: o => o instanceof Uint32Array,
|
||||||
|
_212: o => o instanceof Float32Array,
|
||||||
|
_213: o => o instanceof Float64Array,
|
||||||
|
_214: o => o instanceof ArrayBuffer,
|
||||||
|
_215: o => o instanceof DataView,
|
||||||
|
_216: o => o instanceof Array,
|
||||||
|
_217: o => typeof o === 'function' && o[jsWrappedDartFunctionSymbol] === true,
|
||||||
|
_220: o => o instanceof RegExp,
|
||||||
|
_221: (l, r) => l === r,
|
||||||
|
_222: o => o,
|
||||||
|
_223: o => o,
|
||||||
|
_224: o => o,
|
||||||
|
_225: b => !!b,
|
||||||
|
_226: o => o.length,
|
||||||
|
_229: (o, i) => o[i],
|
||||||
|
_230: f => f.dartFunction,
|
||||||
|
_231: l => arrayFromDartList(Int8Array, l),
|
||||||
|
_232: (data, length) => {
|
||||||
|
const jsBytes = new Uint8Array(length);
|
||||||
|
const getByte = dartInstance.exports.$uint8ListGet;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
jsBytes[i] = getByte(data, i);
|
||||||
|
}
|
||||||
|
return jsBytes;
|
||||||
|
},
|
||||||
|
_233: l => arrayFromDartList(Uint8ClampedArray, l),
|
||||||
|
_234: l => arrayFromDartList(Int16Array, l),
|
||||||
|
_235: l => arrayFromDartList(Uint16Array, l),
|
||||||
|
_236: l => arrayFromDartList(Int32Array, l),
|
||||||
|
_237: l => arrayFromDartList(Uint32Array, l),
|
||||||
|
_238: l => arrayFromDartList(Float32Array, l),
|
||||||
|
_239: l => arrayFromDartList(Float64Array, l),
|
||||||
|
_240: (data, length) => {
|
||||||
|
const read = dartInstance.exports.$byteDataGetUint8;
|
||||||
|
const view = new DataView(new ArrayBuffer(length));
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
view.setUint8(i, read(data, i));
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
},
|
||||||
|
_241: l => arrayFromDartList(Array, l),
|
||||||
|
_242: (s, length) => {
|
||||||
|
if (length == 0) return '';
|
||||||
|
|
||||||
|
const read = dartInstance.exports.$stringRead1;
|
||||||
|
let result = '';
|
||||||
|
let index = 0;
|
||||||
|
const chunkLength = Math.min(length - index, 500);
|
||||||
|
let array = new Array(chunkLength);
|
||||||
|
while (index < length) {
|
||||||
|
const newChunkLength = Math.min(length - index, 500);
|
||||||
|
for (let i = 0; i < newChunkLength; i++) {
|
||||||
|
array[i] = read(s, index++);
|
||||||
|
}
|
||||||
|
if (newChunkLength < chunkLength) {
|
||||||
|
array = array.slice(0, newChunkLength);
|
||||||
|
}
|
||||||
|
result += String.fromCharCode(...array);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
,
|
||||||
|
_243: (s, length) => {
|
||||||
|
if (length == 0) return '';
|
||||||
|
|
||||||
|
const read = dartInstance.exports.$stringRead2;
|
||||||
|
let result = '';
|
||||||
|
let index = 0;
|
||||||
|
const chunkLength = Math.min(length - index, 500);
|
||||||
|
let array = new Array(chunkLength);
|
||||||
|
while (index < length) {
|
||||||
|
const newChunkLength = Math.min(length - index, 500);
|
||||||
|
for (let i = 0; i < newChunkLength; i++) {
|
||||||
|
array[i] = read(s, index++);
|
||||||
|
}
|
||||||
|
if (newChunkLength < chunkLength) {
|
||||||
|
array = array.slice(0, newChunkLength);
|
||||||
|
}
|
||||||
|
result += String.fromCharCode(...array);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
,
|
||||||
|
_244: (s) => {
|
||||||
|
let length = s.length;
|
||||||
|
let range = 0;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
range |= s.codePointAt(i);
|
||||||
|
}
|
||||||
|
const exports = dartInstance.exports;
|
||||||
|
if (range < 256) {
|
||||||
|
if (length <= 10) {
|
||||||
|
if (length == 1) {
|
||||||
|
return exports.$stringAllocate1_1(s.codePointAt(0));
|
||||||
|
}
|
||||||
|
if (length == 2) {
|
||||||
|
return exports.$stringAllocate1_2(s.codePointAt(0), s.codePointAt(1));
|
||||||
|
}
|
||||||
|
if (length == 3) {
|
||||||
|
return exports.$stringAllocate1_3(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2));
|
||||||
|
}
|
||||||
|
if (length == 4) {
|
||||||
|
return exports.$stringAllocate1_4(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3));
|
||||||
|
}
|
||||||
|
if (length == 5) {
|
||||||
|
return exports.$stringAllocate1_5(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4));
|
||||||
|
}
|
||||||
|
if (length == 6) {
|
||||||
|
return exports.$stringAllocate1_6(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4), s.codePointAt(5));
|
||||||
|
}
|
||||||
|
if (length == 7) {
|
||||||
|
return exports.$stringAllocate1_7(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4), s.codePointAt(5), s.codePointAt(6));
|
||||||
|
}
|
||||||
|
if (length == 8) {
|
||||||
|
return exports.$stringAllocate1_8(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4), s.codePointAt(5), s.codePointAt(6), s.codePointAt(7));
|
||||||
|
}
|
||||||
|
if (length == 9) {
|
||||||
|
return exports.$stringAllocate1_9(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4), s.codePointAt(5), s.codePointAt(6), s.codePointAt(7), s.codePointAt(8));
|
||||||
|
}
|
||||||
|
if (length == 10) {
|
||||||
|
return exports.$stringAllocate1_10(s.codePointAt(0), s.codePointAt(1), s.codePointAt(2), s.codePointAt(3), s.codePointAt(4), s.codePointAt(5), s.codePointAt(6), s.codePointAt(7), s.codePointAt(8), s.codePointAt(9));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const dartString = exports.$stringAllocate1(length);
|
||||||
|
const write = exports.$stringWrite1;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
write(dartString, i, s.codePointAt(i));
|
||||||
|
}
|
||||||
|
return dartString;
|
||||||
|
} else {
|
||||||
|
const dartString = exports.$stringAllocate2(length);
|
||||||
|
const write = exports.$stringWrite2;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
write(dartString, i, s.charCodeAt(i));
|
||||||
|
}
|
||||||
|
return dartString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,
|
||||||
|
_247: l => new Array(l),
|
||||||
|
_251: (o, p) => o[p],
|
||||||
|
_255: o => String(o),
|
||||||
|
_260: x0 => x0.index,
|
||||||
|
_262: x0 => x0.length,
|
||||||
|
_264: (x0,x1) => x0[x1],
|
||||||
|
_265: (x0,x1) => x0.exec(x1),
|
||||||
|
_267: x0 => x0.flags,
|
||||||
|
_268: x0 => x0.multiline,
|
||||||
|
_269: x0 => x0.ignoreCase,
|
||||||
|
_270: x0 => x0.unicode,
|
||||||
|
_271: x0 => x0.dotAll,
|
||||||
|
_272: (x0,x1) => x0.lastIndex = x1
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseImports = {
|
||||||
|
dart2wasm: dart2wasm,
|
||||||
|
|
||||||
|
|
||||||
|
Math: Math,
|
||||||
|
Date: Date,
|
||||||
|
Object: Object,
|
||||||
|
Array: Array,
|
||||||
|
Reflect: Reflect,
|
||||||
|
};
|
||||||
|
|
||||||
|
const jsStringPolyfill = {
|
||||||
|
"charCodeAt": (s, i) => s.charCodeAt(i),
|
||||||
|
"compare": (s1, s2) => {
|
||||||
|
if (s1 < s2) return -1;
|
||||||
|
if (s1 > s2) return 1;
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
"concat": (s1, s2) => s1 + s2,
|
||||||
|
"equals": (s1, s2) => s1 === s2,
|
||||||
|
"fromCharCode": (i) => String.fromCharCode(i),
|
||||||
|
"length": (s) => s?.length||0,
|
||||||
|
"substring": (s, a, b) => s.substring(a, b),
|
||||||
|
};
|
||||||
|
|
||||||
|
dartInstance = await WebAssembly.instantiate(await modulePromise, {
|
||||||
|
...baseImports,
|
||||||
|
...(await importObjectPromise),
|
||||||
|
"wasm:js-string": jsStringPolyfill,
|
||||||
|
});
|
||||||
|
|
||||||
|
return dartInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the main function for the instantiated module
|
||||||
|
// `moduleInstance` is the instantiated dart2wasm module
|
||||||
|
// `args` are any arguments that should be passed into the main function.
|
||||||
|
export const invoke = (moduleInstance, ...args) => {
|
||||||
|
moduleInstance.exports.$invokeMain(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export let format;
|
||||||
BIN
frontend/src/common/prettier/plugins/dart/dart_fmt.unopt.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/dart/dart_fmt.unopt.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
frontend/src/common/prettier/plugins/dart/dart_fmt.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/dart/dart_fmt.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
10
frontend/src/common/prettier/plugins/dart/dart_fmt_node.js
Normal file
10
frontend/src/common/prettier/plugins/dart/dart_fmt_node.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./dart_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./dart_fmt.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = fs.readFile(wasm)) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./dart_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./dart_fmt.js";
|
||||||
|
import wasm from "./dart_fmt.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = wasm) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./dart_fmt.js";
|
||||||
132
frontend/src/common/prettier/plugins/dart/index.ts
Normal file
132
frontend/src/common/prettier/plugins/dart/index.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for Dart formatting using dart_fmt WebAssembly
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting Dart files using the dart_fmt WASM implementation.
|
||||||
|
* dart_fmt is the official Dart code formatter integrated into the Dart SDK.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer } from 'prettier';
|
||||||
|
|
||||||
|
// Import the Dart formatter WASM module
|
||||||
|
import dartInit, { format } from './dart_fmt_vite.js';
|
||||||
|
|
||||||
|
const parserName = 'dart';
|
||||||
|
|
||||||
|
// Language configuration
|
||||||
|
const languages = [
|
||||||
|
{
|
||||||
|
name: 'Dart',
|
||||||
|
aliases: ['dart'],
|
||||||
|
parsers: [parserName],
|
||||||
|
extensions: ['.dart'],
|
||||||
|
aceMode: 'dart',
|
||||||
|
tmScope: 'source.dart',
|
||||||
|
linguistLanguageId: 103,
|
||||||
|
vscodeLanguageIds: ['dart']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Parser configuration
|
||||||
|
const dartParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (node: string) => node.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lazy initialize Dart WASM module
|
||||||
|
let initPromise: Promise<void> | null = null;
|
||||||
|
let isInitialized = false;
|
||||||
|
|
||||||
|
function initDart(): Promise<void> {
|
||||||
|
if (isInitialized) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initPromise) {
|
||||||
|
initPromise = (async () => {
|
||||||
|
try {
|
||||||
|
await dartInit();
|
||||||
|
isInitialized = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to initialize Dart WASM module:', error);
|
||||||
|
initPromise = null;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printer configuration
|
||||||
|
const dartPrinter: Printer<string> = {
|
||||||
|
// @ts-expect-error -- Support async printer like shell plugin
|
||||||
|
async print(path, options) {
|
||||||
|
try {
|
||||||
|
// Wait for initialization to complete
|
||||||
|
await initDart();
|
||||||
|
|
||||||
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
const config = getDartConfig(options);
|
||||||
|
|
||||||
|
// Format using dart_fmt (synchronous call)
|
||||||
|
const formatted = format(text, undefined, config);
|
||||||
|
|
||||||
|
return formatted.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Dart formatting failed:', error);
|
||||||
|
// Return original text if formatting fails
|
||||||
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function to create Dart config from Prettier options
|
||||||
|
function getDartConfig(options: any): any {
|
||||||
|
const config: any = {};
|
||||||
|
|
||||||
|
// Map Prettier options to Dart formatter config
|
||||||
|
if (options.printWidth !== undefined) {
|
||||||
|
config.line_width = options.printWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.endOfLine !== undefined) {
|
||||||
|
config.line_ending = options.endOfLine === 'crlf' ? 'crlf' : 'lf';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dart language version (if specified)
|
||||||
|
if (options.dartLanguageVersion !== undefined) {
|
||||||
|
config.language_version = options.dartLanguageVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin options
|
||||||
|
const options = {
|
||||||
|
dartLanguageVersion: {
|
||||||
|
since: '0.0.1',
|
||||||
|
category: 'Format' as const,
|
||||||
|
type: 'string' as const,
|
||||||
|
default: undefined,
|
||||||
|
description: 'Dart language version (e.g., "3.0", "2.17")'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Plugin object
|
||||||
|
const dartPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers: {
|
||||||
|
[parserName]: dartParser,
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
[parserName]: dartPrinter,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default dartPlugin;
|
||||||
|
export { languages };
|
||||||
|
export const parsers = dartPlugin.parsers;
|
||||||
|
export const printers = dartPlugin.printers;
|
||||||
31
frontend/src/common/prettier/plugins/dart/lib/binding.dart
Normal file
31
frontend/src/common/prettier/plugins/dart/lib/binding.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:js_interop';
|
||||||
|
import 'package:dart_fmt/dart_fmt.dart';
|
||||||
|
|
||||||
|
class Options {
|
||||||
|
final int? pageWidth;
|
||||||
|
final String? lineEnding;
|
||||||
|
final String? languageVersion;
|
||||||
|
|
||||||
|
Options.fromJson(Map<String, dynamic> json)
|
||||||
|
: pageWidth = json['pageWidth'] as int?,
|
||||||
|
lineEnding = json['lineEnding'] as String?,
|
||||||
|
languageVersion = json['languageVersion'] as String?;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatWrapper(String source, String filename, String options) {
|
||||||
|
final config = Options.fromJson(jsonDecode(options));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return "o${format(source, filename, pageWidth: config.pageWidth, lineEnding: config.lineEnding, version: config.languageVersion)}";
|
||||||
|
} catch (e) {
|
||||||
|
return "x$e";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JS('format')
|
||||||
|
external set formatExport(JSFunction handler);
|
||||||
|
|
||||||
|
void main(List<String> arguments) {
|
||||||
|
formatExport = formatWrapper.toJS;
|
||||||
|
}
|
||||||
5
frontend/src/common/prettier/plugins/dart/lib/build.sh
Normal file
5
frontend/src/common/prettier/plugins/dart/lib/build.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
dart compile wasm ./lib/binding.dart -o ./build/dart_fmt.wasm
|
||||||
|
|
||||||
|
|
||||||
14
frontend/src/common/prettier/plugins/dart/lib/dart_fmt.dart
Normal file
14
frontend/src/common/prettier/plugins/dart/lib/dart_fmt.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:dart_style/dart_style.dart';
|
||||||
|
import 'package:pub_semver/pub_semver.dart';
|
||||||
|
|
||||||
|
String format(String source, String filename,
|
||||||
|
{int? pageWidth, String? lineEnding, String? version}) {
|
||||||
|
final languageVersion = version != null
|
||||||
|
? Version.parse(version)
|
||||||
|
: DartFormatter.latestLanguageVersion;
|
||||||
|
final formatter = DartFormatter(
|
||||||
|
pageWidth: pageWidth,
|
||||||
|
lineEnding: lineEnding,
|
||||||
|
languageVersion: languageVersion);
|
||||||
|
return formatter.format(source, uri: filename);
|
||||||
|
}
|
||||||
10
frontend/src/common/prettier/plugins/go/gofmt.d.ts
vendored
Normal file
10
frontend/src/common/prettier/plugins/go/gofmt.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export type InitInput =
|
||||||
|
| RequestInfo
|
||||||
|
| URL
|
||||||
|
| Response
|
||||||
|
| BufferSource
|
||||||
|
| WebAssembly.Module;
|
||||||
|
|
||||||
|
export default function initAsync(wasm_url?: InitInput): Promise<void>;
|
||||||
|
export declare function initSync(module: BufferSource | WebAssembly.Module): void;
|
||||||
|
export declare function format(input: string): string;
|
||||||
355
frontend/src/common/prettier/plugins/go/gofmt.js
Normal file
355
frontend/src/common/prettier/plugins/go/gofmt.js
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// This file has been modified for use by the TinyGo compiler.
|
||||||
|
|
||||||
|
const encoder = new TextEncoder("utf-8");
|
||||||
|
const decoder = new TextDecoder("utf-8");
|
||||||
|
let reinterpretBuf = new DataView(new ArrayBuffer(8));
|
||||||
|
var logLine = [];
|
||||||
|
|
||||||
|
class TinyGo {
|
||||||
|
constructor() {
|
||||||
|
this._callbackTimeouts = new Map();
|
||||||
|
this._nextCallbackTimeoutID = 1;
|
||||||
|
|
||||||
|
const mem = () => {
|
||||||
|
// The buffer may change when requesting more memory.
|
||||||
|
return new DataView(this._inst.exports.memory.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unboxValue = (v_ref) => {
|
||||||
|
reinterpretBuf.setBigInt64(0, v_ref, true);
|
||||||
|
const f = reinterpretBuf.getFloat64(0, true);
|
||||||
|
if (f === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (!isNaN(f)) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = v_ref & 0xffffffffn;
|
||||||
|
return this._values[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const loadValue = (addr) => {
|
||||||
|
let v_ref = mem().getBigUint64(addr, true);
|
||||||
|
return unboxValue(v_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
const boxValue = (v) => {
|
||||||
|
const nanHead = 0x7FF80000n;
|
||||||
|
|
||||||
|
if (typeof v === "number") {
|
||||||
|
if (isNaN(v)) {
|
||||||
|
return nanHead << 32n;
|
||||||
|
}
|
||||||
|
if (v === 0) {
|
||||||
|
return (nanHead << 32n) | 1n;
|
||||||
|
}
|
||||||
|
reinterpretBuf.setFloat64(0, v, true);
|
||||||
|
return reinterpretBuf.getBigInt64(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (v) {
|
||||||
|
case undefined:
|
||||||
|
return 0n;
|
||||||
|
case null:
|
||||||
|
return (nanHead << 32n) | 2n;
|
||||||
|
case true:
|
||||||
|
return (nanHead << 32n) | 3n;
|
||||||
|
case false:
|
||||||
|
return (nanHead << 32n) | 4n;
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = this._ids.get(v);
|
||||||
|
if (id === undefined) {
|
||||||
|
id = this._idPool.pop();
|
||||||
|
if (id === undefined) {
|
||||||
|
id = BigInt(this._values.length);
|
||||||
|
}
|
||||||
|
this._values[id] = v;
|
||||||
|
this._goRefCounts[id] = 0;
|
||||||
|
this._ids.set(v, id);
|
||||||
|
}
|
||||||
|
this._goRefCounts[id]++;
|
||||||
|
let typeFlag = 1n;
|
||||||
|
switch (typeof v) {
|
||||||
|
case "string":
|
||||||
|
typeFlag = 2n;
|
||||||
|
break;
|
||||||
|
case "symbol":
|
||||||
|
typeFlag = 3n;
|
||||||
|
break;
|
||||||
|
case "function":
|
||||||
|
typeFlag = 4n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return id | ((nanHead | typeFlag) << 32n);
|
||||||
|
}
|
||||||
|
|
||||||
|
const storeValue = (addr, v) => {
|
||||||
|
let v_ref = boxValue(v);
|
||||||
|
mem().setBigUint64(addr, v_ref, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadSlice = (array, len, cap) => {
|
||||||
|
return new Uint8Array(this._inst.exports.memory.buffer, array, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadSliceOfValues = (array, len, cap) => {
|
||||||
|
const a = new Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
a[i] = loadValue(array + i * 8);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadString = (ptr, len) => {
|
||||||
|
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeOrigin = Date.now() - performance.now();
|
||||||
|
this.importObject = {
|
||||||
|
wasi_snapshot_preview1: {
|
||||||
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
||||||
|
fd_write: () => 0, // dummy
|
||||||
|
},
|
||||||
|
gojs: {
|
||||||
|
// func ticks() float64
|
||||||
|
"runtime.ticks": () => {
|
||||||
|
return timeOrigin + performance.now();
|
||||||
|
},
|
||||||
|
|
||||||
|
// func finalizeRef(v ref)
|
||||||
|
"syscall/js.finalizeRef": (v_ref) => {
|
||||||
|
reinterpretBuf.setBigInt64(0, v_ref, true);
|
||||||
|
const f = reinterpretBuf.getFloat64(0, true);
|
||||||
|
if (f === 0 || !isNaN(f)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = v_ref & 0xffffffffn;
|
||||||
|
this._goRefCounts[id]--;
|
||||||
|
if (this._goRefCounts[id] === 0) {
|
||||||
|
const v = this._values[id];
|
||||||
|
this._values[id] = null;
|
||||||
|
this._ids.delete(v);
|
||||||
|
this._idPool.push(id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// func stringVal(value string) ref
|
||||||
|
"syscall/js.stringVal": (value_ptr, value_len) => {
|
||||||
|
const s = loadString(value_ptr, value_len);
|
||||||
|
return boxValue(s);
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueGet(v ref, p string) ref
|
||||||
|
"syscall/js.valueGet": (v_ref, p_ptr, p_len) => {
|
||||||
|
let prop = loadString(p_ptr, p_len);
|
||||||
|
let v = unboxValue(v_ref);
|
||||||
|
let result = Reflect.get(v, prop);
|
||||||
|
return boxValue(result);
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueSet(v ref, p string, x ref)
|
||||||
|
"syscall/js.valueSet": (v_ref, p_ptr, p_len, x_ref) => {
|
||||||
|
const v = unboxValue(v_ref);
|
||||||
|
const p = loadString(p_ptr, p_len);
|
||||||
|
const x = unboxValue(x_ref);
|
||||||
|
Reflect.set(v, p, x);
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueIndex(v ref, i int) ref
|
||||||
|
"syscall/js.valueIndex": (v_ref, i) => {
|
||||||
|
return boxValue(Reflect.get(unboxValue(v_ref), i));
|
||||||
|
},
|
||||||
|
|
||||||
|
// valueSetIndex(v ref, i int, x ref)
|
||||||
|
"syscall/js.valueSetIndex": (v_ref, i, x_ref) => {
|
||||||
|
Reflect.set(unboxValue(v_ref), i, unboxValue(x_ref));
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||||
|
"syscall/js.valueCall": (ret_addr, v_ref, m_ptr, m_len, args_ptr, args_len, args_cap) => {
|
||||||
|
const v = unboxValue(v_ref);
|
||||||
|
const name = loadString(m_ptr, m_len);
|
||||||
|
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
||||||
|
try {
|
||||||
|
const m = Reflect.get(v, name);
|
||||||
|
storeValue(ret_addr, Reflect.apply(m, v, args));
|
||||||
|
mem().setUint8(ret_addr + 8, 1);
|
||||||
|
} catch (err) {
|
||||||
|
storeValue(ret_addr, err);
|
||||||
|
mem().setUint8(ret_addr + 8, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueNew(v ref, args []ref) (ref, bool)
|
||||||
|
"syscall/js.valueNew": (ret_addr, v_ref, args_ptr, args_len, args_cap) => {
|
||||||
|
const v = unboxValue(v_ref);
|
||||||
|
const args = loadSliceOfValues(args_ptr, args_len, args_cap);
|
||||||
|
try {
|
||||||
|
storeValue(ret_addr, Reflect.construct(v, args));
|
||||||
|
mem().setUint8(ret_addr + 8, 1);
|
||||||
|
} catch (err) {
|
||||||
|
storeValue(ret_addr, err);
|
||||||
|
mem().setUint8(ret_addr+ 8, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// func valueLength(v ref) int
|
||||||
|
"syscall/js.valueLength": (v_ref) => {
|
||||||
|
return unboxValue(v_ref).length;
|
||||||
|
},
|
||||||
|
|
||||||
|
// valuePrepareString(v ref) (ref, int)
|
||||||
|
"syscall/js.valuePrepareString": (ret_addr, v_ref) => {
|
||||||
|
const s = String(unboxValue(v_ref));
|
||||||
|
const str = encoder.encode(s);
|
||||||
|
storeValue(ret_addr, str);
|
||||||
|
mem().setInt32(ret_addr + 8, str.length, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
// valueLoadString(v ref, b []byte)
|
||||||
|
"syscall/js.valueLoadString": (v_ref, slice_ptr, slice_len, slice_cap) => {
|
||||||
|
const str = unboxValue(v_ref);
|
||||||
|
loadSlice(slice_ptr, slice_len, slice_cap).set(str);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Go 1.20 uses 'env'. Go 1.21 uses 'gojs'.
|
||||||
|
// For compatibility, we use both as long as Go 1.20 is supported.
|
||||||
|
this.importObject.env = this.importObject.gojs;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(instance) {
|
||||||
|
this._inst = instance;
|
||||||
|
this._values = [ // JS values that Go currently has references to, indexed by reference id
|
||||||
|
NaN,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
// fake global
|
||||||
|
{
|
||||||
|
set format(fn){ instance.format = fn; },
|
||||||
|
Array,
|
||||||
|
Object,
|
||||||
|
},
|
||||||
|
this,
|
||||||
|
];
|
||||||
|
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
|
||||||
|
this._ids = new Map(); // mapping from JS values to reference ids
|
||||||
|
this._idPool = []; // unused ids that have been garbage collected
|
||||||
|
this.exited = false; // whether the Go program has exited
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const callbackPromise = new Promise((resolve) => {
|
||||||
|
this._resolveCallbackPromise = () => {
|
||||||
|
if (this.exited) {
|
||||||
|
throw new Error("bad callback: Go program has already exited");
|
||||||
|
}
|
||||||
|
setTimeout(resolve, 0); // make sure it is asynchronous
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this._inst.exports._start();
|
||||||
|
if (this.exited) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await callbackPromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_resume() {
|
||||||
|
if (this.exited) {
|
||||||
|
throw new Error("Go program has already exited");
|
||||||
|
}
|
||||||
|
this._inst.exports.resume();
|
||||||
|
if (this.exited) {
|
||||||
|
this._resolveExitPromise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_makeFuncWrapper(id) {
|
||||||
|
const go = this;
|
||||||
|
return function () {
|
||||||
|
const event = { id: id, this: this, args: arguments };
|
||||||
|
go._pendingEvent = event;
|
||||||
|
go._resume();
|
||||||
|
return event.result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ================== End of wasm_exec.js ==================
|
||||||
|
*/
|
||||||
|
/**/let wasm;
|
||||||
|
/**/async function __load(module, imports) {
|
||||||
|
/**/ if (typeof Response === 'function' && module instanceof Response) {
|
||||||
|
/**/ if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
/**/ try { return await WebAssembly.instantiateStreaming(module, imports); }
|
||||||
|
/**/ catch (e) {
|
||||||
|
/**/ if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||||
|
/**/ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
|
/**/ } else { throw e; }
|
||||||
|
/**/ }
|
||||||
|
/**/ }
|
||||||
|
/**/ const bytes = await module.arrayBuffer();
|
||||||
|
/**/ return await WebAssembly.instantiate(bytes, imports);
|
||||||
|
/**/ } else {
|
||||||
|
/**/ const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
/**/ if (instance instanceof WebAssembly.Instance) return { instance, module };
|
||||||
|
/**/ else return instance;
|
||||||
|
/**/ }
|
||||||
|
/**/}
|
||||||
|
/**/function __finalize_init(instance) {
|
||||||
|
/**/ return wasm = instance;
|
||||||
|
/**/}
|
||||||
|
/**/function __init_memory(imports, maybe_memory) { }
|
||||||
|
/**/export function initSync(module) {
|
||||||
|
/**/ if (wasm !== undefined) return wasm;
|
||||||
|
/**/
|
||||||
|
/**/ const go = new TinyGo();
|
||||||
|
/**/ const imports = go.importObject;
|
||||||
|
/**/
|
||||||
|
/**/ __init_memory(imports);
|
||||||
|
/**/
|
||||||
|
/**/ if (!(module instanceof WebAssembly.Module)) module = new WebAssembly.Module(module);
|
||||||
|
/**/
|
||||||
|
/**/ const instance = new WebAssembly.Instance(module, imports);
|
||||||
|
/**/
|
||||||
|
/**/ go.run(instance);
|
||||||
|
/**/ return __finalize_init(instance, module);
|
||||||
|
/**/}
|
||||||
|
/**/export default async function initAsync(input) {
|
||||||
|
/**/ if (wasm !== undefined) return wasm;
|
||||||
|
/**/
|
||||||
|
/**/ if (typeof input === 'undefined') input = new URL('gofmt.wasm', import.meta.url);
|
||||||
|
/**/
|
||||||
|
/**/ const go = new TinyGo();
|
||||||
|
/**/ const imports = go.importObject;
|
||||||
|
/**/
|
||||||
|
/**/ if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||||
|
/**/ input = fetch(input);
|
||||||
|
/**/ }
|
||||||
|
/**/
|
||||||
|
/**/ __init_memory(imports);
|
||||||
|
/**/
|
||||||
|
/**/ const { instance, module } = await __load(await input, imports);
|
||||||
|
/**/
|
||||||
|
/**/ go.run(instance);
|
||||||
|
/**/ return __finalize_init(instance, module);
|
||||||
|
/**/}
|
||||||
|
/**/export function format(input) {
|
||||||
|
/**/ const [err, result] = wasm.format(input);
|
||||||
|
/**/ if (err) {
|
||||||
|
/**/ throw new Error(result);
|
||||||
|
/**/ }
|
||||||
|
/**/ return result;
|
||||||
|
/**/}
|
||||||
|
/**/
|
||||||
BIN
frontend/src/common/prettier/plugins/go/gofmt.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/go/gofmt.wasm
Normal file
Binary file not shown.
10
frontend/src/common/prettier/plugins/go/gofmt_node.js
Normal file
10
frontend/src/common/prettier/plugins/go/gofmt_node.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./gofmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./gofmt.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function (init = fs.readFile(wasm)) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./gofmt.js";
|
||||||
8
frontend/src/common/prettier/plugins/go/gofmt_vite.js
Normal file
8
frontend/src/common/prettier/plugins/go/gofmt_vite.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./gofmt.js";
|
||||||
|
import wasm_url from "./gofmt.wasm?url";
|
||||||
|
|
||||||
|
export default function (input = wasm_url) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./gofmt.js";
|
||||||
101
frontend/src/common/prettier/plugins/go/index.ts
Normal file
101
frontend/src/common/prettier/plugins/go/index.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for Go formatting using gofmt WebAssembly
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting Go files using the gofmt WASM implementation.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer } from 'prettier';
|
||||||
|
|
||||||
|
// Import the gofmt WASM module
|
||||||
|
import gofmtInit, { format } from './gofmt_vite.js';
|
||||||
|
|
||||||
|
const parserName = 'go';
|
||||||
|
|
||||||
|
// Language configuration
|
||||||
|
const languages = [
|
||||||
|
{
|
||||||
|
name: 'Go',
|
||||||
|
aliases: ['go', 'golang'],
|
||||||
|
parsers: [parserName],
|
||||||
|
extensions: ['.go'],
|
||||||
|
aceMode: 'golang',
|
||||||
|
tmScope: 'source.go',
|
||||||
|
linguistLanguageId: 132,
|
||||||
|
vscodeLanguageIds: ['go']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Parser configuration
|
||||||
|
const goParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (node: string) => node.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lazy initialize gofmt WASM module
|
||||||
|
let initPromise: Promise<void> | null = null;
|
||||||
|
let isInitialized = false;
|
||||||
|
|
||||||
|
function initGofmt(): Promise<void> {
|
||||||
|
if (isInitialized) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initPromise) {
|
||||||
|
initPromise = (async () => {
|
||||||
|
try {
|
||||||
|
await gofmtInit();
|
||||||
|
isInitialized = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to initialize gofmt WASM module:', error);
|
||||||
|
initPromise = null;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printer configuration
|
||||||
|
const goPrinter: Printer<string> = {
|
||||||
|
// @ts-expect-error -- Support async printer like shell plugin
|
||||||
|
async print(path, options) {
|
||||||
|
try {
|
||||||
|
// Wait for initialization to complete
|
||||||
|
await initGofmt();
|
||||||
|
|
||||||
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
|
||||||
|
// Format using gofmt (synchronous call)
|
||||||
|
const formatted = format(text);
|
||||||
|
|
||||||
|
return formatted.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Go formatting failed:', error);
|
||||||
|
// Return original text if formatting fails
|
||||||
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Plugin options (Go doesn't need additional config options)
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
// Plugin definition
|
||||||
|
const goPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers: {
|
||||||
|
[parserName]: goParser,
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
[parserName]: goPrinter,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export plugin without auto-initialization
|
||||||
|
export default goPlugin;
|
||||||
|
export { languages, initGofmt as initialize };
|
||||||
|
export const parsers = goPlugin.parsers;
|
||||||
|
export const printers = goPlugin.printers;
|
||||||
9
frontend/src/common/prettier/plugins/go/src/build.sh
Normal file
9
frontend/src/common/prettier/plugins/go/src/build.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
set -Eeo pipefail
|
||||||
|
|
||||||
|
cd $(dirname $0)
|
||||||
|
|
||||||
|
echo "Building..."
|
||||||
|
tinygo build -o=../gofmt.wasm -target=wasm -no-debug ./lib.go
|
||||||
|
|
||||||
|
echo "Generating JS..."
|
||||||
|
cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js ../gofmt.js
|
||||||
23
frontend/src/common/prettier/plugins/go/src/lib.go
Normal file
23
frontend/src/common/prettier/plugins/go/src/lib.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/format"
|
||||||
|
"syscall/js"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Format(this js.Value, args []js.Value) any {
|
||||||
|
input := ([]byte)(args[0].String())
|
||||||
|
|
||||||
|
output, err := format.Source(input)
|
||||||
|
if err != nil {
|
||||||
|
return []any{true, err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []any{false, string(output)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
done := make(chan bool)
|
||||||
|
js.Global().Set("format", js.FuncOf(Format))
|
||||||
|
<-done
|
||||||
|
}
|
||||||
67
frontend/src/common/prettier/plugins/groovy/index.ts
Normal file
67
frontend/src/common/prettier/plugins/groovy/index.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for Groovy/Jenkins file formatting
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting Groovy and Jenkins files using the groovy-beautify library.
|
||||||
|
* It supports .groovy files and Jenkins-related files like Jenkinsfile.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer } from 'prettier';
|
||||||
|
import groovyBeautify from 'groovy-beautify';
|
||||||
|
|
||||||
|
const parserName = 'groovy';
|
||||||
|
|
||||||
|
// 语言配置
|
||||||
|
const languages = [
|
||||||
|
{
|
||||||
|
name: 'Groovy',
|
||||||
|
aliases: ['groovy'],
|
||||||
|
parsers: [parserName],
|
||||||
|
filenames: ['jenkinsfile', 'Jenkinsfile'],
|
||||||
|
extensions: ['.jenkinsfile', '.Jenkinsfile', '.groovy'],
|
||||||
|
aceMode: 'groovy',
|
||||||
|
tmScope: 'source.groovy',
|
||||||
|
linguistLanguageId: 142,
|
||||||
|
vscodeLanguageIds: ['groovy']
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 解析器配置
|
||||||
|
const groovyParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (node: string) => node.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打印器配置
|
||||||
|
const groovyPrinter: Printer<string> = {
|
||||||
|
print: (path, options) => {
|
||||||
|
try {
|
||||||
|
return groovyBeautify(path.node, {
|
||||||
|
width: options.printWidth || 80,
|
||||||
|
}).trim();
|
||||||
|
} catch (error) {
|
||||||
|
return path.node;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 插件对象
|
||||||
|
const groovyPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers: {
|
||||||
|
[parserName]: groovyParser,
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
[parserName]: groovyPrinter,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default groovyPlugin;
|
||||||
|
export { languages };
|
||||||
|
export const parsers = groovyPlugin.parsers;
|
||||||
|
export const printers = groovyPlugin.printers;
|
||||||
17
frontend/src/common/prettier/plugins/java/comments.d.ts
vendored
Normal file
17
frontend/src/common/prettier/plugins/java/comments.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { IToken } from "java-parser";
|
||||||
|
import { type AstPath } from "prettier";
|
||||||
|
import { type JavaNode, type JavaNonTerminal, type JavaParserOptions } from "./printers/helpers.js";
|
||||||
|
export declare function determineFormatterOffOnRanges(cst: JavaNonTerminal): void;
|
||||||
|
export declare function isFullyBetweenFormatterOffOn(path: AstPath<JavaNode>): boolean;
|
||||||
|
export declare function canAttachComment(node: JavaNode): boolean;
|
||||||
|
export declare function handleLineComment(commentNode: JavaComment, _: string, options: JavaParserOptions): boolean;
|
||||||
|
export declare function handleRemainingComment(commentNode: JavaComment): boolean;
|
||||||
|
export type JavaComment = IToken & {
|
||||||
|
value: string;
|
||||||
|
leading: boolean;
|
||||||
|
trailing: boolean;
|
||||||
|
printed: boolean;
|
||||||
|
enclosingNode?: JavaNonTerminal;
|
||||||
|
precedingNode?: JavaNonTerminal;
|
||||||
|
followingNode?: JavaNonTerminal;
|
||||||
|
};
|
||||||
199
frontend/src/common/prettier/plugins/java/comments.js
Normal file
199
frontend/src/common/prettier/plugins/java/comments.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import { util } from "prettier";
|
||||||
|
import parser from "./parser.js";
|
||||||
|
import { isEmptyStatement, isNonTerminal, isTerminal } from "./printers/helpers.js";
|
||||||
|
const formatterOffOnRangesByCst = new WeakMap();
|
||||||
|
export function determineFormatterOffOnRanges(cst) {
|
||||||
|
const { comments } = cst;
|
||||||
|
if (!comments) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ranges = comments
|
||||||
|
.filter(({ image }) => /^(\/\/\s*@formatter:(off|on)\s*|\/\*\s*@formatter:(off|on)\s*\*\/)$/.test(image))
|
||||||
|
.reduce((ranges, { image, startOffset }) => {
|
||||||
|
const previous = ranges.at(-1);
|
||||||
|
if (image.endsWith("off")) {
|
||||||
|
if ((previous === null || previous === void 0 ? void 0 : previous.on) !== Infinity) {
|
||||||
|
ranges.push({ off: startOffset, on: Infinity });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((previous === null || previous === void 0 ? void 0 : previous.on) === Infinity) {
|
||||||
|
previous.on = startOffset;
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
}, new Array());
|
||||||
|
formatterOffOnRangesByCst.set(cst, ranges);
|
||||||
|
}
|
||||||
|
export function isFullyBetweenFormatterOffOn(path) {
|
||||||
|
var _a;
|
||||||
|
const { node, root } = path;
|
||||||
|
const start = parser.locStart(node);
|
||||||
|
const end = parser.locEnd(node);
|
||||||
|
return (((_a = formatterOffOnRangesByCst
|
||||||
|
.get(root)) === null || _a === void 0 ? void 0 : _a.some(range => range.off < start && end < range.on)) === true);
|
||||||
|
}
|
||||||
|
export function canAttachComment(node) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
if (isTerminal(node)) {
|
||||||
|
const { name, CATEGORIES } = node.tokenType;
|
||||||
|
return (name === "Identifier" ||
|
||||||
|
(CATEGORIES === null || CATEGORIES === void 0 ? void 0 : CATEGORIES.find(({ name }) => name === "BinaryOperator")) !== undefined);
|
||||||
|
}
|
||||||
|
const { children, name } = node;
|
||||||
|
switch (name) {
|
||||||
|
case "argumentList":
|
||||||
|
case "blockStatements":
|
||||||
|
case "emptyStatement":
|
||||||
|
case "enumBodyDeclarations":
|
||||||
|
return false;
|
||||||
|
case "annotationInterfaceMemberDeclaration":
|
||||||
|
case "classMemberDeclaration":
|
||||||
|
case "interfaceMemberDeclaration":
|
||||||
|
case "methodBody":
|
||||||
|
return !children.Semicolon;
|
||||||
|
case "blockStatement":
|
||||||
|
return !children.statement || !isEmptyStatement(children.statement[0]);
|
||||||
|
case "classBodyDeclaration":
|
||||||
|
return !((_a = children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.Semicolon);
|
||||||
|
case "recordBodyDeclaration":
|
||||||
|
return !((_c = (_b = children.classBodyDeclaration) === null || _b === void 0 ? void 0 : _b[0].children.classMemberDeclaration) === null || _c === void 0 ? void 0 : _c[0].children.Semicolon);
|
||||||
|
case "statement":
|
||||||
|
return !isEmptyStatement(node);
|
||||||
|
case "statementWithoutTrailingSubstatement":
|
||||||
|
return !children.emptyStatement;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function handleLineComment(commentNode, _, options) {
|
||||||
|
return [
|
||||||
|
handleBinaryExpressionComments,
|
||||||
|
handleFqnOrRefTypeComments,
|
||||||
|
handleIfStatementComments,
|
||||||
|
handleJumpStatementComments,
|
||||||
|
handleLabeledStatementComments,
|
||||||
|
handleNameComments
|
||||||
|
].some(fn => fn(commentNode, options));
|
||||||
|
}
|
||||||
|
export function handleRemainingComment(commentNode) {
|
||||||
|
return [
|
||||||
|
handleFqnOrRefTypeComments,
|
||||||
|
handleMethodDeclaratorComments,
|
||||||
|
handleNameComments,
|
||||||
|
handleJumpStatementComments
|
||||||
|
].some(fn => fn(commentNode));
|
||||||
|
}
|
||||||
|
function handleBinaryExpressionComments(commentNode, options) {
|
||||||
|
const { enclosingNode, precedingNode, followingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
enclosingNode.name === "binaryExpression") {
|
||||||
|
if (isBinaryOperator(followingNode)) {
|
||||||
|
if (options.experimentalOperatorPosition === "start") {
|
||||||
|
util.addLeadingComment(followingNode, commentNode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
util.addTrailingComment(followingNode, commentNode);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (options.experimentalOperatorPosition === "start" &&
|
||||||
|
isBinaryOperator(precedingNode)) {
|
||||||
|
util.addLeadingComment(precedingNode, commentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleFqnOrRefTypeComments(commentNode) {
|
||||||
|
const { enclosingNode, followingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
enclosingNode.name === "fqnOrRefType" &&
|
||||||
|
followingNode) {
|
||||||
|
util.addLeadingComment(followingNode, commentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleIfStatementComments(commentNode) {
|
||||||
|
const { enclosingNode, precedingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
enclosingNode.name === "ifStatement" &&
|
||||||
|
precedingNode &&
|
||||||
|
isNonTerminal(precedingNode) &&
|
||||||
|
precedingNode.name === "statement") {
|
||||||
|
util.addDanglingComment(enclosingNode, commentNode, undefined);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleJumpStatementComments(commentNode) {
|
||||||
|
const { enclosingNode, precedingNode, followingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
!precedingNode &&
|
||||||
|
!followingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
["breakStatement", "continueStatement", "returnStatement"].includes(enclosingNode.name)) {
|
||||||
|
util.addTrailingComment(enclosingNode, commentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleLabeledStatementComments(commentNode) {
|
||||||
|
const { enclosingNode, precedingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
precedingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
enclosingNode.name === "labeledStatement" &&
|
||||||
|
isTerminal(precedingNode) &&
|
||||||
|
precedingNode.tokenType.name === "Identifier") {
|
||||||
|
util.addLeadingComment(precedingNode, commentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleMethodDeclaratorComments(commentNode) {
|
||||||
|
const { enclosingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
enclosingNode.name === "methodDeclarator" &&
|
||||||
|
!enclosingNode.children.receiverParameter &&
|
||||||
|
!enclosingNode.children.formalParameterList &&
|
||||||
|
enclosingNode.children.LBrace[0].startOffset < commentNode.startOffset &&
|
||||||
|
commentNode.startOffset < enclosingNode.children.RBrace[0].startOffset) {
|
||||||
|
util.addDanglingComment(enclosingNode, commentNode, undefined);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function handleNameComments(commentNode) {
|
||||||
|
const { enclosingNode, precedingNode } = commentNode;
|
||||||
|
if (enclosingNode &&
|
||||||
|
precedingNode &&
|
||||||
|
isNonTerminal(enclosingNode) &&
|
||||||
|
isTerminal(precedingNode) &&
|
||||||
|
precedingNode.tokenType.name === "Identifier" &&
|
||||||
|
[
|
||||||
|
"ambiguousName",
|
||||||
|
"classOrInterfaceTypeToInstantiate",
|
||||||
|
"expressionName",
|
||||||
|
"moduleDeclaration",
|
||||||
|
"moduleName",
|
||||||
|
"packageDeclaration",
|
||||||
|
"packageName",
|
||||||
|
"packageOrTypeName",
|
||||||
|
"typeName"
|
||||||
|
].includes(enclosingNode.name)) {
|
||||||
|
util.addTrailingComment(precedingNode, commentNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function isBinaryOperator(node) {
|
||||||
|
var _a;
|
||||||
|
return (node !== undefined &&
|
||||||
|
(isNonTerminal(node)
|
||||||
|
? node.name === "shiftOperator"
|
||||||
|
: (_a = node.tokenType.CATEGORIES) === null || _a === void 0 ? void 0 : _a.some(({ name }) => name === "BinaryOperator")));
|
||||||
|
}
|
||||||
563
frontend/src/common/prettier/plugins/java/index.d.ts
vendored
Normal file
563
frontend/src/common/prettier/plugins/java/index.d.ts
vendored
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
import type { JavaNode } from "./printers/helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
languages: {
|
||||||
|
name: string;
|
||||||
|
parsers: "java"[];
|
||||||
|
group: string;
|
||||||
|
tmScope: string;
|
||||||
|
aceMode: string;
|
||||||
|
codemirrorMode: string;
|
||||||
|
codemirrorMimeType: string;
|
||||||
|
extensions: string[];
|
||||||
|
linguistLanguageId: number;
|
||||||
|
vscodeLanguageIds: string[];
|
||||||
|
}[];
|
||||||
|
parsers: {
|
||||||
|
java: {
|
||||||
|
parse(text: string, options: import("./printers/helpers.js").JavaParserOptions): import("./printers/helpers.js").JavaNonTerminal;
|
||||||
|
astFormat: string;
|
||||||
|
hasPragma(text: string): boolean;
|
||||||
|
locStart(node: JavaNode): number;
|
||||||
|
locEnd(node: JavaNode): number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
printers: {
|
||||||
|
java: {
|
||||||
|
print(path: import("prettier").AstPath<import("java-parser").ArrayInitializerCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableInitializerListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BlockCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BlockStatementsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LocalVariableDeclarationStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LocalVariableDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LabeledStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExpressionStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").IfStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AssertStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SwitchStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SwitchBlockCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SwitchBlockStatementGroupCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SwitchLabelCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SwitchRuleCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").WhileStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DoStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BasicForStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StatementExpressionListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnhancedForStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BreakStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ContinueStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ReturnStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ThrowStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SynchronizedStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TryStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CatchesCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CatchClauseCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CatchFormalParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CatchTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FinallyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TryWithResourcesStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ResourceSpecificationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ResourceListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").YieldStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ForInitCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ForUpdateCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StatementWithoutTrailingSubstatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ForStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BlockStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CaseConstantCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CasePatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EmptyStatementCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StatementExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LocalVariableTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ResourceCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableAccessCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NormalClassDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeParametersCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeParameterListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassExtendsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassImplementsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceTypeListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassMemberDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FieldDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableDeclaratorListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableDeclaratorCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableDeclaratorIdCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannPrimitiveTypeWithOptionalDimsSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannReferenceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodHeaderCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodDeclaratorCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ReceiverParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FormalParameterListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableParaRegularParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableArityParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ThrowsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExceptionTypeListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StaticInitializerCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstructorDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstructorDeclaratorCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstructorBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnqualifiedExplicitConstructorInvocationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").QualifiedExplicitConstructorInvocationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumConstantListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumConstantCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumBodyDeclarationsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordHeaderCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordComponentListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordComponentCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableArityRecordComponentCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CompactConstructorDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableInitializerCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").VariableModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannClassTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassBodyDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InstanceInitializerCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassPermitsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FieldModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstructorModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").SimpleTypeNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExplicitConstructorInvocationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EnumConstantModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExceptionTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FormalParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ResultCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordBodyDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordComponentModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannClassOrInterfaceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannInterfaceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannPrimitiveTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnannTypeVariableCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaParametersCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaParametersWithBracesCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConciseLambdaParameterListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NormalLambdaParameterListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RegularLambdaParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConditionalExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BinaryExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnaryExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnaryExpressionNotPlusMinusCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PrimaryCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PrimarySuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FqnOrRefTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FqnOrRefTypePartFirstCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FqnOrRefTypePartRestCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FqnOrRefTypePartCommonCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ParenthesisExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PrimitiveCastExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ReferenceTypeCastExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UnqualifiedClassInstanceCreationExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassOrInterfaceTypeToInstantiateCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodInvocationSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ArgumentListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ArrayCreationExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ArrayCreationExpressionWithoutInitializerSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ArrayCreationWithInitializerSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DimExprsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DimExprCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassLiteralSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ArrayAccessSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodReferenceSuffixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").StringTemplateCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TextBlockTemplateCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RecordPatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ComponentPatternListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").GuardCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TemplateCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypePatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CastExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeArgumentsOrDiamondCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DiamondCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ComponentPatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MatchAllPatternCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConciseLambdaParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").EmbeddedExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaParameterListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NormalLambdaParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LambdaParameterTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NewExpressionCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PrimaryPrefixCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TemplateArgumentCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NormalInterfaceDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceExtendsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceMemberDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstantDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceMethodDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationInterfaceDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationInterfaceBodyCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationInterfaceMemberDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationInterfaceElementDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DefaultValueCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ElementValuePairListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ElementValuePairCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ElementValueArrayInitializerCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ElementValueListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ElementValueCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AnnotationInterfaceElementModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ConstantModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfacePermitsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceMethodModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").LiteralCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ShiftOperatorCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").BooleanLiteralCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FloatingPointLiteralCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").IntegerLiteralCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").MethodNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AmbiguousNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeIdentifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExpressionNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PackageNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ModuleNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PackageOrTypeNameCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").CompilationUnitCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").OrdinaryCompilationUnitCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ModularCompilationUnitCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PackageDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ImportDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ModuleDeclarationCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RequiresModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ExportsModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").OpensModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").UsesModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ProvidesModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ModuleDirectiveCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").RequiresModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PackageModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").PrimitiveTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ReferenceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeVariableCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").DimsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeParameterCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeBoundCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").AdditionalBoundCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeArgumentsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeArgumentListCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").WildcardCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").WildcardBoundsCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").InterfaceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").NumericTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").ClassOrInterfaceTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").FloatingPointTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").IntegralTypeCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeArgumentCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").TypeParameterModifierCstNode & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}> | import("prettier").AstPath<import("java-parser").IToken & {
|
||||||
|
comments?: import("./comments.js").JavaComment[];
|
||||||
|
}>, options: import("prettier").ParserOptions<JavaNode>, print: (path: import("prettier").AstPath<JavaNode>) => import("prettier").Doc, args: unknown): import("prettier/doc.js").builders.Doc;
|
||||||
|
hasPrettierIgnore(path: import("prettier").AstPath<JavaNode>): boolean;
|
||||||
|
canAttachComment: typeof import("./comments.js").canAttachComment;
|
||||||
|
isBlockComment(node: JavaNode): boolean;
|
||||||
|
printComment(commentPath: import("prettier").AstPath<JavaNode>): string | import("prettier/doc.js").builders.Doc[];
|
||||||
|
getCommentChildNodes(node: JavaNode): any[];
|
||||||
|
handleComments: {
|
||||||
|
ownLine: typeof import("./comments.js").handleLineComment;
|
||||||
|
endOfLine: typeof import("./comments.js").handleLineComment;
|
||||||
|
remaining: typeof import("./comments.js").handleRemainingComment;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
options: {
|
||||||
|
entrypoint: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
arrowParens: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
trailingComma: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
experimentalOperatorPosition: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
defaultOptions: {
|
||||||
|
arrowParens: "avoid";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
29
frontend/src/common/prettier/plugins/java/index.js
Normal file
29
frontend/src/common/prettier/plugins/java/index.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import options from "./options.js";
|
||||||
|
import parser from "./parser.js";
|
||||||
|
import printer from "./printer.js";
|
||||||
|
export default {
|
||||||
|
languages: [
|
||||||
|
{
|
||||||
|
name: "Java",
|
||||||
|
parsers: ["java"],
|
||||||
|
group: "Java",
|
||||||
|
tmScope: "source.java",
|
||||||
|
aceMode: "java",
|
||||||
|
codemirrorMode: "clike",
|
||||||
|
codemirrorMimeType: "text/x-java",
|
||||||
|
extensions: [".java"],
|
||||||
|
linguistLanguageId: 181,
|
||||||
|
vscodeLanguageIds: ["java"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
parsers: {
|
||||||
|
java: parser
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
java: printer
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
defaultOptions: {
|
||||||
|
arrowParens: "avoid"
|
||||||
|
}
|
||||||
|
};
|
||||||
43
frontend/src/common/prettier/plugins/java/options.d.ts
vendored
Normal file
43
frontend/src/common/prettier/plugins/java/options.d.ts
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
declare const _default: {
|
||||||
|
entrypoint: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
arrowParens: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
trailingComma: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
experimentalOperatorPosition: {
|
||||||
|
type: "choice";
|
||||||
|
category: string;
|
||||||
|
default: string;
|
||||||
|
choices: {
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
}[];
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
284
frontend/src/common/prettier/plugins/java/options.js
Normal file
284
frontend/src/common/prettier/plugins/java/options.js
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
export default {
|
||||||
|
entrypoint: {
|
||||||
|
type: "choice",
|
||||||
|
category: "Global",
|
||||||
|
default: "compilationUnit",
|
||||||
|
// sed -nr 's/.*\.RULE\(([^,]+),.*/\1/p' $(ls path/to/java-parser/rules/folder/*)
|
||||||
|
choices: [
|
||||||
|
{ value: "arrayInitializer", description: "" },
|
||||||
|
{ value: "variableInitializerList", description: "" },
|
||||||
|
{ value: "block", description: "" },
|
||||||
|
{ value: "blockStatements", description: "" },
|
||||||
|
{ value: "blockStatement", description: "" },
|
||||||
|
{ value: "localVariableDeclarationStatement", description: "" },
|
||||||
|
{ value: "localVariableDeclaration", description: "" },
|
||||||
|
{ value: "localVariableType", description: "" },
|
||||||
|
{ value: "statement", description: "" },
|
||||||
|
{ value: "statementWithoutTrailingSubstatement", description: "" },
|
||||||
|
{ value: "emptyStatement", description: "" },
|
||||||
|
{ value: "labeledStatement", description: "" },
|
||||||
|
{ value: "expressionStatement", description: "" },
|
||||||
|
{ value: "statementExpression", description: "" },
|
||||||
|
{ value: "ifStatement", description: "" },
|
||||||
|
{ value: "assertStatement", description: "" },
|
||||||
|
{ value: "switchStatement", description: "" },
|
||||||
|
{ value: "switchBlock", description: "" },
|
||||||
|
{ value: "switchBlockStatementGroup", description: "" },
|
||||||
|
{ value: "switchLabel", description: "" },
|
||||||
|
{ value: "switchRule", description: "" },
|
||||||
|
{ value: "caseConstant", description: "" },
|
||||||
|
{ value: "casePattern", description: "" },
|
||||||
|
{ value: "whileStatement", description: "" },
|
||||||
|
{ value: "doStatement", description: "" },
|
||||||
|
{ value: "forStatement", description: "" },
|
||||||
|
{ value: "basicForStatement", description: "" },
|
||||||
|
{ value: "forInit", description: "" },
|
||||||
|
{ value: "forUpdate", description: "" },
|
||||||
|
{ value: "statementExpressionList", description: "" },
|
||||||
|
{ value: "enhancedForStatement", description: "" },
|
||||||
|
{ value: "breakStatement", description: "" },
|
||||||
|
{ value: "continueStatement", description: "" },
|
||||||
|
{ value: "returnStatement", description: "" },
|
||||||
|
{ value: "throwStatement", description: "" },
|
||||||
|
{ value: "synchronizedStatement", description: "" },
|
||||||
|
{ value: "tryStatement", description: "" },
|
||||||
|
{ value: "catches", description: "" },
|
||||||
|
{ value: "catchClause", description: "" },
|
||||||
|
{ value: "catchFormalParameter", description: "" },
|
||||||
|
{ value: "catchType", description: "" },
|
||||||
|
{ value: "finally", description: "" },
|
||||||
|
{ value: "tryWithResourcesStatement", description: "" },
|
||||||
|
{ value: "resourceSpecification", description: "" },
|
||||||
|
{ value: "resourceList", description: "" },
|
||||||
|
{ value: "resource", description: "" },
|
||||||
|
{ value: "yieldStatement", description: "" },
|
||||||
|
{ value: "variableAccess", description: "" },
|
||||||
|
{ value: "classDeclaration", description: "" },
|
||||||
|
{ value: "normalClassDeclaration", description: "" },
|
||||||
|
{ value: "classModifier", description: "" },
|
||||||
|
{ value: "typeParameters", description: "" },
|
||||||
|
{ value: "typeParameterList", description: "" },
|
||||||
|
{ value: "classExtends", description: "" },
|
||||||
|
{ value: "classImplements", description: "" },
|
||||||
|
{ value: "interfaceTypeList", description: "" },
|
||||||
|
{ value: "classPermits", description: "" },
|
||||||
|
{ value: "classBody", description: "" },
|
||||||
|
{ value: "classBodyDeclaration", description: "" },
|
||||||
|
{ value: "classMemberDeclaration", description: "" },
|
||||||
|
{ value: "fieldDeclaration", description: "" },
|
||||||
|
{ value: "fieldModifier", description: "" },
|
||||||
|
{ value: "variableDeclaratorList", description: "" },
|
||||||
|
{ value: "variableDeclarator", description: "" },
|
||||||
|
{ value: "variableDeclaratorId", description: "" },
|
||||||
|
{ value: "variableInitializer", description: "" },
|
||||||
|
{ value: "unannType", description: "" },
|
||||||
|
{ value: "unannPrimitiveTypeWithOptionalDimsSuffix", description: "" },
|
||||||
|
{ value: "unannPrimitiveType", description: "" },
|
||||||
|
{ value: "unannReferenceType", description: "" },
|
||||||
|
{ value: "unannClassOrInterfaceType", description: "" },
|
||||||
|
{ value: "unannClassType", description: "" },
|
||||||
|
{ value: "unannInterfaceType", description: "" },
|
||||||
|
{ value: "unannTypeVariable", description: "" },
|
||||||
|
{ value: "methodDeclaration", description: "" },
|
||||||
|
{ value: "methodModifier", description: "" },
|
||||||
|
{ value: "methodHeader", description: "" },
|
||||||
|
{ value: "result", description: "" },
|
||||||
|
{ value: "methodDeclarator", description: "" },
|
||||||
|
{ value: "receiverParameter", description: "" },
|
||||||
|
{ value: "formalParameterList", description: "" },
|
||||||
|
{ value: "formalParameter", description: "" },
|
||||||
|
{ value: "variableParaRegularParameter", description: "" },
|
||||||
|
{ value: "variableArityParameter", description: "" },
|
||||||
|
{ value: "variableModifier", description: "" },
|
||||||
|
{ value: "throws", description: "" },
|
||||||
|
{ value: "exceptionTypeList", description: "" },
|
||||||
|
{ value: "exceptionType", description: "" },
|
||||||
|
{ value: "methodBody", description: "" },
|
||||||
|
{ value: "instanceInitializer", description: "" },
|
||||||
|
{ value: "staticInitializer", description: "" },
|
||||||
|
{ value: "constructorDeclaration", description: "" },
|
||||||
|
{ value: "constructorModifier", description: "" },
|
||||||
|
{ value: "constructorDeclarator", description: "" },
|
||||||
|
{ value: "simpleTypeName", description: "" },
|
||||||
|
{ value: "constructorBody", description: "" },
|
||||||
|
{ value: "explicitConstructorInvocation", description: "" },
|
||||||
|
{ value: "unqualifiedExplicitConstructorInvocation", description: "" },
|
||||||
|
{ value: "qualifiedExplicitConstructorInvocation", description: "" },
|
||||||
|
{ value: "enumDeclaration", description: "" },
|
||||||
|
{ value: "enumBody", description: "" },
|
||||||
|
{ value: "enumConstantList", description: "" },
|
||||||
|
{ value: "enumConstant", description: "" },
|
||||||
|
{ value: "enumConstantModifier", description: "" },
|
||||||
|
{ value: "enumBodyDeclarations", description: "" },
|
||||||
|
{ value: "recordDeclaration", description: "" },
|
||||||
|
{ value: "recordHeader", description: "" },
|
||||||
|
{ value: "recordComponentList", description: "" },
|
||||||
|
{ value: "recordComponent", description: "" },
|
||||||
|
{ value: "variableArityRecordComponent", description: "" },
|
||||||
|
{ value: "recordComponentModifier", description: "" },
|
||||||
|
{ value: "recordBody", description: "" },
|
||||||
|
{ value: "recordBodyDeclaration", description: "" },
|
||||||
|
{ value: "compactConstructorDeclaration", description: "" },
|
||||||
|
{ value: "isDims", description: "" },
|
||||||
|
{ value: "expression", description: "" },
|
||||||
|
{ value: "lambdaExpression", description: "" },
|
||||||
|
{ value: "lambdaParameters", description: "" },
|
||||||
|
{ value: "lambdaParametersWithBraces", description: "" },
|
||||||
|
{ value: "lambdaParameterList", description: "" },
|
||||||
|
{ value: "conciseLambdaParameterList", description: "" },
|
||||||
|
{ value: "normalLambdaParameterList", description: "" },
|
||||||
|
{ value: "normalLambdaParameter", description: "" },
|
||||||
|
{ value: "regularLambdaParameter", description: "" },
|
||||||
|
{ value: "lambdaParameterType", description: "" },
|
||||||
|
{ value: "conciseLambdaParameter", description: "" },
|
||||||
|
{ value: "lambdaBody", description: "" },
|
||||||
|
{ value: "conditionalExpression", description: "" },
|
||||||
|
{ value: "binaryExpression", description: "" },
|
||||||
|
{ value: "unaryExpression", description: "" },
|
||||||
|
{ value: "unaryExpressionNotPlusMinus", description: "" },
|
||||||
|
{ value: "primary", description: "" },
|
||||||
|
{ value: "primaryPrefix", description: "" },
|
||||||
|
{ value: "primarySuffix", description: "" },
|
||||||
|
{ value: "fqnOrRefType", description: "" },
|
||||||
|
{ value: "fqnOrRefTypePartRest", description: "" },
|
||||||
|
{ value: "fqnOrRefTypePartCommon", description: "" },
|
||||||
|
{ value: "fqnOrRefTypePartFirst", description: "" },
|
||||||
|
{ value: "parenthesisExpression", description: "" },
|
||||||
|
{ value: "castExpression", description: "" },
|
||||||
|
{ value: "primitiveCastExpression", description: "" },
|
||||||
|
{ value: "referenceTypeCastExpression", description: "" },
|
||||||
|
{ value: "newExpression", description: "" },
|
||||||
|
{ value: "unqualifiedClassInstanceCreationExpression", description: "" },
|
||||||
|
{ value: "classOrInterfaceTypeToInstantiate", description: "" },
|
||||||
|
{ value: "typeArgumentsOrDiamond", description: "" },
|
||||||
|
{ value: "diamond", description: "" },
|
||||||
|
{ value: "methodInvocationSuffix", description: "" },
|
||||||
|
{ value: "argumentList", description: "" },
|
||||||
|
{ value: "arrayCreationExpression", description: "" },
|
||||||
|
{
|
||||||
|
value: "arrayCreationExpressionWithoutInitializerSuffix",
|
||||||
|
description: ""
|
||||||
|
},
|
||||||
|
{ value: "arrayCreationWithInitializerSuffix", description: "" },
|
||||||
|
{ value: "dimExprs", description: "" },
|
||||||
|
{ value: "dimExpr", description: "" },
|
||||||
|
{ value: "classLiteralSuffix", description: "" },
|
||||||
|
{ value: "arrayAccessSuffix", description: "" },
|
||||||
|
{ value: "methodReferenceSuffix", description: "" },
|
||||||
|
{ value: "templateArgument", description: "" },
|
||||||
|
{ value: "template", description: "" },
|
||||||
|
{ value: "stringTemplate", description: "" },
|
||||||
|
{ value: "textBlockTemplate", description: "" },
|
||||||
|
{ value: "embeddedExpression", description: "" },
|
||||||
|
{ value: "pattern", description: "" },
|
||||||
|
{ value: "typePattern", description: "" },
|
||||||
|
{ value: "recordPattern", description: "" },
|
||||||
|
{ value: "componentPatternList", description: "" },
|
||||||
|
{ value: "componentPattern", description: "" },
|
||||||
|
{ value: "matchAllPattern", description: "" },
|
||||||
|
{ value: "guard", description: "" },
|
||||||
|
{ value: "isRefTypeInMethodRef", description: "" },
|
||||||
|
{ value: "interfaceDeclaration", description: "" },
|
||||||
|
{ value: "normalInterfaceDeclaration", description: "" },
|
||||||
|
{ value: "interfaceModifier", description: "" },
|
||||||
|
{ value: "interfaceExtends", description: "" },
|
||||||
|
{ value: "interfacePermits", description: "" },
|
||||||
|
{ value: "interfaceBody", description: "" },
|
||||||
|
{ value: "interfaceMemberDeclaration", description: "" },
|
||||||
|
{ value: "constantDeclaration", description: "" },
|
||||||
|
{ value: "constantModifier", description: "" },
|
||||||
|
{ value: "interfaceMethodDeclaration", description: "" },
|
||||||
|
{ value: "interfaceMethodModifier", description: "" },
|
||||||
|
{ value: "annotationInterfaceDeclaration", description: "" },
|
||||||
|
{ value: "annotationInterfaceBody", description: "" },
|
||||||
|
{ value: "annotationInterfaceMemberDeclaration", description: "" },
|
||||||
|
{ value: "annotationInterfaceElementDeclaration", description: "" },
|
||||||
|
{ value: "annotationInterfaceElementModifier", description: "" },
|
||||||
|
{ value: "defaultValue", description: "" },
|
||||||
|
{ value: "annotation", description: "" },
|
||||||
|
{ value: "elementValuePairList", description: "" },
|
||||||
|
{ value: "elementValuePair", description: "" },
|
||||||
|
{ value: "elementValue", description: "" },
|
||||||
|
{ value: "elementValueArrayInitializer", description: "" },
|
||||||
|
{ value: "elementValueList", description: "" },
|
||||||
|
{ value: "literal", description: "" },
|
||||||
|
{ value: "integerLiteral", description: "" },
|
||||||
|
{ value: "floatingPointLiteral", description: "" },
|
||||||
|
{ value: "booleanLiteral", description: "" },
|
||||||
|
{ value: "shiftOperator", description: "" },
|
||||||
|
{ value: "moduleName", description: "" },
|
||||||
|
{ value: "packageName", description: "" },
|
||||||
|
{ value: "typeName", description: "" },
|
||||||
|
{ value: "expressionName", description: "" },
|
||||||
|
{ value: "methodName", description: "" },
|
||||||
|
{ value: "packageOrTypeName", description: "" },
|
||||||
|
{ value: "ambiguousName", description: "" },
|
||||||
|
{ value: "compilationUnit", description: "" },
|
||||||
|
{ value: "ordinaryCompilationUnit", description: "" },
|
||||||
|
{ value: "modularCompilationUnit", description: "" },
|
||||||
|
{ value: "packageDeclaration", description: "" },
|
||||||
|
{ value: "packageModifier", description: "" },
|
||||||
|
{ value: "importDeclaration", description: "" },
|
||||||
|
{ value: "typeDeclaration", description: "" },
|
||||||
|
{ value: "moduleDeclaration", description: "" },
|
||||||
|
{ value: "moduleDirective", description: "" },
|
||||||
|
{ value: "requiresModuleDirective", description: "" },
|
||||||
|
{ value: "exportsModuleDirective", description: "" },
|
||||||
|
{ value: "opensModuleDirective", description: "" },
|
||||||
|
{ value: "usesModuleDirective", description: "" },
|
||||||
|
{ value: "providesModuleDirective", description: "" },
|
||||||
|
{ value: "requiresModifier", description: "" },
|
||||||
|
{ value: "primitiveType", description: "" },
|
||||||
|
{ value: "numericType", description: "" },
|
||||||
|
{ value: "integralType", description: "" },
|
||||||
|
{ value: "floatingPointType", description: "" },
|
||||||
|
{ value: "referenceType", description: "" },
|
||||||
|
{ value: "classOrInterfaceType", description: "" },
|
||||||
|
{ value: "classType", description: "" },
|
||||||
|
{ value: "interfaceType", description: "" },
|
||||||
|
{ value: "typeVariable", description: "" },
|
||||||
|
{ value: "dims", description: "" },
|
||||||
|
{ value: "typeParameter", description: "" },
|
||||||
|
{ value: "typeParameterModifier", description: "" },
|
||||||
|
{ value: "typeBound", description: "" },
|
||||||
|
{ value: "additionalBound", description: "" },
|
||||||
|
{ value: "typeArguments", description: "" },
|
||||||
|
{ value: "typeArgumentList", description: "" },
|
||||||
|
{ value: "typeArgument", description: "" },
|
||||||
|
{ value: "wildcard", description: "" },
|
||||||
|
{ value: "wildcardBounds", description: "" }
|
||||||
|
],
|
||||||
|
description: "Prettify from the entrypoint, allowing to use prettier on snippet."
|
||||||
|
},
|
||||||
|
arrowParens: {
|
||||||
|
type: "choice",
|
||||||
|
category: "Java",
|
||||||
|
default: "always",
|
||||||
|
choices: [
|
||||||
|
{ value: "always", description: "" },
|
||||||
|
{ value: "avoid", description: "" }
|
||||||
|
],
|
||||||
|
description: "Include parentheses around a sole arrow function parameter."
|
||||||
|
},
|
||||||
|
trailingComma: {
|
||||||
|
type: "choice",
|
||||||
|
category: "Java",
|
||||||
|
default: "all",
|
||||||
|
choices: [
|
||||||
|
{ value: "all", description: "" },
|
||||||
|
{ value: "es5", description: "" },
|
||||||
|
{ value: "none", description: "" }
|
||||||
|
],
|
||||||
|
description: "Print trailing commas wherever possible when multi-line."
|
||||||
|
},
|
||||||
|
experimentalOperatorPosition: {
|
||||||
|
type: "choice",
|
||||||
|
category: "Java",
|
||||||
|
default: "end",
|
||||||
|
choices: [
|
||||||
|
{ value: "start", description: "" },
|
||||||
|
{ value: "end", description: "" }
|
||||||
|
],
|
||||||
|
description: "Where to print operators when binary expressions wrap lines."
|
||||||
|
}
|
||||||
|
};
|
||||||
9
frontend/src/common/prettier/plugins/java/parser.d.ts
vendored
Normal file
9
frontend/src/common/prettier/plugins/java/parser.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { type JavaNode, type JavaNonTerminal, type JavaParserOptions } from "./printers/helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
parse(text: string, options: JavaParserOptions): JavaNonTerminal;
|
||||||
|
astFormat: string;
|
||||||
|
hasPragma(text: string): boolean;
|
||||||
|
locStart(node: JavaNode): number;
|
||||||
|
locEnd(node: JavaNode): number;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
24
frontend/src/common/prettier/plugins/java/parser.js
Normal file
24
frontend/src/common/prettier/plugins/java/parser.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { parse } from "java-parser";
|
||||||
|
import { determineFormatterOffOnRanges } from "./comments.js";
|
||||||
|
import { isTerminal } from "./printers/helpers.js";
|
||||||
|
export default {
|
||||||
|
parse(text, options) {
|
||||||
|
var _a;
|
||||||
|
const cst = parse(text, options.entrypoint);
|
||||||
|
(_a = cst.comments) === null || _a === void 0 ? void 0 : _a.forEach(comment => {
|
||||||
|
comment.value = comment.image;
|
||||||
|
});
|
||||||
|
determineFormatterOffOnRanges(cst);
|
||||||
|
return cst;
|
||||||
|
},
|
||||||
|
astFormat: "java",
|
||||||
|
hasPragma(text) {
|
||||||
|
return /^\/\*\*\n\s+\*\s@(format|prettier)\n\s+\*\//.test(text);
|
||||||
|
},
|
||||||
|
locStart(node) {
|
||||||
|
return isTerminal(node) ? node.startOffset : node.location.startOffset;
|
||||||
|
},
|
||||||
|
locEnd(node) {
|
||||||
|
return (isTerminal(node) ? node.endOffset : node.location.endOffset) + 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
18
frontend/src/common/prettier/plugins/java/printer.d.ts
vendored
Normal file
18
frontend/src/common/prettier/plugins/java/printer.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import type { AstPath } from "prettier";
|
||||||
|
import { canAttachComment, handleLineComment, handleRemainingComment } from "./comments.js";
|
||||||
|
import { type JavaNode } from "./printers/helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
print(path: DistributedAstPath<JavaNode>, options: import("prettier").ParserOptions<JavaNode>, print: (path: AstPath<JavaNode>) => import("prettier").Doc, args: unknown): import("prettier/doc.js").builders.Doc;
|
||||||
|
hasPrettierIgnore(path: AstPath<JavaNode>): boolean;
|
||||||
|
canAttachComment: typeof canAttachComment;
|
||||||
|
isBlockComment(node: JavaNode): boolean;
|
||||||
|
printComment(commentPath: AstPath<JavaNode>): string | import("prettier/doc.js").builders.Doc[];
|
||||||
|
getCommentChildNodes(node: JavaNode): any[];
|
||||||
|
handleComments: {
|
||||||
|
ownLine: typeof handleLineComment;
|
||||||
|
endOfLine: typeof handleLineComment;
|
||||||
|
remaining: typeof handleRemainingComment;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
|
type DistributedAstPath<T> = T extends any ? AstPath<T> : never;
|
||||||
40
frontend/src/common/prettier/plugins/java/printer.js
Normal file
40
frontend/src/common/prettier/plugins/java/printer.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { canAttachComment, handleLineComment, handleRemainingComment, isFullyBetweenFormatterOffOn } from "./comments.js";
|
||||||
|
import { isNonTerminal, isTerminal, printComment } from "./printers/helpers.js";
|
||||||
|
import { printerForNodeType } from "./printers/index.js";
|
||||||
|
export default {
|
||||||
|
print(path, options, print, args) {
|
||||||
|
return hasTerminal(path)
|
||||||
|
? path.node.image
|
||||||
|
: printerForNodeType(path.node.name)(path, print, options, args);
|
||||||
|
},
|
||||||
|
hasPrettierIgnore(path) {
|
||||||
|
var _a;
|
||||||
|
const { node } = path;
|
||||||
|
return (((_a = node.comments) === null || _a === void 0 ? void 0 : _a.some(({ image }) => /^(\/\/\s*prettier-ignore|\/\*\s*prettier-ignore\s*\*\/)$/.test(image))) === true ||
|
||||||
|
(canAttachComment(node) && isFullyBetweenFormatterOffOn(path)));
|
||||||
|
},
|
||||||
|
canAttachComment,
|
||||||
|
isBlockComment(node) {
|
||||||
|
return isTerminal(node) && node.tokenType.name === "TraditionalComment";
|
||||||
|
},
|
||||||
|
printComment(commentPath) {
|
||||||
|
const { node } = commentPath;
|
||||||
|
if (isNonTerminal(node) || node.tokenType.GROUP !== "comments") {
|
||||||
|
throw new Error(`Not a comment: ${JSON.stringify(node)}`);
|
||||||
|
}
|
||||||
|
return printComment(node);
|
||||||
|
},
|
||||||
|
getCommentChildNodes(node) {
|
||||||
|
return isNonTerminal(node)
|
||||||
|
? Object.values(node.children).flatMap(child => child)
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
handleComments: {
|
||||||
|
ownLine: handleLineComment,
|
||||||
|
endOfLine: handleLineComment,
|
||||||
|
remaining: handleRemainingComment
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function hasTerminal(path) {
|
||||||
|
return isTerminal(path.node);
|
||||||
|
}
|
||||||
9
frontend/src/common/prettier/plugins/java/printers/arrays.d.ts
vendored
Normal file
9
frontend/src/common/prettier/plugins/java/printers/arrays.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
declare const _default: {
|
||||||
|
arrayInitializer(path: import("prettier").AstPath<import("java-parser").ArrayInitializerCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn, options: import("./helpers.js").JavaParserOptions): import("prettier/doc.js").builders.Group | "{}";
|
||||||
|
variableInitializerList(path: import("prettier").AstPath<import("java-parser").VariableInitializerListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): import("prettier/doc.js").builders.Doc[];
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { printArrayInitializer, printList } from "./helpers.js";
|
||||||
|
export default {
|
||||||
|
arrayInitializer(path, print, options) {
|
||||||
|
return printArrayInitializer(path, print, options, "variableInitializerList");
|
||||||
|
},
|
||||||
|
variableInitializerList(path, print) {
|
||||||
|
return printList(path, print, "variableInitializer");
|
||||||
|
}
|
||||||
|
};
|
||||||
117
frontend/src/common/prettier/plugins/java/printers/blocks-and-statements.d.ts
vendored
Normal file
117
frontend/src/common/prettier/plugins/java/printers/blocks-and-statements.d.ts
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import { printSingle } from "./helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
block(path: import("prettier").AstPath<import("java-parser").BlockCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
blockStatements(path: import("prettier").AstPath<import("java-parser").BlockStatementsCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
blockStatement: typeof printSingle;
|
||||||
|
localVariableDeclarationStatement(path: import("prettier").AstPath<import("java-parser").LocalVariableDeclarationStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
localVariableDeclaration(path: import("prettier").AstPath<import("java-parser").LocalVariableDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
localVariableType: typeof printSingle;
|
||||||
|
statement: typeof printSingle;
|
||||||
|
statementWithoutTrailingSubstatement: typeof printSingle;
|
||||||
|
emptyStatement(): string;
|
||||||
|
labeledStatement(path: import("prettier").AstPath<import("java-parser").LabeledStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
expressionStatement(path: import("prettier").AstPath<import("java-parser").ExpressionStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
statementExpression: typeof printSingle;
|
||||||
|
ifStatement(path: import("prettier").AstPath<import("java-parser").IfStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
assertStatement(path: import("prettier").AstPath<import("java-parser").AssertStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
switchStatement(path: import("prettier").AstPath<import("java-parser").SwitchStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
switchBlock(path: import("prettier").AstPath<import("java-parser").SwitchBlockCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
switchBlockStatementGroup(path: import("prettier").AstPath<import("java-parser").SwitchBlockStatementGroupCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
switchLabel(path: import("prettier").AstPath<import("java-parser").SwitchLabelCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): "default" | builders.Group | builders.Doc[];
|
||||||
|
switchRule(path: import("prettier").AstPath<import("java-parser").SwitchRuleCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
caseConstant: typeof printSingle;
|
||||||
|
casePattern: typeof printSingle;
|
||||||
|
whileStatement(path: import("prettier").AstPath<import("java-parser").WhileStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
doStatement(path: import("prettier").AstPath<import("java-parser").DoStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): (string | builders.Group | builders.Doc[])[];
|
||||||
|
forStatement: typeof printSingle;
|
||||||
|
basicForStatement(path: import("prettier").AstPath<import("java-parser").BasicForStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
forInit: typeof printSingle;
|
||||||
|
forUpdate: typeof printSingle;
|
||||||
|
statementExpressionList(path: import("prettier").AstPath<import("java-parser").StatementExpressionListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Group;
|
||||||
|
enhancedForStatement(path: import("prettier").AstPath<import("java-parser").EnhancedForStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Group;
|
||||||
|
breakStatement(path: import("prettier").AstPath<import("java-parser").BreakStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[] | "break;";
|
||||||
|
continueStatement(path: import("prettier").AstPath<import("java-parser").ContinueStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[] | "continue;";
|
||||||
|
returnStatement(path: import("prettier").AstPath<import("java-parser").ReturnStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
throwStatement(path: import("prettier").AstPath<import("java-parser").ThrowStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
synchronizedStatement(path: import("prettier").AstPath<import("java-parser").SynchronizedStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
tryStatement(path: import("prettier").AstPath<import("java-parser").TryStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc;
|
||||||
|
catches(path: import("prettier").AstPath<import("java-parser").CatchesCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
catchClause(path: import("prettier").AstPath<import("java-parser").CatchClauseCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
catchFormalParameter(path: import("prettier").AstPath<import("java-parser").CatchFormalParameterCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
catchType(path: import("prettier").AstPath<import("java-parser").CatchTypeCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
finally(path: import("prettier").AstPath<import("java-parser").FinallyCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
tryWithResourcesStatement(path: import("prettier").AstPath<import("java-parser").TryWithResourcesStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
resourceSpecification(path: import("prettier").AstPath<import("java-parser").ResourceSpecificationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Group | "()";
|
||||||
|
resourceList(path: import("prettier").AstPath<import("java-parser").ResourceListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
resource: typeof printSingle;
|
||||||
|
yieldStatement(path: import("prettier").AstPath<import("java-parser").YieldStatementCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: import("./helpers.js").JavaPrintFn): builders.Doc[];
|
||||||
|
variableAccess: typeof printSingle;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import { call, definedKeys, indentInParentheses, isBinaryExpression, isEmptyStatement, lineEndWithComments, lineStartWithComments, map, onlyDefinedKey, printBlock, printDanglingComments, printSingle, printWithModifiers } from "./helpers.js";
|
||||||
|
const { group, hardline, ifBreak, indent, join, line, softline } = builders;
|
||||||
|
export default {
|
||||||
|
block(path, print) {
|
||||||
|
const statements = path.node.children.blockStatements
|
||||||
|
? call(path, print, "blockStatements")
|
||||||
|
: [];
|
||||||
|
return printBlock(path, statements.length ? [statements] : []);
|
||||||
|
},
|
||||||
|
blockStatements(path, print) {
|
||||||
|
return join(hardline, map(path, statementPath => {
|
||||||
|
const { node, previous } = statementPath;
|
||||||
|
const statement = print(statementPath);
|
||||||
|
return previous &&
|
||||||
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1
|
||||||
|
? [hardline, statement]
|
||||||
|
: statement;
|
||||||
|
}, "blockStatement").filter(doc => doc !== ""));
|
||||||
|
},
|
||||||
|
blockStatement: printSingle,
|
||||||
|
localVariableDeclarationStatement(path, print) {
|
||||||
|
return [call(path, print, "localVariableDeclaration"), ";"];
|
||||||
|
},
|
||||||
|
localVariableDeclaration(path, print) {
|
||||||
|
const declaration = join(" ", [
|
||||||
|
call(path, print, "localVariableType"),
|
||||||
|
call(path, print, "variableDeclaratorList")
|
||||||
|
]);
|
||||||
|
return printWithModifiers(path, print, "variableModifier", declaration);
|
||||||
|
},
|
||||||
|
localVariableType: printSingle,
|
||||||
|
statement: printSingle,
|
||||||
|
statementWithoutTrailingSubstatement: printSingle,
|
||||||
|
emptyStatement() {
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
labeledStatement(path, print) {
|
||||||
|
return [
|
||||||
|
call(path, print, "Identifier"),
|
||||||
|
": ",
|
||||||
|
call(path, print, "statement")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
expressionStatement(path, print) {
|
||||||
|
return [call(path, print, "statementExpression"), ";"];
|
||||||
|
},
|
||||||
|
statementExpression: printSingle,
|
||||||
|
ifStatement(path, print) {
|
||||||
|
var _a;
|
||||||
|
const { children } = path.node;
|
||||||
|
const hasEmptyStatement = isEmptyStatement(children.statement[0]);
|
||||||
|
const statements = map(path, print, "statement");
|
||||||
|
const statement = [
|
||||||
|
"if ",
|
||||||
|
indentInParentheses(call(path, print, "expression")),
|
||||||
|
hasEmptyStatement ? ";" : [" ", statements[0]]
|
||||||
|
];
|
||||||
|
if (children.Else) {
|
||||||
|
const danglingComments = printDanglingComments(path);
|
||||||
|
if (danglingComments.length) {
|
||||||
|
statement.push(hardline, ...danglingComments, hardline);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const elseHasBlock = ((_a = children.statement[0].children
|
||||||
|
.statementWithoutTrailingSubstatement) === null || _a === void 0 ? void 0 : _a[0].children.block) !==
|
||||||
|
undefined;
|
||||||
|
statement.push(elseHasBlock ? " " : hardline);
|
||||||
|
}
|
||||||
|
const elseHasEmptyStatement = isEmptyStatement(children.statement[1]);
|
||||||
|
statement.push("else", elseHasEmptyStatement ? ";" : [" ", statements[1]]);
|
||||||
|
}
|
||||||
|
return statement;
|
||||||
|
},
|
||||||
|
assertStatement(path, print) {
|
||||||
|
return ["assert ", ...join([" : "], map(path, print, "expression")), ";"];
|
||||||
|
},
|
||||||
|
switchStatement(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
"switch",
|
||||||
|
indentInParentheses(call(path, print, "expression")),
|
||||||
|
call(path, print, "switchBlock")
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
switchBlock(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const caseKeys = definedKeys(children, [
|
||||||
|
"switchBlockStatementGroup",
|
||||||
|
"switchRule"
|
||||||
|
]);
|
||||||
|
const cases = caseKeys.length === 1 ? map(path, print, caseKeys[0]) : [];
|
||||||
|
return printBlock(path, cases);
|
||||||
|
},
|
||||||
|
switchBlockStatementGroup(path, print) {
|
||||||
|
var _a, _b;
|
||||||
|
const { children } = path.node;
|
||||||
|
const switchLabel = call(path, print, "switchLabel");
|
||||||
|
if (!children.blockStatements) {
|
||||||
|
return [switchLabel, ":"];
|
||||||
|
}
|
||||||
|
const blockStatements = call(path, print, "blockStatements");
|
||||||
|
const statements = children.blockStatements[0].children.blockStatement;
|
||||||
|
const onlyStatementIsBlock = statements.length === 1 &&
|
||||||
|
((_b = (_a = statements[0].children.statement) === null || _a === void 0 ? void 0 : _a[0].children.statementWithoutTrailingSubstatement) === null || _b === void 0 ? void 0 : _b[0].children.block) !== undefined;
|
||||||
|
return [
|
||||||
|
switchLabel,
|
||||||
|
":",
|
||||||
|
onlyStatementIsBlock
|
||||||
|
? [" ", blockStatements]
|
||||||
|
: indent([hardline, blockStatements])
|
||||||
|
];
|
||||||
|
},
|
||||||
|
switchLabel(path, print) {
|
||||||
|
var _a, _b;
|
||||||
|
const { children } = path.node;
|
||||||
|
if (!((_b = (_a = children.caseConstant) !== null && _a !== void 0 ? _a : children.casePattern) !== null && _b !== void 0 ? _b : children.Null)) {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
const values = [];
|
||||||
|
if (children.Null) {
|
||||||
|
values.push("null");
|
||||||
|
if (children.Default) {
|
||||||
|
values.push("default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const valuesKey = onlyDefinedKey(children, [
|
||||||
|
"caseConstant",
|
||||||
|
"casePattern"
|
||||||
|
]);
|
||||||
|
values.push(...map(path, print, valuesKey));
|
||||||
|
}
|
||||||
|
const hasMultipleValues = values.length > 1;
|
||||||
|
const label = hasMultipleValues
|
||||||
|
? ["case", indent([line, ...join([",", line], values)])]
|
||||||
|
: ["case ", values[0]];
|
||||||
|
return children.guard
|
||||||
|
? [
|
||||||
|
group([...label, hasMultipleValues ? line : " "]),
|
||||||
|
call(path, print, "guard")
|
||||||
|
]
|
||||||
|
: group(label);
|
||||||
|
},
|
||||||
|
switchRule(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const bodyKey = onlyDefinedKey(children, [
|
||||||
|
"block",
|
||||||
|
"expression",
|
||||||
|
"throwStatement"
|
||||||
|
]);
|
||||||
|
const parts = [
|
||||||
|
call(path, print, "switchLabel"),
|
||||||
|
" -> ",
|
||||||
|
call(path, print, bodyKey)
|
||||||
|
];
|
||||||
|
if (children.Semicolon) {
|
||||||
|
parts.push(";");
|
||||||
|
}
|
||||||
|
return parts;
|
||||||
|
},
|
||||||
|
caseConstant: printSingle,
|
||||||
|
casePattern: printSingle,
|
||||||
|
whileStatement(path, print) {
|
||||||
|
const statement = call(path, print, "statement");
|
||||||
|
const hasEmptyStatement = isEmptyStatement(path.node.children.statement[0]);
|
||||||
|
return [
|
||||||
|
"while ",
|
||||||
|
indentInParentheses(call(path, print, "expression")),
|
||||||
|
...[hasEmptyStatement ? ";" : " ", statement]
|
||||||
|
];
|
||||||
|
},
|
||||||
|
doStatement(path, print) {
|
||||||
|
const hasEmptyStatement = isEmptyStatement(path.node.children.statement[0]);
|
||||||
|
return [
|
||||||
|
"do",
|
||||||
|
hasEmptyStatement ? ";" : [" ", call(path, print, "statement")],
|
||||||
|
" while ",
|
||||||
|
indentInParentheses(call(path, print, "expression")),
|
||||||
|
";"
|
||||||
|
];
|
||||||
|
},
|
||||||
|
forStatement: printSingle,
|
||||||
|
basicForStatement(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const danglingComments = printDanglingComments(path);
|
||||||
|
if (danglingComments.length) {
|
||||||
|
danglingComments.push(hardline);
|
||||||
|
}
|
||||||
|
const expressions = ["forInit", "expression", "forUpdate"].map(expressionKey => expressionKey in children ? call(path, print, expressionKey) : "");
|
||||||
|
const hasEmptyStatement = isEmptyStatement(children.statement[0]);
|
||||||
|
return [
|
||||||
|
...danglingComments,
|
||||||
|
"for ",
|
||||||
|
expressions.some(expression => expression !== "")
|
||||||
|
? indentInParentheses(join([";", line], expressions))
|
||||||
|
: "(;;)",
|
||||||
|
hasEmptyStatement ? ";" : [" ", call(path, print, "statement")]
|
||||||
|
];
|
||||||
|
},
|
||||||
|
forInit: printSingle,
|
||||||
|
forUpdate: printSingle,
|
||||||
|
statementExpressionList(path, print) {
|
||||||
|
return group(map(path, print, "statementExpression").map((expression, index) => index === 0 ? expression : [",", indent([line, expression])]));
|
||||||
|
},
|
||||||
|
enhancedForStatement(path, print) {
|
||||||
|
var _a;
|
||||||
|
const statementNode = path.node.children.statement[0];
|
||||||
|
const forStatement = [
|
||||||
|
printDanglingComments(path),
|
||||||
|
"for ",
|
||||||
|
"(",
|
||||||
|
call(path, print, "localVariableDeclaration"),
|
||||||
|
" : ",
|
||||||
|
call(path, print, "expression"),
|
||||||
|
")"
|
||||||
|
];
|
||||||
|
if (isEmptyStatement(statementNode)) {
|
||||||
|
forStatement.push(";");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const hasStatementBlock = ((_a = statementNode.children.statementWithoutTrailingSubstatement) === null || _a === void 0 ? void 0 : _a[0].children.block) !== undefined;
|
||||||
|
const statement = call(path, print, "statement");
|
||||||
|
forStatement.push(hasStatementBlock ? [" ", statement] : indent([line, statement]));
|
||||||
|
}
|
||||||
|
return group(forStatement);
|
||||||
|
},
|
||||||
|
breakStatement(path, print) {
|
||||||
|
return path.node.children.Identifier
|
||||||
|
? ["break ", call(path, print, "Identifier"), ";"]
|
||||||
|
: "break;";
|
||||||
|
},
|
||||||
|
continueStatement(path, print) {
|
||||||
|
return path.node.children.Identifier
|
||||||
|
? ["continue ", call(path, print, "Identifier"), ";"]
|
||||||
|
: "continue;";
|
||||||
|
},
|
||||||
|
returnStatement(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const statement = ["return"];
|
||||||
|
if (children.expression) {
|
||||||
|
statement.push(" ");
|
||||||
|
const expression = call(path, print, "expression");
|
||||||
|
if (isBinaryExpression(children.expression[0])) {
|
||||||
|
statement.push(group([
|
||||||
|
ifBreak("("),
|
||||||
|
indent([softline, expression]),
|
||||||
|
softline,
|
||||||
|
ifBreak(")")
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
statement.push(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statement.push(";");
|
||||||
|
return statement;
|
||||||
|
},
|
||||||
|
throwStatement(path, print) {
|
||||||
|
return ["throw ", call(path, print, "expression"), ";"];
|
||||||
|
},
|
||||||
|
synchronizedStatement(path, print) {
|
||||||
|
return [
|
||||||
|
"synchronized ",
|
||||||
|
indentInParentheses(call(path, print, "expression")),
|
||||||
|
" ",
|
||||||
|
call(path, print, "block")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
tryStatement(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
if (children.tryWithResourcesStatement) {
|
||||||
|
return call(path, print, "tryWithResourcesStatement");
|
||||||
|
}
|
||||||
|
const blocks = ["try", call(path, print, "block")];
|
||||||
|
if (children.catches) {
|
||||||
|
blocks.push(call(path, print, "catches"));
|
||||||
|
}
|
||||||
|
if (children.finally) {
|
||||||
|
blocks.push(call(path, print, "finally"));
|
||||||
|
}
|
||||||
|
return join(" ", blocks);
|
||||||
|
},
|
||||||
|
catches(path, print) {
|
||||||
|
return join(" ", map(path, print, "catchClause"));
|
||||||
|
},
|
||||||
|
catchClause(path, print) {
|
||||||
|
return [
|
||||||
|
"catch ",
|
||||||
|
indentInParentheses(call(path, print, "catchFormalParameter")),
|
||||||
|
" ",
|
||||||
|
call(path, print, "block")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
catchFormalParameter(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "variableModifier"),
|
||||||
|
call(path, print, "catchType"),
|
||||||
|
call(path, print, "variableDeclaratorId")
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
catchType(path, print) {
|
||||||
|
return join([line, "| "], [call(path, print, "unannClassType"), ...map(path, print, "classType")]);
|
||||||
|
},
|
||||||
|
finally(path, print) {
|
||||||
|
return ["finally ", call(path, print, "block")];
|
||||||
|
},
|
||||||
|
tryWithResourcesStatement(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const blocks = [
|
||||||
|
"try",
|
||||||
|
call(path, print, "resourceSpecification"),
|
||||||
|
call(path, print, "block")
|
||||||
|
];
|
||||||
|
if (children.catches) {
|
||||||
|
blocks.push(call(path, print, "catches"));
|
||||||
|
}
|
||||||
|
if (children.finally) {
|
||||||
|
blocks.push(call(path, print, "finally"));
|
||||||
|
}
|
||||||
|
return join(" ", blocks);
|
||||||
|
},
|
||||||
|
resourceSpecification(path, print) {
|
||||||
|
const resources = [call(path, print, "resourceList")];
|
||||||
|
if (path.node.children.Semicolon) {
|
||||||
|
resources.push(ifBreak(";"));
|
||||||
|
}
|
||||||
|
return indentInParentheses(resources);
|
||||||
|
},
|
||||||
|
resourceList(path, print) {
|
||||||
|
return join([";", line], map(path, print, "resource"));
|
||||||
|
},
|
||||||
|
resource: printSingle,
|
||||||
|
yieldStatement(path, print) {
|
||||||
|
return ["yield ", call(path, print, "expression"), ";"];
|
||||||
|
},
|
||||||
|
variableAccess: printSingle
|
||||||
|
};
|
||||||
157
frontend/src/common/prettier/plugins/java/printers/classes.d.ts
vendored
Normal file
157
frontend/src/common/prettier/plugins/java/printers/classes.d.ts
vendored
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import type { ClassBodyCstNode, EnumBodyDeclarationsCstNode } from "java-parser";
|
||||||
|
import type { AstPath } from "prettier";
|
||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import { printClassPermits, printClassType, printSingle, type JavaPrintFn } from "./helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
classDeclaration(path: AstPath<import("java-parser").ClassDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
normalClassDeclaration(path: AstPath<import("java-parser").NormalClassDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
classModifier: typeof printSingle;
|
||||||
|
typeParameters(path: AstPath<import("java-parser").TypeParametersCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group;
|
||||||
|
typeParameterList(path: AstPath<import("java-parser").TypeParameterListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
classExtends(path: AstPath<import("java-parser").ClassExtendsCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
classImplements(path: AstPath<import("java-parser").ClassImplementsCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group;
|
||||||
|
classPermits: typeof printClassPermits;
|
||||||
|
interfaceTypeList(path: AstPath<import("java-parser").InterfaceTypeListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group;
|
||||||
|
classBody(path: AstPath<ClassBodyCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
classBodyDeclaration: typeof printSingle;
|
||||||
|
classMemberDeclaration(path: AstPath<import("java-parser").ClassMemberDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
fieldDeclaration(path: AstPath<import("java-parser").FieldDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
fieldModifier: typeof printSingle;
|
||||||
|
variableDeclaratorList(path: AstPath<import("java-parser").VariableDeclaratorListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | builders.Doc[];
|
||||||
|
variableDeclarator(path: AstPath<import("java-parser").VariableDeclaratorCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
variableDeclaratorId(path: AstPath<import("java-parser").VariableDeclaratorIdCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
variableInitializer: typeof printSingle;
|
||||||
|
unannType: typeof printSingle;
|
||||||
|
unannPrimitiveTypeWithOptionalDimsSuffix(path: AstPath<import("java-parser").UnannPrimitiveTypeWithOptionalDimsSuffixCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
unannPrimitiveType: typeof printSingle;
|
||||||
|
unannReferenceType(path: AstPath<import("java-parser").UnannReferenceTypeCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
unannClassOrInterfaceType: typeof printSingle;
|
||||||
|
unannClassType: typeof printClassType;
|
||||||
|
unannInterfaceType: typeof printSingle;
|
||||||
|
unannTypeVariable: typeof printSingle;
|
||||||
|
methodDeclaration(path: AstPath<import("java-parser").MethodDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
methodModifier: typeof printSingle;
|
||||||
|
methodHeader(path: AstPath<import("java-parser").MethodHeaderCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group;
|
||||||
|
result: typeof printSingle;
|
||||||
|
methodDeclarator(path: AstPath<import("java-parser").MethodDeclaratorCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
receiverParameter(path: AstPath<import("java-parser").ReceiverParameterCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
formalParameterList(path: AstPath<import("java-parser").FormalParameterListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
formalParameter: typeof printSingle;
|
||||||
|
variableParaRegularParameter(path: AstPath<import("java-parser").VariableParaRegularParameterCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
variableArityParameter(path: AstPath<import("java-parser").VariableArityParameterCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
variableModifier: typeof printSingle;
|
||||||
|
throws(path: AstPath<import("java-parser").ThrowsCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
exceptionTypeList(path: AstPath<import("java-parser").ExceptionTypeListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
exceptionType: typeof printSingle;
|
||||||
|
methodBody: typeof printSingle;
|
||||||
|
instanceInitializer: typeof printSingle;
|
||||||
|
staticInitializer(path: AstPath<import("java-parser").StaticInitializerCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
constructorDeclaration(path: AstPath<import("java-parser").ConstructorDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
constructorModifier: typeof printSingle;
|
||||||
|
constructorDeclarator(path: AstPath<import("java-parser").ConstructorDeclaratorCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
simpleTypeName: typeof printSingle;
|
||||||
|
constructorBody(path: AstPath<import("java-parser").ConstructorBodyCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
explicitConstructorInvocation: typeof printSingle;
|
||||||
|
unqualifiedExplicitConstructorInvocation(path: AstPath<import("java-parser").UnqualifiedExplicitConstructorInvocationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
qualifiedExplicitConstructorInvocation(path: AstPath<import("java-parser").QualifiedExplicitConstructorInvocationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
enumDeclaration(path: AstPath<import("java-parser").EnumDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
enumBody(path: AstPath<import("java-parser").EnumBodyCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
enumConstantList(path: AstPath<import("java-parser").EnumConstantListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
enumConstant(path: AstPath<import("java-parser").EnumConstantCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
enumConstantModifier: typeof printSingle;
|
||||||
|
enumBodyDeclarations(path: AstPath<EnumBodyDeclarationsCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
recordDeclaration(path: AstPath<import("java-parser").RecordDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
recordHeader(path: AstPath<import("java-parser").RecordHeaderCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "()";
|
||||||
|
recordComponentList(path: AstPath<import("java-parser").RecordComponentListCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
recordComponent(path: AstPath<import("java-parser").RecordComponentCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group;
|
||||||
|
variableArityRecordComponent(path: AstPath<import("java-parser").VariableArityRecordComponentCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
recordComponentModifier: typeof printSingle;
|
||||||
|
recordBody(path: AstPath<import("java-parser").RecordBodyCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
recordBodyDeclaration: typeof printSingle;
|
||||||
|
compactConstructorDeclaration(path: AstPath<import("java-parser").CompactConstructorDeclarationCstNode & {
|
||||||
|
comments?: import("../comments.js").JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
446
frontend/src/common/prettier/plugins/java/printers/classes.js
Normal file
446
frontend/src/common/prettier/plugins/java/printers/classes.js
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import { call, each, hasDeclarationAnnotations, hasLeadingComments, indentInParentheses, isBinaryExpression, lineEndWithComments, lineStartWithComments, map, onlyDefinedKey, printBlock, printClassPermits, printClassType, printDanglingComments, printList, printSingle, printWithModifiers } from "./helpers.js";
|
||||||
|
const { group, hardline, indent, indentIfBreak, join, line, softline } = builders;
|
||||||
|
export default {
|
||||||
|
classDeclaration(path, print) {
|
||||||
|
const declarationKey = onlyDefinedKey(path.node.children, [
|
||||||
|
"enumDeclaration",
|
||||||
|
"normalClassDeclaration",
|
||||||
|
"recordDeclaration"
|
||||||
|
]);
|
||||||
|
const declaration = call(path, print, declarationKey);
|
||||||
|
return printWithModifiers(path, print, "classModifier", declaration, true);
|
||||||
|
},
|
||||||
|
normalClassDeclaration(path, print) {
|
||||||
|
const { classExtends, classImplements, classPermits, typeParameters } = path.node.children;
|
||||||
|
const header = ["class ", call(path, print, "typeIdentifier")];
|
||||||
|
if (typeParameters) {
|
||||||
|
header.push(call(path, print, "typeParameters"));
|
||||||
|
}
|
||||||
|
if (classExtends) {
|
||||||
|
header.push(indent([line, call(path, print, "classExtends")]));
|
||||||
|
}
|
||||||
|
if (classImplements) {
|
||||||
|
header.push(indent([line, call(path, print, "classImplements")]));
|
||||||
|
}
|
||||||
|
if (classPermits) {
|
||||||
|
header.push(indent([line, call(path, print, "classPermits")]));
|
||||||
|
}
|
||||||
|
return [group(header), " ", call(path, print, "classBody")];
|
||||||
|
},
|
||||||
|
classModifier: printSingle,
|
||||||
|
typeParameters(path, print) {
|
||||||
|
return group([
|
||||||
|
"<",
|
||||||
|
indent([softline, call(path, print, "typeParameterList")]),
|
||||||
|
softline,
|
||||||
|
">"
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
typeParameterList(path, print) {
|
||||||
|
return printList(path, print, "typeParameter");
|
||||||
|
},
|
||||||
|
classExtends(path, print) {
|
||||||
|
return ["extends ", call(path, print, "classType")];
|
||||||
|
},
|
||||||
|
classImplements(path, print) {
|
||||||
|
return group([
|
||||||
|
"implements",
|
||||||
|
indent([line, call(path, print, "interfaceTypeList")])
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
classPermits: printClassPermits,
|
||||||
|
interfaceTypeList(path, print) {
|
||||||
|
return group(printList(path, print, "interfaceType"));
|
||||||
|
},
|
||||||
|
classBody(path, print) {
|
||||||
|
return printBlock(path, printClassBodyDeclarations(path, print));
|
||||||
|
},
|
||||||
|
classBodyDeclaration: printSingle,
|
||||||
|
classMemberDeclaration(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
return children.Semicolon
|
||||||
|
? ""
|
||||||
|
: call(path, print, onlyDefinedKey(children));
|
||||||
|
},
|
||||||
|
fieldDeclaration(path, print) {
|
||||||
|
const declaration = [
|
||||||
|
call(path, print, "unannType"),
|
||||||
|
" ",
|
||||||
|
call(path, print, "variableDeclaratorList"),
|
||||||
|
";"
|
||||||
|
];
|
||||||
|
return printWithModifiers(path, print, "fieldModifier", declaration);
|
||||||
|
},
|
||||||
|
fieldModifier: printSingle,
|
||||||
|
variableDeclaratorList(path, print) {
|
||||||
|
var _a;
|
||||||
|
const declarators = map(path, print, "variableDeclarator");
|
||||||
|
return declarators.length > 1 &&
|
||||||
|
path.node.children.variableDeclarator.some(({ children }) => children.Equals)
|
||||||
|
? group(indent(join([",", line], declarators)), {
|
||||||
|
shouldBreak: ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) !== "forInit"
|
||||||
|
})
|
||||||
|
: join(", ", declarators);
|
||||||
|
},
|
||||||
|
variableDeclarator(path, print) {
|
||||||
|
var _a, _b;
|
||||||
|
const { children } = path.node;
|
||||||
|
const variableInitializer = (_a = children.variableInitializer) === null || _a === void 0 ? void 0 : _a[0];
|
||||||
|
const declaratorId = call(path, print, "variableDeclaratorId");
|
||||||
|
if (!variableInitializer) {
|
||||||
|
return declaratorId;
|
||||||
|
}
|
||||||
|
const expression = (_b = variableInitializer.children.expression) === null || _b === void 0 ? void 0 : _b[0];
|
||||||
|
const declarator = [declaratorId, " ", call(path, print, "Equals")];
|
||||||
|
const initializer = call(path, print, "variableInitializer");
|
||||||
|
if (hasLeadingComments(variableInitializer) ||
|
||||||
|
(expression && isBinaryExpression(expression))) {
|
||||||
|
declarator.push(group(indent([line, initializer])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const groupId = Symbol("assignment");
|
||||||
|
declarator.push(group(indent(line), { id: groupId }), indentIfBreak(initializer, { groupId }));
|
||||||
|
}
|
||||||
|
return group(declarator);
|
||||||
|
},
|
||||||
|
variableDeclaratorId(path, print) {
|
||||||
|
const { dims, Underscore } = path.node.children;
|
||||||
|
if (Underscore) {
|
||||||
|
return "_";
|
||||||
|
}
|
||||||
|
const identifier = call(path, print, "Identifier");
|
||||||
|
return dims ? [identifier, call(path, print, "dims")] : identifier;
|
||||||
|
},
|
||||||
|
variableInitializer: printSingle,
|
||||||
|
unannType: printSingle,
|
||||||
|
unannPrimitiveTypeWithOptionalDimsSuffix(path, print) {
|
||||||
|
const type = call(path, print, "unannPrimitiveType");
|
||||||
|
return path.node.children.dims ? [type, call(path, print, "dims")] : type;
|
||||||
|
},
|
||||||
|
unannPrimitiveType: printSingle,
|
||||||
|
unannReferenceType(path, print) {
|
||||||
|
const type = call(path, print, "unannClassOrInterfaceType");
|
||||||
|
return path.node.children.dims ? [type, call(path, print, "dims")] : type;
|
||||||
|
},
|
||||||
|
unannClassOrInterfaceType: printSingle,
|
||||||
|
unannClassType: printClassType,
|
||||||
|
unannInterfaceType: printSingle,
|
||||||
|
unannTypeVariable: printSingle,
|
||||||
|
methodDeclaration(path, print) {
|
||||||
|
const declaration = [
|
||||||
|
call(path, print, "methodHeader"),
|
||||||
|
path.node.children.methodBody[0].children.Semicolon ? "" : " ",
|
||||||
|
call(path, print, "methodBody")
|
||||||
|
];
|
||||||
|
return printWithModifiers(path, print, "methodModifier", declaration);
|
||||||
|
},
|
||||||
|
methodModifier: printSingle,
|
||||||
|
methodHeader(path, print) {
|
||||||
|
const { typeParameters, annotation, throws } = path.node.children;
|
||||||
|
const header = [];
|
||||||
|
if (typeParameters) {
|
||||||
|
header.push(call(path, print, "typeParameters"));
|
||||||
|
}
|
||||||
|
if (annotation) {
|
||||||
|
header.push(join(line, map(path, print, "annotation")));
|
||||||
|
}
|
||||||
|
header.push(call(path, print, "result"), call(path, print, "methodDeclarator"));
|
||||||
|
return throws
|
||||||
|
? group([
|
||||||
|
...join(" ", header),
|
||||||
|
group(indent([line, call(path, print, "throws")]))
|
||||||
|
])
|
||||||
|
: group(join(" ", header));
|
||||||
|
},
|
||||||
|
result: printSingle,
|
||||||
|
methodDeclarator(path, print) {
|
||||||
|
const { dims, formalParameterList, receiverParameter } = path.node.children;
|
||||||
|
const declarator = [call(path, print, "Identifier")];
|
||||||
|
const parameters = [];
|
||||||
|
if (receiverParameter) {
|
||||||
|
parameters.push(call(path, print, "receiverParameter"));
|
||||||
|
}
|
||||||
|
if (formalParameterList) {
|
||||||
|
parameters.push(call(path, print, "formalParameterList"));
|
||||||
|
}
|
||||||
|
const items = parameters.length
|
||||||
|
? join([",", line], parameters)
|
||||||
|
: printDanglingComments(path);
|
||||||
|
declarator.push(items.length ? indentInParentheses(items) : "()");
|
||||||
|
if (dims) {
|
||||||
|
declarator.push(call(path, print, "dims"));
|
||||||
|
}
|
||||||
|
return declarator;
|
||||||
|
},
|
||||||
|
receiverParameter(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "annotation"),
|
||||||
|
call(path, print, "unannType"),
|
||||||
|
path.node.children.Identifier
|
||||||
|
? [call(path, print, "Identifier"), ".this"]
|
||||||
|
: "this"
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
formalParameterList(path, print) {
|
||||||
|
return printList(path, print, "formalParameter");
|
||||||
|
},
|
||||||
|
formalParameter: printSingle,
|
||||||
|
variableParaRegularParameter(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "variableModifier"),
|
||||||
|
call(path, print, "unannType"),
|
||||||
|
call(path, print, "variableDeclaratorId")
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
variableArityParameter(path, print) {
|
||||||
|
const type = join(" ", [
|
||||||
|
...map(path, print, "variableModifier"),
|
||||||
|
call(path, print, "unannType"),
|
||||||
|
...map(path, print, "annotation")
|
||||||
|
]);
|
||||||
|
return [type, "... ", call(path, print, "Identifier")];
|
||||||
|
},
|
||||||
|
variableModifier: printSingle,
|
||||||
|
throws(path, print) {
|
||||||
|
return ["throws ", call(path, print, "exceptionTypeList")];
|
||||||
|
},
|
||||||
|
exceptionTypeList(path, print) {
|
||||||
|
return join(", ", map(path, print, "exceptionType"));
|
||||||
|
},
|
||||||
|
exceptionType: printSingle,
|
||||||
|
methodBody: printSingle,
|
||||||
|
instanceInitializer: printSingle,
|
||||||
|
staticInitializer(path, print) {
|
||||||
|
return ["static ", call(path, print, "block")];
|
||||||
|
},
|
||||||
|
constructorDeclaration(path, print) {
|
||||||
|
const declaration = [call(path, print, "constructorDeclarator")];
|
||||||
|
if (path.node.children.throws) {
|
||||||
|
declaration.push(group(indent([line, call(path, print, "throws")])));
|
||||||
|
}
|
||||||
|
declaration.push(" ", call(path, print, "constructorBody"));
|
||||||
|
return printWithModifiers(path, print, "constructorModifier", declaration, true);
|
||||||
|
},
|
||||||
|
constructorModifier: printSingle,
|
||||||
|
constructorDeclarator(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const parameters = [];
|
||||||
|
if (children.receiverParameter) {
|
||||||
|
parameters.push(call(path, print, "receiverParameter"));
|
||||||
|
}
|
||||||
|
if (children.formalParameterList) {
|
||||||
|
parameters.push(call(path, print, "formalParameterList"));
|
||||||
|
}
|
||||||
|
const header = [call(path, print, "simpleTypeName")];
|
||||||
|
header.push(parameters.length
|
||||||
|
? indentInParentheses(join([",", line], parameters))
|
||||||
|
: "()");
|
||||||
|
return children.typeParameters
|
||||||
|
? [call(path, print, "typeParameters"), " ", ...header]
|
||||||
|
: header;
|
||||||
|
},
|
||||||
|
simpleTypeName: printSingle,
|
||||||
|
constructorBody(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const statements = [];
|
||||||
|
if (children.explicitConstructorInvocation) {
|
||||||
|
statements.push(call(path, print, "explicitConstructorInvocation"));
|
||||||
|
}
|
||||||
|
if (children.blockStatements) {
|
||||||
|
statements.push(call(path, print, "blockStatements"));
|
||||||
|
}
|
||||||
|
return printBlock(path, statements);
|
||||||
|
},
|
||||||
|
explicitConstructorInvocation: printSingle,
|
||||||
|
unqualifiedExplicitConstructorInvocation(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const invocation = [];
|
||||||
|
if (children.typeArguments) {
|
||||||
|
invocation.push(call(path, print, "typeArguments"));
|
||||||
|
}
|
||||||
|
invocation.push(children.Super ? "super" : "this");
|
||||||
|
if (children.argumentList) {
|
||||||
|
invocation.push(group(["(", call(path, print, "argumentList"), ")"]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
invocation.push(indentInParentheses(printDanglingComments(path), { shouldBreak: true }));
|
||||||
|
}
|
||||||
|
invocation.push(";");
|
||||||
|
return invocation;
|
||||||
|
},
|
||||||
|
qualifiedExplicitConstructorInvocation(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const invocation = [call(path, print, "expressionName"), "."];
|
||||||
|
if (children.typeArguments) {
|
||||||
|
invocation.push(call(path, print, "typeArguments"));
|
||||||
|
}
|
||||||
|
invocation.push("super");
|
||||||
|
if (children.argumentList) {
|
||||||
|
invocation.push(group(["(", call(path, print, "argumentList"), ")"]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
invocation.push(indentInParentheses(printDanglingComments(path), { shouldBreak: true }));
|
||||||
|
}
|
||||||
|
invocation.push(";");
|
||||||
|
return invocation;
|
||||||
|
},
|
||||||
|
enumDeclaration(path, print) {
|
||||||
|
const header = ["enum", call(path, print, "typeIdentifier")];
|
||||||
|
if (path.node.children.classImplements) {
|
||||||
|
header.push(call(path, print, "classImplements"));
|
||||||
|
}
|
||||||
|
return join(" ", [...header, call(path, print, "enumBody")]);
|
||||||
|
},
|
||||||
|
enumBody(path, print, options) {
|
||||||
|
var _a;
|
||||||
|
const { children } = path.node;
|
||||||
|
const contents = [];
|
||||||
|
const hasNonEmptyDeclaration = ((_a = children.enumBodyDeclarations) !== null && _a !== void 0 ? _a : [])
|
||||||
|
.flatMap(({ children }) => { var _a; return (_a = children.classBodyDeclaration) !== null && _a !== void 0 ? _a : []; })
|
||||||
|
.some(({ children }) => { var _a; return !((_a = children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.Semicolon); });
|
||||||
|
if (children.enumConstantList) {
|
||||||
|
contents.push(call(path, print, "enumConstantList"));
|
||||||
|
if (!hasNonEmptyDeclaration && options.trailingComma !== "none") {
|
||||||
|
contents.push(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNonEmptyDeclaration) {
|
||||||
|
contents.push(";", hardline, call(path, print, "enumBodyDeclarations"));
|
||||||
|
}
|
||||||
|
return printBlock(path, contents.length ? [contents] : []);
|
||||||
|
},
|
||||||
|
enumConstantList(path, print) {
|
||||||
|
return join([",", hardline], map(path, constantPath => {
|
||||||
|
const constant = print(constantPath);
|
||||||
|
const { node, previous } = constantPath;
|
||||||
|
return !previous ||
|
||||||
|
lineStartWithComments(node) <= lineEndWithComments(previous) + 1
|
||||||
|
? constant
|
||||||
|
: [hardline, constant];
|
||||||
|
}, "enumConstant"));
|
||||||
|
},
|
||||||
|
enumConstant(path, print) {
|
||||||
|
const { argumentList, classBody } = path.node.children;
|
||||||
|
const initializer = [call(path, print, "Identifier")];
|
||||||
|
if (argumentList) {
|
||||||
|
initializer.push(group(["(", call(path, print, "argumentList"), ")"]));
|
||||||
|
}
|
||||||
|
if (classBody) {
|
||||||
|
initializer.push(" ", call(path, print, "classBody"));
|
||||||
|
}
|
||||||
|
return printWithModifiers(path, print, "enumConstantModifier", initializer);
|
||||||
|
},
|
||||||
|
enumConstantModifier: printSingle,
|
||||||
|
enumBodyDeclarations(path, print) {
|
||||||
|
return join(hardline, printClassBodyDeclarations(path, print));
|
||||||
|
},
|
||||||
|
recordDeclaration(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const header = ["record ", call(path, print, "typeIdentifier")];
|
||||||
|
if (children.typeParameters) {
|
||||||
|
header.push(call(path, print, "typeParameters"));
|
||||||
|
}
|
||||||
|
header.push(call(path, print, "recordHeader"));
|
||||||
|
if (children.classImplements) {
|
||||||
|
header.push(" ", call(path, print, "classImplements"));
|
||||||
|
}
|
||||||
|
return [group(header), " ", call(path, print, "recordBody")];
|
||||||
|
},
|
||||||
|
recordHeader(path, print) {
|
||||||
|
return path.node.children.recordComponentList
|
||||||
|
? indentInParentheses(call(path, print, "recordComponentList"))
|
||||||
|
: indentInParentheses(printDanglingComments(path), { shouldBreak: true });
|
||||||
|
},
|
||||||
|
recordComponentList(path, print) {
|
||||||
|
return join([",", line], map(path, componentPath => {
|
||||||
|
const { node, previous } = componentPath;
|
||||||
|
const blankLine = previous &&
|
||||||
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1;
|
||||||
|
const component = print(componentPath);
|
||||||
|
return blankLine ? [softline, component] : component;
|
||||||
|
}, "recordComponent"));
|
||||||
|
},
|
||||||
|
recordComponent(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const component = [call(path, print, "unannType")];
|
||||||
|
if (children.Identifier ||
|
||||||
|
children.variableArityRecordComponent[0].children.annotation) {
|
||||||
|
component.push(" ");
|
||||||
|
}
|
||||||
|
const suffixKey = onlyDefinedKey(children, [
|
||||||
|
"Identifier",
|
||||||
|
"variableArityRecordComponent"
|
||||||
|
]);
|
||||||
|
component.push(call(path, print, suffixKey));
|
||||||
|
return group(join(line, [...map(path, print, "recordComponentModifier"), component]));
|
||||||
|
},
|
||||||
|
variableArityRecordComponent(path, print) {
|
||||||
|
return [
|
||||||
|
...join(" ", map(path, print, "annotation")),
|
||||||
|
"... ",
|
||||||
|
call(path, print, "Identifier")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
recordComponentModifier: printSingle,
|
||||||
|
recordBody(path, print) {
|
||||||
|
const declarations = [];
|
||||||
|
let previousRequiresPadding = false;
|
||||||
|
each(path, declarationPath => {
|
||||||
|
var _a, _b, _c, _d;
|
||||||
|
const declaration = print(declarationPath);
|
||||||
|
if (declaration === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { node, previous } = declarationPath;
|
||||||
|
const fieldDeclaration = (_c = (_b = (_a = node.children.classBodyDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.classMemberDeclaration) === null || _b === void 0 ? void 0 : _b[0].children.fieldDeclaration) === null || _c === void 0 ? void 0 : _c[0].children;
|
||||||
|
const currentRequiresPadding = !fieldDeclaration ||
|
||||||
|
hasDeclarationAnnotations((_d = fieldDeclaration.fieldModifier) !== null && _d !== void 0 ? _d : []);
|
||||||
|
const blankLine = declarations.length > 0 &&
|
||||||
|
(previousRequiresPadding ||
|
||||||
|
currentRequiresPadding ||
|
||||||
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1);
|
||||||
|
declarations.push(blankLine ? [hardline, declaration] : declaration);
|
||||||
|
previousRequiresPadding = currentRequiresPadding;
|
||||||
|
}, "recordBodyDeclaration");
|
||||||
|
return printBlock(path, declarations);
|
||||||
|
},
|
||||||
|
recordBodyDeclaration: printSingle,
|
||||||
|
compactConstructorDeclaration(path, print) {
|
||||||
|
const declaration = [
|
||||||
|
call(path, print, "simpleTypeName"),
|
||||||
|
" ",
|
||||||
|
call(path, print, "constructorBody")
|
||||||
|
];
|
||||||
|
return printWithModifiers(path, print, "constructorModifier", declaration, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function printClassBodyDeclarations(path, print) {
|
||||||
|
var _a;
|
||||||
|
if (!path.node.children.classBodyDeclaration) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const declarations = [];
|
||||||
|
let previousRequiresPadding = path.node.name === "enumBodyDeclarations" ||
|
||||||
|
((_a = path.grandparent) === null || _a === void 0 ? void 0 : _a.name) ===
|
||||||
|
"normalClassDeclaration";
|
||||||
|
each(path, declarationPath => {
|
||||||
|
var _a, _b, _c;
|
||||||
|
const declaration = print(declarationPath);
|
||||||
|
if (declaration === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { node, previous } = declarationPath;
|
||||||
|
const fieldDeclaration = (_b = (_a = node.children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.fieldDeclaration) === null || _b === void 0 ? void 0 : _b[0].children;
|
||||||
|
const currentRequiresPadding = fieldDeclaration
|
||||||
|
? hasDeclarationAnnotations((_c = fieldDeclaration.fieldModifier) !== null && _c !== void 0 ? _c : [])
|
||||||
|
: true;
|
||||||
|
const blankLine = previousRequiresPadding ||
|
||||||
|
(declarations.length > 0 &&
|
||||||
|
(currentRequiresPadding ||
|
||||||
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1));
|
||||||
|
declarations.push(blankLine ? [hardline, declaration] : declaration);
|
||||||
|
previousRequiresPadding = currentRequiresPadding;
|
||||||
|
}, "classBodyDeclaration");
|
||||||
|
return declarations;
|
||||||
|
}
|
||||||
134
frontend/src/common/prettier/plugins/java/printers/expressions.d.ts
vendored
Normal file
134
frontend/src/common/prettier/plugins/java/printers/expressions.d.ts
vendored
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import type { StringTemplateCstNode, TextBlockTemplateCstNode } from "java-parser";
|
||||||
|
import type { AstPath } from "prettier";
|
||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import type { JavaComment } from "../comments.js";
|
||||||
|
import { printSingle, type JavaPrintFn } from "./helpers.js";
|
||||||
|
declare const _default: {
|
||||||
|
expression: typeof printSingle;
|
||||||
|
lambdaExpression(path: AstPath<import("java-parser").LambdaExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, _: import("./helpers.js").JavaParserOptions, args?: unknown): builders.Doc[];
|
||||||
|
lambdaParameters(path: AstPath<import("java-parser").LambdaParametersCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Doc;
|
||||||
|
lambdaParametersWithBraces(path: AstPath<import("java-parser").LambdaParametersWithBracesCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Doc;
|
||||||
|
lambdaParameterList: typeof printSingle;
|
||||||
|
conciseLambdaParameterList(path: AstPath<import("java-parser").ConciseLambdaParameterListCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
normalLambdaParameterList(path: AstPath<import("java-parser").NormalLambdaParameterListCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
normalLambdaParameter: typeof printSingle;
|
||||||
|
regularLambdaParameter(path: AstPath<import("java-parser").RegularLambdaParameterCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
lambdaParameterType: typeof printSingle;
|
||||||
|
conciseLambdaParameter: typeof printSingle;
|
||||||
|
lambdaBody: typeof printSingle;
|
||||||
|
conditionalExpression(path: AstPath<import("java-parser").ConditionalExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
binaryExpression(path: AstPath<import("java-parser").BinaryExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Doc;
|
||||||
|
unaryExpression(path: AstPath<import("java-parser").UnaryExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
unaryExpressionNotPlusMinus(path: AstPath<import("java-parser").UnaryExpressionNotPlusMinusCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
primary(path: AstPath<import("java-parser").PrimaryCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
primaryPrefix: typeof printSingle;
|
||||||
|
primarySuffix(path: AstPath<import("java-parser").PrimarySuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
fqnOrRefType(path: AstPath<import("java-parser").FqnOrRefTypeCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn, _: import("./helpers.js").JavaParserOptions, args: unknown): builders.Doc[];
|
||||||
|
fqnOrRefTypePartFirst(path: AstPath<import("java-parser").FqnOrRefTypePartFirstCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
fqnOrRefTypePartRest(path: AstPath<import("java-parser").FqnOrRefTypePartRestCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
fqnOrRefTypePartCommon(path: AstPath<import("java-parser").FqnOrRefTypePartCommonCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
parenthesisExpression(path: AstPath<import("java-parser").ParenthesisExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "()" | (string | builders.Indent)[];
|
||||||
|
castExpression: typeof printSingle;
|
||||||
|
primitiveCastExpression(path: AstPath<import("java-parser").PrimitiveCastExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
referenceTypeCastExpression(path: AstPath<import("java-parser").ReferenceTypeCastExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
newExpression: typeof printSingle;
|
||||||
|
unqualifiedClassInstanceCreationExpression(path: AstPath<import("java-parser").UnqualifiedClassInstanceCreationExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
classOrInterfaceTypeToInstantiate(path: AstPath<import("java-parser").ClassOrInterfaceTypeToInstantiateCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
typeArgumentsOrDiamond: typeof printSingle;
|
||||||
|
diamond(): string;
|
||||||
|
methodInvocationSuffix(path: AstPath<import("java-parser").MethodInvocationSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | "()";
|
||||||
|
argumentList(path: AstPath<import("java-parser").ArgumentListCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Group | (builders.Indent | builders.Softline)[] | (builders.BreakParent | builders.Group)[];
|
||||||
|
arrayCreationExpression(path: AstPath<import("java-parser").ArrayCreationExpressionCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
arrayCreationExpressionWithoutInitializerSuffix(path: AstPath<import("java-parser").ArrayCreationExpressionWithoutInitializerSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc;
|
||||||
|
arrayCreationWithInitializerSuffix(path: AstPath<import("java-parser").ArrayCreationWithInitializerSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
dimExprs(path: AstPath<import("java-parser").DimExprsCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
dimExpr(path: AstPath<import("java-parser").DimExprCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
classLiteralSuffix(path: AstPath<import("java-parser").ClassLiteralSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
arrayAccessSuffix(path: AstPath<import("java-parser").ArrayAccessSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
methodReferenceSuffix(path: AstPath<import("java-parser").MethodReferenceSuffixCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
templateArgument: typeof printSingle;
|
||||||
|
template: typeof printSingle;
|
||||||
|
stringTemplate(path: AstPath<StringTemplateCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Indent;
|
||||||
|
textBlockTemplate(path: AstPath<TextBlockTemplateCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Indent;
|
||||||
|
embeddedExpression: typeof printSingle;
|
||||||
|
pattern: typeof printSingle;
|
||||||
|
typePattern: typeof printSingle;
|
||||||
|
recordPattern(path: AstPath<import("java-parser").RecordPatternCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
componentPatternList(path: AstPath<import("java-parser").ComponentPatternListCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
componentPattern: typeof printSingle;
|
||||||
|
matchAllPattern: typeof printSingle;
|
||||||
|
guard(path: AstPath<import("java-parser").GuardCstNode & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
@@ -0,0 +1,598 @@
|
|||||||
|
import { builders, utils } from "prettier/doc";
|
||||||
|
import { call, definedKeys, each, findBaseIndent, flatMap, hasLeadingComments, indentInParentheses, isBinaryExpression, isNonTerminal, isTerminal, map, onlyDefinedKey, printDanglingComments, printList, printName, printSingle } from "./helpers.js";
|
||||||
|
const { breakParent, conditionalGroup, group, hardline, ifBreak, indent, indentIfBreak, join, line, lineSuffixBoundary, softline } = builders;
|
||||||
|
const { removeLines, willBreak } = utils;
|
||||||
|
export default {
|
||||||
|
expression: printSingle,
|
||||||
|
lambdaExpression(path, print, _, args = {}) {
|
||||||
|
var _a;
|
||||||
|
const hug = (_a = args.hug) !== null && _a !== void 0 ? _a : false;
|
||||||
|
const parameters = call(path, print, "lambdaParameters");
|
||||||
|
const expression = [hug ? removeLines(parameters) : parameters, " ->"];
|
||||||
|
const lambdaExpression = path.node.children.lambdaBody[0].children.expression;
|
||||||
|
const body = call(path, print, "lambdaBody");
|
||||||
|
if (lambdaExpression) {
|
||||||
|
const suffix = indent([line, body]);
|
||||||
|
expression.push(group(hug ? [suffix, softline] : suffix));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expression.push(" ", body);
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
},
|
||||||
|
lambdaParameters(path, print, options) {
|
||||||
|
const parameters = printSingle(path, print);
|
||||||
|
return !path.node.children.lambdaParametersWithBraces &&
|
||||||
|
options.arrowParens === "always"
|
||||||
|
? ["(", parameters, ")"]
|
||||||
|
: parameters;
|
||||||
|
},
|
||||||
|
lambdaParametersWithBraces(path, print, options) {
|
||||||
|
var _a;
|
||||||
|
const { lambdaParameterList } = path.node.children;
|
||||||
|
if (!lambdaParameterList) {
|
||||||
|
return "()";
|
||||||
|
}
|
||||||
|
const { conciseLambdaParameterList, normalLambdaParameterList } = lambdaParameterList[0].children;
|
||||||
|
const parameterCount = ((_a = conciseLambdaParameterList === null || conciseLambdaParameterList === void 0 ? void 0 : conciseLambdaParameterList[0].children.conciseLambdaParameter) !== null && _a !== void 0 ? _a : normalLambdaParameterList === null || normalLambdaParameterList === void 0 ? void 0 : normalLambdaParameterList[0].children.normalLambdaParameter).length;
|
||||||
|
const parameters = call(path, print, "lambdaParameterList");
|
||||||
|
if (parameterCount > 1) {
|
||||||
|
return indentInParentheses(parameters);
|
||||||
|
}
|
||||||
|
return conciseLambdaParameterList && options.arrowParens === "avoid"
|
||||||
|
? parameters
|
||||||
|
: ["(", parameters, ")"];
|
||||||
|
},
|
||||||
|
lambdaParameterList: printSingle,
|
||||||
|
conciseLambdaParameterList(path, print) {
|
||||||
|
return printList(path, print, "conciseLambdaParameter");
|
||||||
|
},
|
||||||
|
normalLambdaParameterList(path, print) {
|
||||||
|
return printList(path, print, "normalLambdaParameter");
|
||||||
|
},
|
||||||
|
normalLambdaParameter: printSingle,
|
||||||
|
regularLambdaParameter(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "variableModifier"),
|
||||||
|
call(path, print, "lambdaParameterType"),
|
||||||
|
call(path, print, "variableDeclaratorId")
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
lambdaParameterType: printSingle,
|
||||||
|
conciseLambdaParameter: printSingle,
|
||||||
|
lambdaBody: printSingle,
|
||||||
|
conditionalExpression(path, print) {
|
||||||
|
var _a;
|
||||||
|
const binaryExpression = call(path, print, "binaryExpression");
|
||||||
|
if (!path.node.children.QuestionMark) {
|
||||||
|
return binaryExpression;
|
||||||
|
}
|
||||||
|
const expressions = map(path, print, "expression");
|
||||||
|
const contents = indent(join(line, [
|
||||||
|
binaryExpression,
|
||||||
|
["? ", expressions[0]],
|
||||||
|
[": ", expressions[1]]
|
||||||
|
]));
|
||||||
|
const isNestedTernary = ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) ===
|
||||||
|
"conditionalExpression";
|
||||||
|
return isNestedTernary ? contents : group(contents);
|
||||||
|
},
|
||||||
|
binaryExpression(path, print, options) {
|
||||||
|
var _a, _b;
|
||||||
|
const { children } = path.node;
|
||||||
|
const operands = flatMap(path, print, definedKeys(children, [
|
||||||
|
"expression",
|
||||||
|
"pattern",
|
||||||
|
"referenceType",
|
||||||
|
"unaryExpression"
|
||||||
|
]));
|
||||||
|
const operators = flatMap(path, operatorPath => {
|
||||||
|
const { node } = operatorPath;
|
||||||
|
let image;
|
||||||
|
if (isTerminal(node)) {
|
||||||
|
image = node.image;
|
||||||
|
}
|
||||||
|
else if (node.children.Less) {
|
||||||
|
image = "<<";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
image = node.children.Greater.length === 2 ? ">>" : ">>>";
|
||||||
|
}
|
||||||
|
return { image, doc: print(operatorPath) };
|
||||||
|
}, definedKeys(children, [
|
||||||
|
"AssignmentOperator",
|
||||||
|
"BinaryOperator",
|
||||||
|
"Instanceof",
|
||||||
|
"shiftOperator"
|
||||||
|
]));
|
||||||
|
const hasNonAssignmentOperators = (operators.length > 0 && !children.AssignmentOperator) ||
|
||||||
|
(children.expression !== undefined &&
|
||||||
|
isBinaryExpression(children.expression[0]));
|
||||||
|
const isInList = ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) === "elementValue" ||
|
||||||
|
((_b = path.getNode(6)) === null || _b === void 0 ? void 0 : _b.name) === "argumentList";
|
||||||
|
return binary(operands, operators, {
|
||||||
|
hasNonAssignmentOperators,
|
||||||
|
isInList,
|
||||||
|
isRoot: true,
|
||||||
|
operatorPosition: options.experimentalOperatorPosition
|
||||||
|
});
|
||||||
|
},
|
||||||
|
unaryExpression(path, print) {
|
||||||
|
return [
|
||||||
|
...map(path, print, "UnaryPrefixOperator"),
|
||||||
|
call(path, print, "primary"),
|
||||||
|
...map(path, print, "UnarySuffixOperator")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
unaryExpressionNotPlusMinus(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const expression = [];
|
||||||
|
if (children.UnaryPrefixOperatorNotPlusMinus) {
|
||||||
|
expression.push(...map(path, print, "UnaryPrefixOperatorNotPlusMinus"));
|
||||||
|
}
|
||||||
|
expression.push(call(path, print, "primary"));
|
||||||
|
if (children.UnarySuffixOperator) {
|
||||||
|
expression.push(...map(path, print, "UnarySuffixOperator"));
|
||||||
|
}
|
||||||
|
return join(" ", expression);
|
||||||
|
},
|
||||||
|
primary(path, print) {
|
||||||
|
var _a, _b;
|
||||||
|
const { children } = path.node;
|
||||||
|
if (!children.primarySuffix) {
|
||||||
|
return call(path, print, "primaryPrefix");
|
||||||
|
}
|
||||||
|
const methodInvocations = children.primarySuffix
|
||||||
|
.filter(({ children }) => children.methodInvocationSuffix)
|
||||||
|
.map(({ children }) => children.methodInvocationSuffix[0].children);
|
||||||
|
const hasLambdaMethodParameter = methodInvocations.some(({ argumentList }) => argumentList === null || argumentList === void 0 ? void 0 : argumentList[0].children.expression.some(({ children }) => children.lambdaExpression));
|
||||||
|
const prefixIsCallExpression = children.primaryPrefix[0].children.newExpression;
|
||||||
|
const callExpressionCount = methodInvocations.length +
|
||||||
|
(prefixIsCallExpression ? 1 : 0) +
|
||||||
|
children.primarySuffix.filter(({ children }) => children.unqualifiedClassInstanceCreationExpression).length;
|
||||||
|
const fqnOrRefType = (_a = children.primaryPrefix[0].children.fqnOrRefType) === null || _a === void 0 ? void 0 : _a[0].children;
|
||||||
|
const prefixIsMethodInvocation = (fqnOrRefType === null || fqnOrRefType === void 0 ? void 0 : fqnOrRefType.fqnOrRefTypePartRest) !== undefined &&
|
||||||
|
((_b = children.primarySuffix) === null || _b === void 0 ? void 0 : _b[0].children.methodInvocationSuffix) !== undefined;
|
||||||
|
const prefixIsStaticMethodInvocation = prefixIsMethodInvocation && isCapitalizedIdentifier(fqnOrRefType);
|
||||||
|
const prefixIsInstanceMethodInvocation = prefixIsMethodInvocation && !prefixIsStaticMethodInvocation;
|
||||||
|
const mustBreakForCallExpressions = methodInvocations.length > 2 && hasLambdaMethodParameter;
|
||||||
|
const separator = mustBreakForCallExpressions ? hardline : softline;
|
||||||
|
const prefix = [
|
||||||
|
call(path, prefixPath => print(prefixPath, {
|
||||||
|
lastSeparator: prefixIsStaticMethodInvocation ||
|
||||||
|
(prefixIsInstanceMethodInvocation && callExpressionCount === 1)
|
||||||
|
? ""
|
||||||
|
: separator
|
||||||
|
}), "primaryPrefix")
|
||||||
|
];
|
||||||
|
const canBreakForCallExpressions = callExpressionCount > 2 ||
|
||||||
|
(callExpressionCount === 2 && prefixIsInstanceMethodInvocation) ||
|
||||||
|
willBreak(prefix);
|
||||||
|
const suffixes = [];
|
||||||
|
each(path, suffixPath => {
|
||||||
|
const { node, previous } = suffixPath;
|
||||||
|
const suffix = print(suffixPath);
|
||||||
|
if (node.children.Dot) {
|
||||||
|
if ((canBreakForCallExpressions &&
|
||||||
|
((!previous && prefixIsCallExpression) ||
|
||||||
|
(previous === null || previous === void 0 ? void 0 : previous.children.methodInvocationSuffix) ||
|
||||||
|
(previous === null || previous === void 0 ? void 0 : previous.children.unqualifiedClassInstanceCreationExpression))) ||
|
||||||
|
(!node.children.templateArgument && willBreak(suffix))) {
|
||||||
|
suffixes.push(separator);
|
||||||
|
}
|
||||||
|
suffixes.push(suffix);
|
||||||
|
}
|
||||||
|
else if (previous) {
|
||||||
|
suffixes.push(suffix);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prefix.push(prefixIsInstanceMethodInvocation && callExpressionCount >= 2
|
||||||
|
? indent(suffix)
|
||||||
|
: suffix);
|
||||||
|
}
|
||||||
|
}, "primarySuffix");
|
||||||
|
const hasSuffixComments = children.primarySuffix.some(suffix => hasLeadingComments(suffix));
|
||||||
|
return group(canBreakForCallExpressions || hasSuffixComments
|
||||||
|
? [prefix, indent(suffixes)]
|
||||||
|
: [prefix, ...suffixes]);
|
||||||
|
},
|
||||||
|
primaryPrefix: printSingle,
|
||||||
|
primarySuffix(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
if (!children.Dot) {
|
||||||
|
return printSingle(path, print);
|
||||||
|
}
|
||||||
|
const suffix = ["."];
|
||||||
|
if (children.This) {
|
||||||
|
suffix.push("this");
|
||||||
|
}
|
||||||
|
else if (children.Identifier) {
|
||||||
|
if (children.typeArguments) {
|
||||||
|
suffix.push(call(path, print, "typeArguments"));
|
||||||
|
}
|
||||||
|
suffix.push(call(path, print, "Identifier"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const suffixKey = onlyDefinedKey(children, [
|
||||||
|
"templateArgument",
|
||||||
|
"unqualifiedClassInstanceCreationExpression"
|
||||||
|
]);
|
||||||
|
suffix.push(call(path, print, suffixKey));
|
||||||
|
}
|
||||||
|
return suffix;
|
||||||
|
},
|
||||||
|
fqnOrRefType(path, print, _, args) {
|
||||||
|
var _a;
|
||||||
|
const lastSeparator = (_a = args.lastSeparator) !== null && _a !== void 0 ? _a : "";
|
||||||
|
const fqnOrRefType = [
|
||||||
|
call(path, print, "fqnOrRefTypePartFirst"),
|
||||||
|
...map(path, partPath => {
|
||||||
|
const part = print(partPath);
|
||||||
|
return partPath.isLast
|
||||||
|
? [willBreak(part) ? hardline : lastSeparator, part]
|
||||||
|
: part;
|
||||||
|
}, "fqnOrRefTypePartRest")
|
||||||
|
];
|
||||||
|
fqnOrRefType.push(indent(fqnOrRefType.pop()));
|
||||||
|
return path.node.children.dims
|
||||||
|
? [fqnOrRefType, call(path, print, "dims")]
|
||||||
|
: fqnOrRefType;
|
||||||
|
},
|
||||||
|
fqnOrRefTypePartFirst(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "annotation"),
|
||||||
|
call(path, print, "fqnOrRefTypePartCommon")
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
fqnOrRefTypePartRest(path, print) {
|
||||||
|
const common = call(path, print, "fqnOrRefTypePartCommon");
|
||||||
|
const type = path.node.children.typeArguments
|
||||||
|
? [call(path, print, "typeArguments"), common]
|
||||||
|
: common;
|
||||||
|
return [".", ...join(" ", [...map(path, print, "annotation"), type])];
|
||||||
|
},
|
||||||
|
fqnOrRefTypePartCommon(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const keywordKey = onlyDefinedKey(children, ["Identifier", "Super"]);
|
||||||
|
const keyword = call(path, print, keywordKey);
|
||||||
|
return children.typeArguments
|
||||||
|
? [keyword, call(path, print, "typeArguments")]
|
||||||
|
: keyword;
|
||||||
|
},
|
||||||
|
parenthesisExpression(path, print) {
|
||||||
|
var _a;
|
||||||
|
const expression = call(path, print, "expression");
|
||||||
|
const ancestorName = (_a = path.getNode(14)) === null || _a === void 0 ? void 0 : _a.name;
|
||||||
|
const binaryExpression = path.getNode(8);
|
||||||
|
return ancestorName &&
|
||||||
|
["guard", "returnStatement"].includes(ancestorName) &&
|
||||||
|
binaryExpression &&
|
||||||
|
binaryExpression.name === "binaryExpression" &&
|
||||||
|
Object.keys(binaryExpression.children).length === 1
|
||||||
|
? indentInParentheses(expression)
|
||||||
|
: ["(", indent(expression), ")"];
|
||||||
|
},
|
||||||
|
castExpression: printSingle,
|
||||||
|
primitiveCastExpression(path, print) {
|
||||||
|
return [
|
||||||
|
"(",
|
||||||
|
call(path, print, "primitiveType"),
|
||||||
|
") ",
|
||||||
|
call(path, print, "unaryExpression")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
referenceTypeCastExpression(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const type = call(path, print, "referenceType");
|
||||||
|
const cast = children.additionalBound
|
||||||
|
? indentInParentheses(join(line, [type, ...map(path, print, "additionalBound")]))
|
||||||
|
: ["(", type, ")"];
|
||||||
|
const expressionKey = onlyDefinedKey(children, [
|
||||||
|
"lambdaExpression",
|
||||||
|
"unaryExpressionNotPlusMinus"
|
||||||
|
]);
|
||||||
|
return [cast, " ", call(path, print, expressionKey)];
|
||||||
|
},
|
||||||
|
newExpression: printSingle,
|
||||||
|
unqualifiedClassInstanceCreationExpression(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const expression = ["new "];
|
||||||
|
if (children.typeArguments) {
|
||||||
|
expression.push(call(path, print, "typeArguments"));
|
||||||
|
}
|
||||||
|
expression.push(call(path, print, "classOrInterfaceTypeToInstantiate"), children.argumentList
|
||||||
|
? group(["(", call(path, print, "argumentList"), ")"])
|
||||||
|
: "()");
|
||||||
|
if (children.classBody) {
|
||||||
|
expression.push(" ", call(path, print, "classBody"));
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
},
|
||||||
|
classOrInterfaceTypeToInstantiate(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const type = children.annotation
|
||||||
|
? flatMap(path, childPath => [
|
||||||
|
print(childPath),
|
||||||
|
isNonTerminal(childPath.node) ? " " : "."
|
||||||
|
], ["annotation", "Identifier"])
|
||||||
|
: printName(path, print);
|
||||||
|
if (children.typeArgumentsOrDiamond) {
|
||||||
|
type.push(call(path, print, "typeArgumentsOrDiamond"));
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
},
|
||||||
|
typeArgumentsOrDiamond: printSingle,
|
||||||
|
diamond() {
|
||||||
|
return "<>";
|
||||||
|
},
|
||||||
|
methodInvocationSuffix(path, print) {
|
||||||
|
return path.node.children.argumentList
|
||||||
|
? group(["(", call(path, print, "argumentList"), ")"])
|
||||||
|
: indentInParentheses(printDanglingComments(path), { shouldBreak: true });
|
||||||
|
},
|
||||||
|
argumentList(path, print) {
|
||||||
|
var _a, _b, _c, _d;
|
||||||
|
const expressions = path.node.children.expression;
|
||||||
|
const lastExpression = expressions.at(-1);
|
||||||
|
const lastExpressionLambdaBodyExpression = (_b = (_a = lastExpression.children.lambdaExpression) === null || _a === void 0 ? void 0 : _a[0].children.lambdaBody[0].children.expression) === null || _b === void 0 ? void 0 : _b[0].children;
|
||||||
|
const lastExpressionLambdaBodyTernaryExpression = (_c = lastExpressionLambdaBodyExpression === null || lastExpressionLambdaBodyExpression === void 0 ? void 0 : lastExpressionLambdaBodyExpression.conditionalExpression) === null || _c === void 0 ? void 0 : _c[0].children;
|
||||||
|
const isHuggable = !lastExpression.comments &&
|
||||||
|
(!lastExpressionLambdaBodyExpression ||
|
||||||
|
(lastExpressionLambdaBodyTernaryExpression === null || lastExpressionLambdaBodyTernaryExpression === void 0 ? void 0 : lastExpressionLambdaBodyTernaryExpression.QuestionMark) !== undefined ||
|
||||||
|
((_d = lastExpressionLambdaBodyTernaryExpression === null || lastExpressionLambdaBodyTernaryExpression === void 0 ? void 0 : lastExpressionLambdaBodyTernaryExpression.binaryExpression) === null || _d === void 0 ? void 0 : _d[0].children.unaryExpression.length) === 1) &&
|
||||||
|
expressions.findIndex(({ children }) => children.lambdaExpression) ===
|
||||||
|
expressions.length - 1;
|
||||||
|
const args = map(path, print, "expression");
|
||||||
|
const allArgsExpandable = [
|
||||||
|
indent([softline, ...join([",", line], args)]),
|
||||||
|
softline
|
||||||
|
];
|
||||||
|
if (!isHuggable || willBreak(args.at(-1)[0])) {
|
||||||
|
return allArgsExpandable;
|
||||||
|
}
|
||||||
|
const headArgs = args.slice(0, -1);
|
||||||
|
const huggedLastArg = path.call(argPath => print(argPath, { hug: true }), "children", "expression", args.length - 1);
|
||||||
|
const lastArgExpanded = join(", ", [
|
||||||
|
...headArgs,
|
||||||
|
group(huggedLastArg, { shouldBreak: true })
|
||||||
|
]);
|
||||||
|
if (willBreak(huggedLastArg)) {
|
||||||
|
return [
|
||||||
|
breakParent,
|
||||||
|
conditionalGroup([lastArgExpanded, allArgsExpandable])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return conditionalGroup([
|
||||||
|
join(", ", [...headArgs, huggedLastArg]),
|
||||||
|
lastArgExpanded,
|
||||||
|
allArgsExpandable
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
arrayCreationExpression(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const typeKey = onlyDefinedKey(children, [
|
||||||
|
"classOrInterfaceType",
|
||||||
|
"primitiveType"
|
||||||
|
]);
|
||||||
|
const suffixKey = onlyDefinedKey(children, [
|
||||||
|
"arrayCreationExpressionWithoutInitializerSuffix",
|
||||||
|
"arrayCreationWithInitializerSuffix"
|
||||||
|
]);
|
||||||
|
return ["new ", call(path, print, typeKey), call(path, print, suffixKey)];
|
||||||
|
},
|
||||||
|
arrayCreationExpressionWithoutInitializerSuffix(path, print) {
|
||||||
|
const expressions = call(path, print, "dimExprs");
|
||||||
|
return path.node.children.dims
|
||||||
|
? [expressions, call(path, print, "dims")]
|
||||||
|
: expressions;
|
||||||
|
},
|
||||||
|
arrayCreationWithInitializerSuffix(path, print) {
|
||||||
|
return [
|
||||||
|
call(path, print, "dims"),
|
||||||
|
" ",
|
||||||
|
call(path, print, "arrayInitializer")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
dimExprs(path, print) {
|
||||||
|
return map(path, print, "dimExpr");
|
||||||
|
},
|
||||||
|
dimExpr(path, print) {
|
||||||
|
return join(" ", [
|
||||||
|
...map(path, print, "annotation"),
|
||||||
|
["[", call(path, print, "expression"), "]"]
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
classLiteralSuffix(path, print) {
|
||||||
|
const lSquares = map(path, print, "LSquare");
|
||||||
|
const rSquares = map(path, print, "RSquare");
|
||||||
|
return [
|
||||||
|
...lSquares.flatMap((lSquare, index) => [lSquare, rSquares[index]]),
|
||||||
|
".class"
|
||||||
|
];
|
||||||
|
},
|
||||||
|
arrayAccessSuffix(path, print) {
|
||||||
|
return ["[", call(path, print, "expression"), "]"];
|
||||||
|
},
|
||||||
|
methodReferenceSuffix(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
const reference = ["::"];
|
||||||
|
if (children.typeArguments) {
|
||||||
|
reference.push(call(path, print, "typeArguments"));
|
||||||
|
}
|
||||||
|
reference.push(call(path, print, onlyDefinedKey(children, ["Identifier", "New"])));
|
||||||
|
return reference;
|
||||||
|
},
|
||||||
|
templateArgument: printSingle,
|
||||||
|
template: printSingle,
|
||||||
|
stringTemplate(path, print) {
|
||||||
|
return printTemplate(path, print, "StringTemplateBegin", "StringTemplateMid", "StringTemplateEnd");
|
||||||
|
},
|
||||||
|
textBlockTemplate(path, print) {
|
||||||
|
return printTemplate(path, print, "TextBlockTemplateBegin", "TextBlockTemplateMid", "TextBlockTemplateEnd");
|
||||||
|
},
|
||||||
|
embeddedExpression: printSingle,
|
||||||
|
pattern: printSingle,
|
||||||
|
typePattern: printSingle,
|
||||||
|
recordPattern(path, print) {
|
||||||
|
const patterns = path.node.children.componentPatternList
|
||||||
|
? indentInParentheses(call(path, print, "componentPatternList"))
|
||||||
|
: "()";
|
||||||
|
return [call(path, print, "referenceType"), patterns];
|
||||||
|
},
|
||||||
|
componentPatternList(path, print) {
|
||||||
|
return printList(path, print, "componentPattern");
|
||||||
|
},
|
||||||
|
componentPattern: printSingle,
|
||||||
|
matchAllPattern: printSingle,
|
||||||
|
guard(path, print) {
|
||||||
|
var _a;
|
||||||
|
const expression = call(path, print, "expression");
|
||||||
|
const hasParentheses = ((_a = path.node.children.expression[0].children.conditionalExpression) === null || _a === void 0 ? void 0 : _a[0].children.binaryExpression[0].children.unaryExpression[0].children.primary[0].children.primaryPrefix[0].children.parenthesisExpression) !==
|
||||||
|
undefined;
|
||||||
|
return [
|
||||||
|
"when ",
|
||||||
|
hasParentheses
|
||||||
|
? expression
|
||||||
|
: group([
|
||||||
|
ifBreak("("),
|
||||||
|
indent([softline, expression]),
|
||||||
|
softline,
|
||||||
|
ifBreak(")")
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function binary(operands, operators, { hasNonAssignmentOperators = false, isInList = false, isRoot = false, operatorPosition }) {
|
||||||
|
let levelOperator;
|
||||||
|
let levelPrecedence;
|
||||||
|
let level = [];
|
||||||
|
while (operators.length) {
|
||||||
|
const nextOperator = operators[0].image;
|
||||||
|
const nextPrecedence = getOperatorPrecedence(nextOperator);
|
||||||
|
if (levelPrecedence === undefined || nextPrecedence === levelPrecedence) {
|
||||||
|
const { image: operator, doc: operatorDoc } = operators.shift();
|
||||||
|
level.push(operands.shift());
|
||||||
|
if (levelOperator !== undefined &&
|
||||||
|
needsParentheses(levelOperator, operator)) {
|
||||||
|
level = [["(", group(indent(level)), ")"]];
|
||||||
|
}
|
||||||
|
const parts = [" ", operatorDoc, line];
|
||||||
|
if (operatorPosition === "start" && !isAssignmentOperator(operator)) {
|
||||||
|
parts.reverse();
|
||||||
|
}
|
||||||
|
level.push(parts);
|
||||||
|
levelOperator = operator;
|
||||||
|
levelPrecedence = nextPrecedence;
|
||||||
|
}
|
||||||
|
else if (nextPrecedence < levelPrecedence) {
|
||||||
|
if (!isRoot) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
level.push(operands.shift());
|
||||||
|
const content = group(indent(level));
|
||||||
|
operands.unshift(levelOperator !== undefined &&
|
||||||
|
needsParentheses(levelOperator, nextOperator)
|
||||||
|
? ["(", content, ")"]
|
||||||
|
: content);
|
||||||
|
level = [];
|
||||||
|
levelOperator = undefined;
|
||||||
|
levelPrecedence = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const content = binary(operands, operators, { operatorPosition });
|
||||||
|
operands.unshift(levelOperator !== undefined &&
|
||||||
|
needsParentheses(nextOperator, levelOperator)
|
||||||
|
? ["(", indent(content), ")"]
|
||||||
|
: content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
level.push(operands.shift());
|
||||||
|
if (!levelOperator ||
|
||||||
|
(!isInList &&
|
||||||
|
!isAssignmentOperator(levelOperator) &&
|
||||||
|
levelOperator !== "instanceof")) {
|
||||||
|
return group(level);
|
||||||
|
}
|
||||||
|
if (!isRoot || hasNonAssignmentOperators) {
|
||||||
|
return group(indent(level));
|
||||||
|
}
|
||||||
|
const groupId = Symbol("assignment");
|
||||||
|
return group([
|
||||||
|
level[0],
|
||||||
|
group(indent(level[1]), { id: groupId }),
|
||||||
|
indentIfBreak(level[2], { groupId })
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
const precedencesByOperator = new Map([
|
||||||
|
["||"],
|
||||||
|
["&&"],
|
||||||
|
["|"],
|
||||||
|
["^"],
|
||||||
|
["&"],
|
||||||
|
["==", "!="],
|
||||||
|
["<", ">", "<=", ">=", "instanceof"],
|
||||||
|
["<<", ">>", ">>>"],
|
||||||
|
["+", "-"],
|
||||||
|
["*", "/", "%"]
|
||||||
|
].flatMap((operators, index) => operators.map(operator => [operator, index])));
|
||||||
|
function getOperatorPrecedence(operator) {
|
||||||
|
var _a;
|
||||||
|
return (_a = precedencesByOperator.get(operator)) !== null && _a !== void 0 ? _a : -1;
|
||||||
|
}
|
||||||
|
function needsParentheses(operator, parentOperator) {
|
||||||
|
return ((operator === "&&" && parentOperator === "||") ||
|
||||||
|
(["|", "^", "&", "<<", ">>", ">>>"].includes(parentOperator) &&
|
||||||
|
getOperatorPrecedence(operator) >
|
||||||
|
getOperatorPrecedence(parentOperator)) ||
|
||||||
|
[operator, parentOperator].every(o => ["==", "!="].includes(o)) ||
|
||||||
|
[operator, parentOperator].every(o => ["<<", ">>", ">>>"].includes(o)) ||
|
||||||
|
(operator === "*" && parentOperator === "/") ||
|
||||||
|
(operator === "/" && parentOperator === "*") ||
|
||||||
|
(operator === "%" && ["+", "-", "*", "/"].includes(parentOperator)) ||
|
||||||
|
(["*", "/"].includes(operator) && parentOperator === "%"));
|
||||||
|
}
|
||||||
|
const assignmentOperators = new Set([
|
||||||
|
"=",
|
||||||
|
"*=",
|
||||||
|
"/=",
|
||||||
|
"%=",
|
||||||
|
"+=",
|
||||||
|
"-=",
|
||||||
|
"<<=",
|
||||||
|
">>=",
|
||||||
|
">>>=",
|
||||||
|
"&=",
|
||||||
|
"^=",
|
||||||
|
"|="
|
||||||
|
]);
|
||||||
|
function isAssignmentOperator(operator) {
|
||||||
|
return assignmentOperators.has(operator);
|
||||||
|
}
|
||||||
|
function isCapitalizedIdentifier(fqnOrRefType) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
const nextToLastIdentifier = (_c = (_b = [
|
||||||
|
fqnOrRefType.fqnOrRefTypePartFirst[0],
|
||||||
|
...((_a = fqnOrRefType.fqnOrRefTypePartRest) !== null && _a !== void 0 ? _a : [])
|
||||||
|
].at(-2)) === null || _b === void 0 ? void 0 : _b.children.fqnOrRefTypePartCommon[0].children.Identifier) === null || _c === void 0 ? void 0 : _c[0].image;
|
||||||
|
return /^\p{Uppercase_Letter}/u.test(nextToLastIdentifier !== null && nextToLastIdentifier !== void 0 ? nextToLastIdentifier : "");
|
||||||
|
}
|
||||||
|
function printTemplate(path, print, beginKey, midKey, endKey) {
|
||||||
|
const begin = call(path, ({ node }) => node.image, beginKey);
|
||||||
|
const mids = map(path, ({ node }) => node.image, midKey);
|
||||||
|
const end = call(path, ({ node }) => node.image, endKey);
|
||||||
|
const lines = [begin, ...mids, end].join("").split("\n").slice(1);
|
||||||
|
const baseIndent = findBaseIndent(lines);
|
||||||
|
const prefix = "\n" + " ".repeat(baseIndent);
|
||||||
|
const parts = [begin, ...mids, end].map(image => join(hardline, image.split(prefix)));
|
||||||
|
return indent([
|
||||||
|
parts[0],
|
||||||
|
...map(path, (expressionPath, index) => {
|
||||||
|
const expression = group([
|
||||||
|
indent([softline, print(expressionPath), lineSuffixBoundary]),
|
||||||
|
softline
|
||||||
|
]);
|
||||||
|
return index === 0 ? expression : [parts[index], expression];
|
||||||
|
}, "embeddedExpression"),
|
||||||
|
parts.at(-1)
|
||||||
|
]);
|
||||||
|
}
|
||||||
71
frontend/src/common/prettier/plugins/java/printers/helpers.d.ts
vendored
Normal file
71
frontend/src/common/prettier/plugins/java/printers/helpers.d.ts
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import type { AnnotationCstNode, ClassPermitsCstNode, ClassTypeCtx, CstElement, CstNode, ExpressionCstNode, InterfacePermitsCstNode, IToken, StatementCstNode } from "java-parser";
|
||||||
|
import type { AstPath, Doc, ParserOptions } from "prettier";
|
||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import type { JavaComment } from "../comments.js";
|
||||||
|
export declare function onlyDefinedKey<T extends Record<string, any>, K extends Key<T> & string>(obj: T, options?: K[]): K;
|
||||||
|
export declare function definedKeys<T extends Record<string, any>, K extends Key<T> & string>(obj: T, options?: K[]): K[];
|
||||||
|
export declare function printWithModifiers<T extends CstNode, P extends IterProperties<T["children"]>>(path: AstPath<T>, print: JavaPrintFn, modifierChild: P, contents: Doc, noTypeAnnotations?: boolean): builders.Doc[];
|
||||||
|
export declare function hasDeclarationAnnotations(modifiers: ModifierNode[]): boolean;
|
||||||
|
export declare function call<T extends CstNode, U, P extends IterProperties<T["children"]>>(path: AstPath<T>, callback: MapCallback<IndexValue<IndexValue<T, "children">, P>, U>, child: P): U;
|
||||||
|
export declare function each<T extends CstNode, P extends IterProperties<T["children"]>>(path: AstPath<T>, callback: MapCallback<IndexValue<IndexValue<T, "children">, P>, void>, child: P): void;
|
||||||
|
export declare function map<T extends CstNode, U, P extends IterProperties<T["children"]>>(path: AstPath<T>, callback: MapCallback<IndexValue<IndexValue<T, "children">, P>, U>, child: P): U[];
|
||||||
|
export declare function flatMap<T extends CstNode, U, P extends IterProperties<T["children"]>>(path: AstPath<T>, callback: MapCallback<IndexValue<IndexValue<T, "children">, P>, U>, children: P[]): U[];
|
||||||
|
export declare function printSingle(path: AstPath<JavaNonTerminal>, print: JavaPrintFn, _?: JavaParserOptions, args?: unknown): builders.Doc;
|
||||||
|
export declare function lineStartWithComments(node: JavaNonTerminal): number;
|
||||||
|
export declare function lineEndWithComments(node: JavaNonTerminal): number;
|
||||||
|
export declare function printDanglingComments(path: AstPath<JavaNonTerminal>): builders.Doc[];
|
||||||
|
export declare function printComment(node: JavaTerminal): string | builders.Doc[];
|
||||||
|
export declare function hasLeadingComments(node: JavaNode): boolean | undefined;
|
||||||
|
export declare function indentInParentheses(contents: Doc, opts?: {
|
||||||
|
shouldBreak?: boolean;
|
||||||
|
}): builders.Group | "()";
|
||||||
|
export declare function printArrayInitializer<T extends JavaNonTerminal, P extends IterProperties<T["children"]>>(path: AstPath<T>, print: JavaPrintFn, options: JavaParserOptions, child: P): builders.Group | "{}";
|
||||||
|
export declare function printBlock(path: AstPath<JavaNonTerminal>, contents: Doc[]): builders.Group | "{}" | (string | builders.Indent | builders.Hardline)[];
|
||||||
|
export declare function printName(path: AstPath<JavaNonTerminal & {
|
||||||
|
children: {
|
||||||
|
Identifier: IToken[];
|
||||||
|
};
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
export declare function printList<T extends JavaNonTerminal, P extends IterProperties<T["children"]>>(path: AstPath<T>, print: JavaPrintFn, child: P): builders.Doc[];
|
||||||
|
export declare function printClassPermits(path: AstPath<ClassPermitsCstNode | InterfacePermitsCstNode>, print: JavaPrintFn): builders.Group;
|
||||||
|
export declare function printClassType(path: AstPath<JavaNonTerminal & {
|
||||||
|
children: ClassTypeCtx;
|
||||||
|
}>, print: JavaPrintFn): builders.Doc[];
|
||||||
|
export declare function isBinaryExpression(expression: ExpressionCstNode): boolean;
|
||||||
|
export declare function findBaseIndent(lines: string[]): number;
|
||||||
|
export declare function isEmptyStatement(statement: StatementCstNode): boolean;
|
||||||
|
export declare function isNonTerminal(node: CstElement): node is JavaNonTerminal;
|
||||||
|
export declare function isTerminal(node: CstElement): node is IToken;
|
||||||
|
export type JavaNode = CstElement & {
|
||||||
|
comments?: JavaComment[];
|
||||||
|
};
|
||||||
|
export type JavaNonTerminal = Exclude<JavaNode, IToken>;
|
||||||
|
export type JavaTerminal = Exclude<JavaNode, CstNode>;
|
||||||
|
export type JavaNodePrinters = {
|
||||||
|
[T in JavaNonTerminal["name"]]: JavaNodePrinter<T>;
|
||||||
|
};
|
||||||
|
export type JavaNodePrinter<T> = (path: AstPath<Extract<JavaNonTerminal, {
|
||||||
|
name: T;
|
||||||
|
}>>, print: JavaPrintFn, options: JavaParserOptions, args?: unknown) => Doc;
|
||||||
|
export type JavaPrintFn = (path: AstPath<JavaNode>, args?: unknown) => Doc;
|
||||||
|
export type JavaParserOptions = ParserOptions<JavaNode> & {
|
||||||
|
entrypoint?: string;
|
||||||
|
};
|
||||||
|
export type IterProperties<T> = T extends any[] ? IndexProperties<T> : ArrayProperties<T>;
|
||||||
|
type Key<T> = T extends T ? keyof T : never;
|
||||||
|
type ModifierNode = JavaNonTerminal & {
|
||||||
|
children: {
|
||||||
|
annotation?: AnnotationCstNode[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
type IsTuple<T> = T extends [] ? true : T extends [infer First, ...infer Remain] ? IsTuple<Remain> : false;
|
||||||
|
type IndexProperties<T extends {
|
||||||
|
length: number;
|
||||||
|
}> = IsTuple<T> extends true ? Exclude<Partial<T>["length"], T["length"]> : number;
|
||||||
|
type ArrayProperties<T> = {
|
||||||
|
[K in keyof T]: NonNullable<T[K]> extends readonly any[] ? K : never;
|
||||||
|
}[keyof T];
|
||||||
|
type ArrayElement<T> = T extends Array<infer E> ? E : never;
|
||||||
|
type MapCallback<T, U> = (path: AstPath<ArrayElement<T>>, index: number, value: any) => U;
|
||||||
|
type IndexValue<T, P> = T extends any[] ? P extends number ? T[P] : never : P extends keyof T ? T[P] : never;
|
||||||
|
export {};
|
||||||
239
frontend/src/common/prettier/plugins/java/printers/helpers.js
Normal file
239
frontend/src/common/prettier/plugins/java/printers/helpers.js
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
import { builders } from "prettier/doc";
|
||||||
|
import parser from "../parser.js";
|
||||||
|
const { group, hardline, ifBreak, indent, join, line, softline } = builders;
|
||||||
|
export function onlyDefinedKey(obj, options) {
|
||||||
|
const keys = definedKeys(obj, options);
|
||||||
|
if (keys.length === 1) {
|
||||||
|
return keys[0];
|
||||||
|
}
|
||||||
|
throw new Error(keys.length > 1
|
||||||
|
? `More than one defined key found: ${keys}`
|
||||||
|
: "No defined keys found");
|
||||||
|
}
|
||||||
|
export function definedKeys(obj, options) {
|
||||||
|
return (options !== null && options !== void 0 ? options : Object.keys(obj)).filter(key => obj[key] !== undefined);
|
||||||
|
}
|
||||||
|
const indexByModifier = [
|
||||||
|
"public",
|
||||||
|
"protected",
|
||||||
|
"private",
|
||||||
|
"abstract",
|
||||||
|
"default",
|
||||||
|
"static",
|
||||||
|
"final",
|
||||||
|
"transient",
|
||||||
|
"volatile",
|
||||||
|
"synchronized",
|
||||||
|
"native",
|
||||||
|
"sealed",
|
||||||
|
"non-sealed",
|
||||||
|
"strictfp"
|
||||||
|
].reduce((map, name, index) => map.set(name, index), new Map());
|
||||||
|
export function printWithModifiers(path, print, modifierChild, contents, noTypeAnnotations = false) {
|
||||||
|
const declarationAnnotations = [];
|
||||||
|
const otherModifiers = [];
|
||||||
|
const typeAnnotations = [];
|
||||||
|
each(path, modifierPath => {
|
||||||
|
const { children } = modifierPath.node;
|
||||||
|
const modifier = print(modifierPath);
|
||||||
|
if (children.annotation) {
|
||||||
|
(otherModifiers.length ? typeAnnotations : declarationAnnotations).push(modifier);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
otherModifiers.push(modifier);
|
||||||
|
declarationAnnotations.push(...typeAnnotations);
|
||||||
|
typeAnnotations.length = 0;
|
||||||
|
}
|
||||||
|
}, modifierChild);
|
||||||
|
if (noTypeAnnotations) {
|
||||||
|
declarationAnnotations.push(...typeAnnotations);
|
||||||
|
typeAnnotations.length = 0;
|
||||||
|
}
|
||||||
|
otherModifiers.sort((a, b) => indexByModifier.get(a) - indexByModifier.get(b));
|
||||||
|
return join(hardline, [
|
||||||
|
...declarationAnnotations,
|
||||||
|
join(" ", [...otherModifiers, ...typeAnnotations, contents])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
export function hasDeclarationAnnotations(modifiers) {
|
||||||
|
let hasAnnotation = false;
|
||||||
|
let hasNonAnnotation = false;
|
||||||
|
for (const modifier of modifiers) {
|
||||||
|
if (modifier.children.annotation) {
|
||||||
|
hasAnnotation = true;
|
||||||
|
}
|
||||||
|
else if (hasAnnotation) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hasNonAnnotation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasAnnotation && !hasNonAnnotation;
|
||||||
|
}
|
||||||
|
export function call(path, callback, child) {
|
||||||
|
return path.map(callback, "children", child)[0];
|
||||||
|
}
|
||||||
|
export function each(path, callback, child) {
|
||||||
|
if (path.node.children[child]) {
|
||||||
|
path.each(callback, "children", child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function map(path, callback, child) {
|
||||||
|
return path.node.children[child] ? path.map(callback, "children", child) : [];
|
||||||
|
}
|
||||||
|
export function flatMap(path, callback, children) {
|
||||||
|
return children
|
||||||
|
.flatMap(child => map(path, callback, child).map((doc, index) => {
|
||||||
|
const node = path.node.children[child][index];
|
||||||
|
return {
|
||||||
|
doc,
|
||||||
|
startOffset: parser.locStart(node)
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
.sort((a, b) => a.startOffset - b.startOffset)
|
||||||
|
.map(({ doc }) => doc);
|
||||||
|
}
|
||||||
|
export function printSingle(path, print, _, args) {
|
||||||
|
return call(path, childPath => print(childPath, args), onlyDefinedKey(path.node.children));
|
||||||
|
}
|
||||||
|
export function lineStartWithComments(node) {
|
||||||
|
const { comments, location } = node;
|
||||||
|
return comments
|
||||||
|
? Math.min(location.startLine, comments[0].startLine)
|
||||||
|
: location.startLine;
|
||||||
|
}
|
||||||
|
export function lineEndWithComments(node) {
|
||||||
|
const { comments, location } = node;
|
||||||
|
return comments
|
||||||
|
? Math.max(location.endLine, comments.at(-1).endLine)
|
||||||
|
: location.endLine;
|
||||||
|
}
|
||||||
|
export function printDanglingComments(path) {
|
||||||
|
if (!path.node.comments) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const comments = [];
|
||||||
|
path.each(commentPath => {
|
||||||
|
const comment = commentPath.node;
|
||||||
|
if (comment.leading || comment.trailing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
comment.printed = true;
|
||||||
|
comments.push(printComment(comment));
|
||||||
|
}, "comments");
|
||||||
|
return join(hardline, comments);
|
||||||
|
}
|
||||||
|
export function printComment(node) {
|
||||||
|
const { image } = node;
|
||||||
|
const lines = image.split("\n").map(line => line.trim());
|
||||||
|
return lines.length > 1 &&
|
||||||
|
lines[0].startsWith("/*") &&
|
||||||
|
lines.slice(1).every(line => line.startsWith("*")) &&
|
||||||
|
lines.at(-1).endsWith("*/")
|
||||||
|
? join(hardline, lines.map((line, index) => (index === 0 ? line : ` ${line}`)))
|
||||||
|
: image;
|
||||||
|
}
|
||||||
|
export function hasLeadingComments(node) {
|
||||||
|
var _a;
|
||||||
|
return (_a = node.comments) === null || _a === void 0 ? void 0 : _a.some(({ leading }) => leading);
|
||||||
|
}
|
||||||
|
export function indentInParentheses(contents, opts) {
|
||||||
|
return !Array.isArray(contents) || contents.length
|
||||||
|
? group(["(", indent([softline, contents]), softline, ")"], opts)
|
||||||
|
: "()";
|
||||||
|
}
|
||||||
|
export function printArrayInitializer(path, print, options, child) {
|
||||||
|
const list = [];
|
||||||
|
if (child && child in path.node.children) {
|
||||||
|
list.push(call(path, print, child));
|
||||||
|
if (options.trailingComma !== "none") {
|
||||||
|
list.push(ifBreak(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.push(...printDanglingComments(path));
|
||||||
|
return list.length ? group(["{", indent([line, ...list]), line, "}"]) : "{}";
|
||||||
|
}
|
||||||
|
export function printBlock(path, contents) {
|
||||||
|
if (!contents.length) {
|
||||||
|
const danglingComments = printDanglingComments(path);
|
||||||
|
return danglingComments.length
|
||||||
|
? ["{", indent([hardline, ...danglingComments]), hardline, "}"]
|
||||||
|
: "{}";
|
||||||
|
}
|
||||||
|
return group([
|
||||||
|
"{",
|
||||||
|
indent([hardline, ...join(hardline, contents)]),
|
||||||
|
hardline,
|
||||||
|
"}"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
export function printName(path, print) {
|
||||||
|
return join(".", map(path, print, "Identifier"));
|
||||||
|
}
|
||||||
|
export function printList(path, print, child) {
|
||||||
|
return join([",", line], map(path, print, child));
|
||||||
|
}
|
||||||
|
export function printClassPermits(path, print) {
|
||||||
|
return group([
|
||||||
|
"permits",
|
||||||
|
indent([line, group(printList(path, print, "typeName"))])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
export function printClassType(path, print) {
|
||||||
|
const { children } = path.node;
|
||||||
|
return definedKeys(children, ["annotation", "Identifier", "typeArguments"])
|
||||||
|
.flatMap(child => children[child].map((node, index) => ({
|
||||||
|
child,
|
||||||
|
index,
|
||||||
|
startOffset: parser.locStart(node)
|
||||||
|
})))
|
||||||
|
.sort((a, b) => a.startOffset - b.startOffset)
|
||||||
|
.flatMap(({ child, index: childIndex }, index, array) => {
|
||||||
|
const node = children[child][childIndex];
|
||||||
|
const next = array.at(index + 1);
|
||||||
|
const nextNode = next && children[next.child][next.index];
|
||||||
|
const docs = [path.call(print, "children", child, childIndex)];
|
||||||
|
if (nextNode) {
|
||||||
|
if (isNonTerminal(node)) {
|
||||||
|
docs.push(node.name === "annotation" ? " " : ".");
|
||||||
|
}
|
||||||
|
else if (isTerminal(nextNode) || nextNode.name === "annotation") {
|
||||||
|
docs.push(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return docs;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function isBinaryExpression(expression) {
|
||||||
|
var _a;
|
||||||
|
const conditionalExpression = (_a = expression.children.conditionalExpression) === null || _a === void 0 ? void 0 : _a[0].children;
|
||||||
|
if (!conditionalExpression) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const isTernary = conditionalExpression.QuestionMark !== undefined;
|
||||||
|
if (isTernary) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const hasNonAssignmentOperators = Object.values(conditionalExpression.binaryExpression[0].children).some(child => {
|
||||||
|
var _a;
|
||||||
|
return isTerminal(child[0]) &&
|
||||||
|
!((_a = child[0].tokenType.CATEGORIES) === null || _a === void 0 ? void 0 : _a.some(category => category.name === "AssignmentOperator"));
|
||||||
|
});
|
||||||
|
return hasNonAssignmentOperators;
|
||||||
|
}
|
||||||
|
export function findBaseIndent(lines) {
|
||||||
|
return lines.length
|
||||||
|
? Math.min(...lines.map(line => line.search(/\S/)).filter(indent => indent >= 0))
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
export function isEmptyStatement(statement) {
|
||||||
|
var _a;
|
||||||
|
return (((_a = statement.children.statementWithoutTrailingSubstatement) === null || _a === void 0 ? void 0 : _a[0].children.emptyStatement) !== undefined);
|
||||||
|
}
|
||||||
|
export function isNonTerminal(node) {
|
||||||
|
return !isTerminal(node);
|
||||||
|
}
|
||||||
|
export function isTerminal(node) {
|
||||||
|
return "tokenType" in node;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user