├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── README_CN.md
├── bin
├── aarch64-linux
│ ├── jcf
│ └── pasls
├── jcfsettings.cfg
├── win32
│ ├── jcf.exe
│ └── pasls.exe
├── x86_64-darwin
│ ├── jcf
│ └── pasls
└── x86_64-linux
│ ├── jcf
│ └── pasls
├── images
├── doc
│ ├── code-snippets.gif
│ ├── documentsymbol.gif
│ ├── format.gif
│ ├── fpctoolkit.gif
│ └── quickfix.gif
├── icon-link.svg
├── logo.png
└── pascal-project.png
├── package.json
├── package.nls.json
├── package.nls.zh-CN.json
├── pascal-configuration.json
├── snippets
└── pascal.json
├── src
├── commands.ts
├── common
│ ├── configuration.ts
│ ├── escape.ts
│ └── util.ts
├── extension.ts
├── formatter.ts
├── languageServer
│ ├── client.ts
│ ├── codeaction.ts
│ └── options.ts
└── providers
│ ├── project.ts
│ └── task.ts
├── syntaxes
└── fpc.tmLanguage
└── tsconfig.json
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: Publish FpcToolKit
4 |
5 | # Controls when the workflow will run
6 | on:
7 | release:
8 | types:
9 | - published
10 |
11 | # Allows you to run this workflow manually from the Actions tab
12 | workflow_dispatch:
13 |
14 | jobs:
15 | release:
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 | - uses: actions/setup-node@v1
21 | with:
22 | node-version: 14
23 | registry-url: https://registry.npmjs.org/
24 |
25 | - name: Install the dependencies
26 | run: npm i
27 |
28 | - name: Install vsce
29 | run: npm i -g vsce
30 |
31 | - name: Install esbuild
32 | run: npm i -g esbuild
33 |
34 | - name: Build with esbuild
35 | run: esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node
36 |
37 | #
38 | # Package and Upload Extension
39 | #
40 | # NOTE:
41 | # The "vscode:prepublish" script in package.json will be executed to compile the extension
42 | # prior to packaging.
43 | #
44 | - name: Package Extension into .vsix file
45 | id: asset
46 | shell: bash
47 | run: >
48 | vsce package;
49 | echo ::set-output name=vsix_path::$(ls *.vsix)
50 |
51 | - name: Upload .vsix file to Github as release asset
52 | uses: actions/upload-release-asset@v1
53 | env:
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 | with:
56 | upload_url: ${{ github.event.release.upload_url }}
57 | asset_path: ${{ steps.asset.outputs.vsix_path }}
58 | asset_name: ${{ steps.asset.outputs.vsix_path }}
59 | asset_content_type: application/zip
60 |
61 |
62 | - name: Publish
63 | run: vsce publish -p ${{ secrets.VSCE_PAT }}
64 |
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | out
3 | *.vsix
4 | *.lock
5 | package-lock.json
6 | *.mov
7 | .DS_Store
8 | req.txt
9 | media
10 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "runtimeExecutable": "${execPath}",
13 | "args": [
14 | "--extensionDevelopmentPath=${workspaceFolder}"
15 | ],
16 | "outFiles": [
17 | "${workspaceFolder}/out/**/*.js",
18 | ],
19 | "preLaunchTask": "${defaultBuildTask}"
20 | },
21 | {
22 | "name": "Extension Tests",
23 | "type": "extensionHost",
24 | "request": "launch",
25 | "runtimeExecutable": "${execPath}",
26 | "args": [
27 | "--extensionDevelopmentPath=${workspaceFolder}",
28 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
29 | ],
30 | "outFiles": [
31 | "${workspaceFolder}/out/test/**/*.js"
32 | ],
33 | "preLaunchTask": "${defaultBuildTask}"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 |
4 | "files.exclude": {
5 | "out": false // set this to true to hide the "out" folder with the compiled JS files
6 | },
7 | "search.exclude": {
8 | "out": true // set this to false to include "out" folder in search results
9 | },
10 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
11 | "typescript.tsc.autoDetect": "off"
12 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "group": "build",
10 | "problemMatcher": [],
11 | "label": "npm: watch",
12 | "detail": "tsc -watch -p ./"
13 | },
14 | {
15 | "type": "npm",
16 | "script": "compile",
17 | "group": "build",
18 | "problemMatcher": [],
19 | "label": "npm: compile",
20 | "detail": "tsc -p ./"
21 | },
22 | {
23 | "type": "npm",
24 | "script": "esbuild",
25 | "group": {
26 | "kind": "build",
27 | "isDefault": true
28 | },
29 | "problemMatcher": [],
30 | "label": "npm: esbuild",
31 | "detail": "npm run -S esbuild-base -- --sourcemap"
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .gitignore
3 | media
4 | node_modules
5 | src
6 | .github
7 | **/tsconfig.json
8 | **/.eslintrc.json
9 | **/*.map
10 | **/*.ts
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [Unreleased]
2 | - Using lazarus project files
3 |
4 | ## [1.1.9] - 2022-12-17
5 | ## add:
6 | - optimize clean up and build
7 | ## fixed:
8 | - can't rename symbol on version 1.1.8
9 |
10 | ## [1.1.8] - 2022-12-16
11 | ## add:
12 | - add error handle for client to avoid crashing
13 | - change maximumCompletions default to 50
14 |
15 | ## [1.1.6] - 2022-12-06
16 | ## add:
17 | - add build events
18 |
19 | ## [1.1.5] - 2022-11-23
20 | ## fixed:
21 | - can't start language server on linux
22 |
23 | ## [1.1.4] - 2022-10-15
24 | ## fixed:
25 | - quick fix not worked
26 |
27 | ## [1.1.3] - 2022-10-14
28 | ### add:
29 | - code format
30 | - quick fix for [5025] Local variable "xxx" not used
31 | - document symbols navigation
32 | - remove ununsed unit
33 | ### fixed:
34 | - Enhance the stability of the program pasls
35 |
36 | ## [1.1.0]
37 | - pascal language server
38 | - code snippets
39 | - auto completion
40 | - gotoDeclaration, gotoDefinition
41 | - references
42 | - documentHighlight
43 | - i18n support
44 |
45 | ## [1.0.4] - 2020-10-14
46 | ### fixed:
47 | - Throw exception when parsing non-fpc type tasks
48 |
49 | ## [1.0.3] - 2020-10-13
50 | ### fixed:
51 | - error with "fs-extra module not found"
52 |
53 |
54 | ## [1.0.2] - 2020-10-12
55 | ### add:
56 | - Clean menu
57 |
58 |
59 | ## [1.0.1] - 2020-09-17
60 | ### fixed:
61 | - Fixes for issues that don't work under Linux
62 |
63 | ## [1.0.0] - 2020-09-17
64 | - Initial release
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation
2 |
3 | All rights reserved.
4 |
5 | MIT License
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FreePascal Toolkit
2 | `FreePascal Toolkit` is a VSCode extension for developing FreePascal applications.
3 |
4 | 
5 |
6 | [中文文档](README_CN.md)
7 | ## Requirements
8 |
9 | - Install [Lazarus](https://www.lazarus-ide.org/) or [FreePascal](https://www.freepascal.org/download.var) on your system.
10 |
11 | - The extendsion will auto search the path of fpc. If it's not be found, please set the system PATH environment variable, or set `fpctoolkit.env.PP` in vscode's user setting.
12 |
13 | - Install [GDB Debugger - Beyond](https://marketplace.visualstudio.com/items?itemName=coolchyni.beyond-debug) to debug your freepascal program .
14 |
15 |
16 | ## Features
17 | - build freepascal program
18 | - Build
19 | - Rebuild
20 | - Clear
21 | - explorer build tasks
22 | - Customize build tasks
23 | - Inherted from other task
24 | - code snippets
25 | - A lot of snippets for code quick edit.
26 | * class
27 | * if-else
28 | * begin-end
29 | * ...
30 | - auto completion
31 |
32 | 
33 |
34 | - gotoDeclaration, gotoDefinition
35 | - Use `ctrl+up`,`ctrl+down` to jump between declaration and implementation.
36 | - class and function references
37 |
38 | 
39 |
40 | - documentHighlight
41 | - High light for source code
42 | - Identify the compilation conditions for the definition. `{$IFDEF} {ELSE} {$ENDIF}`
43 |
44 | - code format with [jcf cli](https://github.com/coolchyni/jcf-cli)
45 |
46 | 
47 |
48 | - Format source code
49 | - Use `jcfsettings.cfg` as config. Will use lazarus's config if it installed.
50 | - quick fix
51 | - Quick fix for `(5025) Local variable "xxx" not used`
52 |
53 | 
54 |
55 | - auto rename symbols
56 | - Rename function,procedure,variable and it's reference.
57 | - code complete
58 | - Use `ctrl+shift+c` auto implement procedure .
59 | - code actions
60 | - remove unused units
61 | ## Pascal Language Server
62 |
63 | from [pascal-language-server](https://github.com/coolchyni/pascal-language-server)
64 |
65 | An [LSP](https://microsoft.github.io/language-server-protocol/) server
66 | implementation for Pascal variants that are supported by [Free
67 | Pascal](https://www.freepascal.org/), including Object Pascal. It uses
68 | [CodeTools](https://wiki.lazarus.freepascal.org/Codetools) from
69 | Lazarus as backend.
70 |
71 | ## Freepascal Task Settings
72 |
73 | You can add freepascal compile tasks by editing `task.json` in your .vscode folder.
74 |
75 | The task's type is `fpc`. It contains the following configuration items.
76 |
77 | ### Task settings
78 | Field | type | Description |
79 | ------ | ----- | :-------------
80 | file | string|main program file. .lpr or .dpr
81 | type | string|always be `fpc`
82 | cwd | string|current path. Use wrokspace root if null.
83 | cleanExt|string|file extensions for clean file in unitOutputDir. use * for clear all file. default:(.o,.ppu)
84 | buildOption|object|build options
85 | inherited|string| inherit from other task
86 |
87 | ### buildEvent
88 | Field | type | Description |
89 | -------| ---- |:---------------
90 | before_build | string[] | Run commands before build
91 | after_build_success | string[]| Run commands after build success.
92 | after_build_failure | string []| Run commands after build failure.
93 |
94 |
95 | ### buildOptions
96 | Field | type | Description |
97 | -------| ---- |:---------------
98 | targetOS | string | Target OS (-T). eg. `linux` `win64`
99 | targetCPU |string| Target cpu family (-P). eg. `x86_64` `i386`
100 | customOptions|string []| Any compile options for fpc.
101 | libPath|string[]|Searchpath for libraries.(-Fl)
102 | outputFile| string| Target file name.(-o)
103 | unitOutputDir| string|Unit output directory.(-FU)
104 | optimizationLevel| number|Optimization levels (-O)
105 | searchPath| string[]|Searchpath for units and other system dependent things.(-Fu)
106 | syntaxMode| string|Syntax Mode (-M)
107 | forceRebuild| boolean|Re-compile all used units, even if the unit sources didn’t change since the last compilation.(-B)
108 | msgIgnore|number[]|Is a list of messages numbers which should not be shown.(-vmxxx)
109 |
110 | example:
111 | ~~~json
112 | {
113 | "version": "2.0.0",
114 | "tasks": [
115 | {
116 | "label": "debug",
117 | "file": "main.lpr",
118 | "type": "fpc",
119 | "buildOption": {
120 | "unitOutputDir": "./out",
121 | "customOptions": [
122 | "-dDEBUG",
123 | "-gw2"
124 | ]
125 | }
126 | }
127 | ]
128 | }
129 | ~~~
130 |
131 | # Thanks
132 | ## HighLight
133 |
134 | Syntaxes from https://github.com/maresmar/ST-Pascal
135 |
136 | ## Format
137 |
138 | Clone and modified from https://github.com/git-bee/jcf-cli
139 |
140 | ## Pascal-language-server
141 |
142 | Clone and modified from
143 | https://github.com/genericptr/pascal-language-server
144 | https://github.com/arjanadriaanse/pascal-language-server
145 |
146 | # Release Notes
147 |
148 | [view changelog](CHANGELOG.md)
149 |
150 |
151 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # FreePascal Toolkit
2 | `FreePascal Toolkit` 是一个用于开发FreePascal程序的 VSCode 应用扩展.
3 |
4 | 
5 |
6 | [English Document](README.md)
7 | ## 准备条件
8 |
9 | - 安装 [Lazarus](https://www.lazarus-ide.org/) 或 [FreePascal](https://www.freepascal.org/download.var) .
10 | - 默认会自动搜索FPC路径,如果找不到,请设置FPC的路径为系统搜索路径,或者在插件里设置 `fpctoolkit.env.PP = FPC程序全路径`.
11 |
12 | - 安装并使用 [GDB Debugger - Beyond](https://marketplace.visualstudio.com/items?itemName=coolchyni.beyond-debug) 进行程序调试
13 |
14 | ## 功能列表
15 | - 编译Free Pascal 程序
16 | - 构建项目
17 | - 清理和构建
18 | - 清理
19 |
20 | - 可视化任务管理
21 | - 支持自定义任务
22 | - 支持从其他任务继承
23 | - 快速代码模版
24 | - 包含非常多的代码模版,用于快速输入代码.
25 | * class
26 | * if-else
27 | * begin-end
28 | * ...
29 | - 智能代码补全,支持函数,过程,类,变量,关键字...
30 |
31 | 
32 |
33 | - 代码快速导航
34 | - 使用 `ctrl+up`,`ctrl+down` 在函数声明和函数体之间快速跳转.
35 | - 快速访问类和函数定义
36 |
37 | 
38 |
39 | - 语法高亮显示
40 | - 源代码高亮
41 | - 能根据编译条件,将`{$IFDEF} {ELSE} {$ENDIF}`之间的无效代码半透明.
42 | - 代码格式化
43 |
44 | - 使用[jcf cli](https://github.com/coolchyni/jcf-cli)格式化源代码
45 | - 使用 `jcfsettings.cfg` 作为配置文件。如果你已经安装了lazarus,本插件将自动使用其配置文件.
46 |
47 | 
48 |
49 | - 快速修复
50 | - 快速修复警告: `(5025) Local variable "xxx" not used`
51 |
52 | 
53 |
54 | - 重命名函数,类,或变量名
55 | - 重命名将会自动更新其相关引用.
56 | - 代码自动完成
57 | - 使用 `ctrl+shift+c` 自动实现函数体 .
58 | - 源代码操作
59 | - 支持删除无用的单元声明
60 |
61 | ## Pascal Language Server
62 |
63 | [pascal-language-server](https://github.com/coolchyni/pascal-language-server)是一个[Free Pascal](https://www.freepascal.org/)实现的[LSP](https://microsoft.github.io/language-server-protocol/) 服务端程序。使用[Lazarus](https://www.lazarus-ide.org/)的[CodeTools](https://wiki.lazarus.freepascal.org/Codetools)作为后台。
64 |
65 | ## 任务设置
66 |
67 | 你可以在.vscode目录下编辑 `task.json` 文件来修改任务选项目。
68 |
69 | 任务类型为 `fpc`. 包含以下可用的配置项:
70 |
71 | ### Task 选项
72 | 字段 | 类型 | 描述 |
73 | ------ | ----- | :-------------
74 | file | string|Free Pascal 项目文件. (.lpr,.dpr)
75 | type | string|必须是 `fpc`
76 | cwd | string|当前工作目录. 如果不设置默认使用vscode工作目录.
77 | cleanExt|string|指定执行清理项目时需要清除的文件名后缀. 输入* 表示清除所有文件. 默认(.o,.ppu,.lfm,.a,.or,.res)
78 | buildOption|object|build 选项
79 | inherited|string| 被继承的任务名
80 |
81 | ### buildEvent
82 | 字段 | 类型 | 描述 |
83 | -------| ---- |:---------------
84 | before_build | string[] | 编译前执行的命令
85 | after_build_success | string[]| 编译成功后执行的命令
86 | after_build_failure | string []|编译失败后执行的命令
87 |
88 | ### buildOptions
89 | 字段 | 类型 | 描述 |
90 | -------| ---- |:---------------
91 | targetOS | string | 目标操作系统 (-T). eg. `linux` `win64`
92 | targetCPU |string| 目标CPU族 (-P). eg. `x86_64` `i386`
93 | customOptions|string []| 自定义编译选项.
94 | libPath|string[]|库搜索路径.(-Fl)
95 | outputFile| string| 目标文件名称.(-o)
96 | unitOutputDir| string|单元文件输出路径.(-FU)
97 | optimizationLevel| number|代码优化级别 (-O)
98 | searchPath| string[]|单元文件搜索路径.(-Fu)
99 | syntaxMode| string|语法模式 (-M {$mode})
100 | forceRebuild| boolean|强制更新所有单元文件并编译.(-B)
101 | msgIgnore|number[]|指定编译时哪些消息不需要显示.(-vmxxx)
102 |
103 | 配置示例:
104 | ~~~ json
105 | {
106 | "version": "2.0.0",
107 | "tasks": [
108 | {
109 | "label": "debug",
110 | "file": "main.lpr",
111 | "type": "fpc",
112 | "buildOption": {
113 | "unitOutputDir": "./out",
114 | "customOptions": [
115 | "-dDEBUG",
116 | "-gw2"
117 | ]
118 | }
119 | }
120 | ]
121 | }
122 | ~~~
123 |
124 | # 致谢
125 | ## 语法高亮
126 |
127 | 语法文件来自于 https://github.com/maresmar/ST-Pascal
128 |
129 | ## 格式化
130 |
131 | 修改自 https://github.com/git-bee/jcf-cli
132 |
133 | ## Pascal-language-server
134 |
135 | 修改自
136 | https://github.com/genericptr/pascal-language-server
137 | https://github.com/arjanadriaanse/pascal-language-server
138 |
139 | # 发布说明
140 |
141 | [查看更新记录](CHANGELOG.md)
142 |
143 |
144 |
--------------------------------------------------------------------------------
/bin/aarch64-linux/jcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/aarch64-linux/jcf
--------------------------------------------------------------------------------
/bin/aarch64-linux/pasls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/aarch64-linux/pasls
--------------------------------------------------------------------------------
/bin/jcfsettings.cfg:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2.44
4 | 44832.7011022801
5 | format settings for use with Lazarus
6 | True
7 |
8 | False
9 | 1
10 | True
11 | True
12 | True
13 | True
14 |
15 |
16 | 0
17 | True
18 | False
19 | Sender
20 | dpr,lpr,pas,pp
21 |
22 |
23 | 2
24 | 0
25 | False
26 | False
27 | 2
28 | True
29 | False
30 | True
31 | True
32 | True
33 | True
34 | False
35 | True
36 | False
37 | False
38 |
39 |
40 | True
41 | False
42 | 2
43 | 2
44 | True
45 | False
46 | 0
47 | 0
48 | 0
49 | 0
50 | 0
51 | 0
52 | 0
53 | 0
54 | 0
55 | 2
56 | True
57 | 0
58 | False
59 | False
60 | False
61 | False
62 | False
63 | False
64 |
65 |
66 | 2
67 | 90
68 | 1
69 | True
70 | True
71 | False
72 | False
73 | True
74 | True
75 | True
76 | True
77 | True
78 | True
79 | True
80 | 1
81 | 0
82 |
83 | 1
84 | 1
85 | 1
86 | 0
87 | 0
88 | 0
89 | 1
90 | 0
91 | 1
92 | 0
93 | 1
94 | 1
95 | 0
96 | 1
97 | 0
98 | True
99 | 4
100 | 1
101 | 1
102 |
103 |
104 | True
105 | True
106 |
107 |
108 | True
109 | 1
110 | 1
111 | 1
112 | 1
113 | 1
114 |
115 |
116 | True
117 |
118 |
119 |
120 | True
121 | ActivePage,AnsiCompareStr,AnsiCompareText,AnsiUpperCase,AsBoolean,AsDateTime,AsFloat,AsInteger,Assign,AsString,AsVariant,BeginDrag,Buttons,Caption,Checked,Classes,ClassName,Clear,Close,Components,Controls,Count,Create,Data,Dec,Delete,Destroy,Dialogs,Enabled,EndDrag,EOF,Exception,Execute,False,FieldByName,First,Forms,Free,FreeAndNil,GetFirstChild,Graphics,Height,idAbort,idCancel,idIgnore,IDispatch,idNo,idOk,idRetry,idYes,Inc,Initialize,IntToStr,ItemIndex,IUnknown,Lines,Math,MaxValue,mbAbort,mbAll,mbCancel,mbHelp,mbIgnore,mbNo,mbOK,mbRetry,mbYes,mbYesToAll,Messages,MinValue,mnNoToAll,mrAbort,mrAll,mrCancel,mrIgnore,mrNo,mrNone,mrNoToAll,mrOk,mrRetry,mrYes,mrYesToAll,mtConfirmation,mtCustom,mtError,mtInformation,mtWarning,Name,Next,Open,Ord,ParamStr,PChar,Perform,ProcessMessages,Read,ReadOnly,RecordCount,Register,Release,Result,Sender,SetFocus,Show,ShowMessage,Source,StdCtrls,StrToInt,SysUtils,TAutoObject,TButton,TComponent,TDataModule,Text,TForm,TFrame,TList,TNotifyEvent,TObject,TObjectList,TPageControl,TPersistent,True,TStringList,TStrings,TTabSheet,Unassigned,Value,Visible,WideString,Width,Windows,Write
122 |
123 |
124 | True
125 | False,Name,nil,PChar,read,ReadOnly,True,WideString,write
126 |
127 |
128 | True
129 | ActnColorMaps,ActnCtrls,ActnList,ActnMan,ActnMenus,ActnPopup,ActnRes,ADOConst,ADODB,ADOInt,AppEvnts,AxCtrls,BandActn,bdeconst,bdemts,Buttons,CheckLst,Classes,Clipbrd.pas,CmAdmCtl,ComCtrls,ComStrs,Consts,Controls,CtlConsts,CtlPanel,CustomizeDlg,DataBkr,DB,DBActns,dbcgrids,DBClient,DBClientActnRes,DBClientActns,DBCommon,DBConnAdmin,DBConsts,DBCtrls,DbExcept,DBGrids,DBLocal,DBLocalI,DBLogDlg,dblookup,DBOleCtl,DBPWDlg,DBTables,DBXpress,DdeMan,Dialogs,DrTable,DSIntf,ExtActns,ExtCtrls,ExtDlgs,FileCtrl,FMTBcd,Forms,Graphics,GraphUtil,Grids,HTTPIntr,IB,IBBlob,IBCustomDataSet,IBDatabase,IBDatabaseInfo,IBDCLConst,IBErrorCodes,IBEvents,IBExternals,IBExtract,IBGeneratorEditor,IBHeader,IBIntf,IBQuery,IBRestoreEditor,IBSecurityEditor,IBServiceEditor,IBSQL,IBSQLMonitor,IBStoredProc,IBTable,IBUpdateSQL,IBUtils,IBXConst,ImgList,Jcl8087,JclAbstractContainers,JclAlgorithms,JclAnsiStrings,JclAppInst,JclArrayLists,JclArraySets,JclBase,JclBinaryTrees,JclBorlandTools,JclCIL,JclCLR,JclCOM,JclComplex,JclCompression,JclConsole,JclContainerIntf,JclCounter,JclDateTime,JclDebug,JclDotNet,JclEDI,JclEDISEF,JclEDITranslators,JclEDIXML,JclEDI_ANSIX12,JclEDI_ANSIX12_Ext,JclEDI_UNEDIFACT,JclEDI_UNEDIFACT_Ext,JclExprEval,JclFileUtils,JclFont,JclGraphics,JclGraphUtils,JclHashMaps,JclHashSets,JclHookExcept,JclIniFiles,JclLANMan,JclLinkedLists,JclLocales,JclLogic,JclMapi,JclMath,JclMetadata,JclMIDI,JclMime,JclMiscel,JclMsdosSys,JclMultimedia,JclNTFS,JclPCRE,JclPeImage,JclPrint,JclQGraphics,JclQGraphUtils,JclQueues,JclRegistry,JclResources,JclRTTI,JclSchedule,JclSecurity,JclShell,JclSimpleXml,JclStacks,JclStatistics,JclStreams,JclStrHashMap,JclStringLists,JclStrings,JclStructStorage,JclSvcCtrl,JclSynch,JclSysInfo,JclSysUtils,JclTask,JclTD32,JclUnicode,JclUnitConv,JclUnitVersioning,JclUnitVersioningProviders,JclValidation,JclVectors,JclWideFormat,JclWideStrings,JclWin32,JclWin32Ex,JclWinMIDI,ListActns,Mask,MConnect,Menus,Midas,MidasCon,MidConst,MPlayer,MtsRdm,Mxconsts,ObjBrkr,OleAuto,OleConst,OleCtnrs,OleCtrls,OleDB,OleServer,Outline,Printers,Provider,recerror,ScktCnst,ScktComp,ScktMain,SConnect,ShadowWnd,SimpleDS,SMINTF,SqlConst,SqlExpr,SqlTimSt,StdActnMenus,StdActns,StdCtrls,StdStyleActnCtrls,SvcMgr,SysUtils,TabNotBk,Tabs,TConnect,Themes,ToolWin,ValEdit,VDBConsts,WinHelpViewer,XPActnCtrls,XPMan,XPStyleActnCtrls
130 |
131 |
132 | 0
133 | 1
134 | True
135 | True
136 | 7
137 | True
138 | 15
139 |
140 |
141 | True
142 | MSWINDOWS
143 |
144 |
145 |
146 | False
147 | False
148 | False
149 | False
150 | False
151 | False
152 | False
153 | 2
154 | 60
155 | 5
156 | 5
157 | 0
158 |
159 |
160 | False
161 |
162 |
163 |
164 | False
165 | False
166 | False
167 | False
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | 1
176 | True
177 | False
178 | False
179 | False
180 | False
181 | False
182 | 0
183 | False
184 |
185 |
186 |
--------------------------------------------------------------------------------
/bin/win32/jcf.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/win32/jcf.exe
--------------------------------------------------------------------------------
/bin/win32/pasls.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/win32/pasls.exe
--------------------------------------------------------------------------------
/bin/x86_64-darwin/jcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/x86_64-darwin/jcf
--------------------------------------------------------------------------------
/bin/x86_64-darwin/pasls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/x86_64-darwin/pasls
--------------------------------------------------------------------------------
/bin/x86_64-linux/jcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/x86_64-linux/jcf
--------------------------------------------------------------------------------
/bin/x86_64-linux/pasls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/bin/x86_64-linux/pasls
--------------------------------------------------------------------------------
/images/doc/code-snippets.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/doc/code-snippets.gif
--------------------------------------------------------------------------------
/images/doc/documentsymbol.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/doc/documentsymbol.gif
--------------------------------------------------------------------------------
/images/doc/format.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/doc/format.gif
--------------------------------------------------------------------------------
/images/doc/fpctoolkit.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/doc/fpctoolkit.gif
--------------------------------------------------------------------------------
/images/doc/quickfix.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/doc/quickfix.gif
--------------------------------------------------------------------------------
/images/icon-link.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/logo.png
--------------------------------------------------------------------------------
/images/pascal-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coolchyni/fpctoolkit/bd55429c1e47770fa67c5ce4baa768daf1c1f80b/images/pascal-project.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fpctoolkit",
3 | "displayName": "FreePascal Toolkit",
4 | "description": "Free pascal compile and build.",
5 | "version": "1.1.9",
6 | "engines": {
7 | "vscode": "^1.44.0"
8 | },
9 | "icon": "images/logo.png",
10 | "categories": [
11 | "Programming Languages"
12 | ],
13 | "publisher": "coolchyni",
14 | "author": "coolchyni ",
15 | "license": "MIT",
16 | "keywords": [
17 | "free",
18 | "pascal",
19 | "freepascal",
20 | "fpc",
21 | "lazarus",
22 | "objectpascal",
23 | "delphi"
24 | ],
25 | "private": true,
26 | "repository": {
27 | "type": "git",
28 | "url": "https://github.com/coolchyni/fpctoolkit.git"
29 | },
30 | "bugs": {
31 | "url": "https://github.com/coolchyni/fpctoolkit/issues"
32 | },
33 | "activationEvents": [
34 | "onView:FpcProjectExplorer",
35 | "onLanguage:objectpascal"
36 | ],
37 | "main": "./out/extension.js",
38 | "contributes": {
39 | "languages": [
40 | {
41 | "id": "objectpascal",
42 | "aliases": [
43 | "Object-Pascal"
44 | ],
45 | "extensions": [
46 | ".pas",
47 | ".pp",
48 | ".lpr",
49 | ".inc",
50 | ".p",
51 | ".dfm",
52 | ".fmx",
53 | ".dpr",
54 | ".dpk",
55 | ".lfm",
56 | ".dpr",
57 | ".lpr"
58 | ],
59 | "configuration": "./pascal-configuration.json"
60 | },
61 | {
62 | "id": "pascal",
63 | "configuration": "./pascal-configuration.json"
64 | }
65 | ],
66 | "grammars": [
67 | {
68 | "language": "objectpascal",
69 | "scopeName": "source.pascal",
70 | "path": "./syntaxes/fpc.tmLanguage"
71 | },
72 | {
73 | "language": "pascal",
74 | "scopeName": "source.pascal",
75 | "path": "./syntaxes/fpc.tmLanguage"
76 | }
77 | ],
78 | "snippets": [
79 | {
80 | "language": "objectpascal",
81 | "path": "./snippets/pascal.json"
82 | },
83 | {
84 | "language": "pascal",
85 | "path": "./snippets/pascal.json"
86 | }
87 | ],
88 | "commands": [
89 | {
90 | "command": "fpctoolkit.project.newproject",
91 | "title": "Create new Fpc Project"
92 | },
93 | {
94 | "command": "fpctoolkit.project.build",
95 | "title": "%project.build%",
96 | "icon": "$(play)"
97 | },
98 | {
99 | "command": "fpctoolkit.project.rebuild",
100 | "title": "%project.rebuild%"
101 | },
102 | {
103 | "command": "fpctoolkit.project.clean",
104 | "title": "%project.clear%"
105 | },
106 | {
107 | "command": "fpctoolkit.project.opensetting",
108 | "title": "%project.open%"
109 | },
110 | {
111 | "command": "fpctoolkit.project.add",
112 | "title": "%project.newconfig%"
113 | },
114 | {
115 | "command": "fpctoolkit.project.setdefault",
116 | "title": "%project.setdefault%"
117 | }
118 | ],
119 | "keybindings": [
120 | {
121 | "key": "ctrl+shift+down",
122 | "command": "editor.action.goToImplementation",
123 | "when": "editorHasImplementationProvider && editorTextFocus && !isInEmbeddedEditor"
124 | },
125 | {
126 | "key": "ctrl+shift+up",
127 | "command": "editor.action.goToImplementation",
128 | "when": "editorHasImplementationProvider && editorTextFocus && !isInEmbeddedEditor"
129 | },
130 | {
131 | "key": "ctrl+shift+c",
132 | "command": "fpctoolkit.code.complete",
133 | "when": "editorTextFocus && !isInEmbeddedEditor"
134 | }
135 | ],
136 | "taskDefinitions": [
137 | {
138 | "type": "fpc",
139 | "required": [
140 | "file"
141 | ],
142 | "properties": {
143 | "file": {
144 | "type": "string",
145 | "description": "%task.file%"
146 | },
147 | "cwd": {
148 | "type": "string",
149 | "description": "%task.cwd%"
150 | },
151 | "cleanExt": {
152 | "type": "string",
153 | "description": "%task.cleanExt%"
154 | },
155 | "inherited":{
156 | "type":"string",
157 | "description": "%task.inherited%"
158 | },
159 | "windows": {
160 | "type": "object",
161 | "properties": {
162 | "customOptions": {
163 | "type": "array",
164 | "items": {
165 | "type": "string"
166 | },
167 | "description": "%task.buildOption.customOptions%"
168 | }
169 | }
170 | },
171 | "linux": {
172 | "type": "object",
173 | "properties": {
174 | "customOptions": {
175 | "type": "array",
176 | "items": {
177 | "type": "string"
178 | },
179 | "description": "%task.buildOption.customOptions%"
180 | }
181 | }
182 | },
183 | "osx": {
184 | "type": "object",
185 | "properties": {
186 | "customOptions": {
187 | "type": "array",
188 | "items": {
189 | "type": "string"
190 | },
191 | "description": "%task.buildOption.customOptions%"
192 | }
193 | }
194 | },
195 | "buildEvent":{
196 | "type":"object",
197 | "description": "Event to run command." ,
198 | "properties": {
199 | "before_build":{
200 | "type":"array",
201 | "description": "Run commands before build.",
202 | "items": {
203 | "type":"string"
204 | }
205 | },
206 | "after_build_success":{
207 | "type":"array",
208 | "description": "Run commands after build success.",
209 | "items": {
210 | "type":"string"
211 | }
212 | },
213 | "after_build_failure":{
214 | "type":"array",
215 | "description": "Run commands after build failure.",
216 | "items": {
217 | "type":"string"
218 | }
219 | }
220 | }
221 | },
222 | "buildOption": {
223 | "type": "object",
224 | "properties": {
225 | "targetOS": {
226 | "type": "string",
227 | "description": "%task.buildOption.targetOS%",
228 | "examples": [
229 | "linux",
230 | "win32",
231 | "win64",
232 | "Darwin"
233 | ]
234 | },
235 | "targetCPU": {
236 | "type": "string",
237 | "description": "%task.buildOption.targetCPU%",
238 | "examples": [
239 | "x86_64",
240 | "aarch64",
241 | "i386"
242 | ]
243 | },
244 | "searchPath": {
245 | "type": "array",
246 | "description": "%task.buildOption.searchPath%",
247 | "items": {
248 | "type": "string"
249 | }
250 | },
251 | "libPath": {
252 | "type": "array",
253 | "description": "%task.buildOption.libPath%",
254 | "items": {
255 | "type": "string"
256 | }
257 | },
258 | "unitOutputDir": {
259 | "type": "string",
260 | "description": "%task.buildOption.unitOutputDir%"
261 | },
262 | "outputFile": {
263 | "type": "string",
264 | "description": "%task.buildOption.outputFile%"
265 | },
266 | "syntaxMode": {
267 | "type": "string",
268 | "description": "%task.buildOption.syntaxMode%",
269 | "default": "ObjFPC",
270 | "examples": [
271 | "fpc",
272 | "Delphi",
273 | "DelphiUnicode",
274 | "ObjFPC"
275 | ]
276 | },
277 | "optimizationLevel": {
278 | "type": "number",
279 | "description": "%task.buildOption.optimizationLevel%",
280 | "enum": [
281 | 0,
282 | 1,
283 | 2,
284 | 3,
285 | 4
286 | ]
287 | },
288 | "forceRebuild":{
289 | "type":"boolean",
290 | "description": "%task.buildOption.forceRebuild%",
291 | "default":false
292 | },
293 | "msgIgnore":{
294 | "type":"array",
295 | "items": {
296 | "type":"number"
297 | },
298 | "description": "%task.buildOption.msgIgnore%"
299 | },
300 | "customOptions": {
301 | "type": "array",
302 | "items": {
303 | "type": "string"
304 | },
305 | "description": "%task.buildOption.customOptions%"
306 | }
307 | }
308 | }
309 | }
310 | }
311 | ],
312 | "menus": {
313 | "view/item/context": [
314 | {
315 | "command": "fpctoolkit.project.build",
316 | "when": "view == FpcProjectExplorer && viewItem==fpcbuild",
317 | "group": "fpcproject@1"
318 | },
319 | {
320 | "command": "fpctoolkit.project.rebuild",
321 | "when": "view == FpcProjectExplorer && viewItem==fpcbuild",
322 | "group": "fpcproject@2"
323 | },
324 | {
325 | "command": "fpctoolkit.project.clean",
326 | "when": "view == FpcProjectExplorer && viewItem==fpcbuild",
327 | "group": "fpcproject@3"
328 | },
329 | {
330 | "command": "fpctoolkit.project.setdefault",
331 | "when": "view == FpcProjectExplorer && viewItem==fpcbuild",
332 | "group": "fpcprojectcfg@4"
333 | },
334 | {
335 | "command": "fpctoolkit.project.add",
336 | "when": "view == FpcProjectExplorer && viewItem==fpcproject",
337 | "group": "fpcproject@0"
338 | },
339 | {
340 | "command": "fpctoolkit.project.build",
341 | "when": "view == FpcProjectExplorer && viewItem==fpcbuild",
342 | "group": "inline"
343 | }
344 |
345 | ]
346 | },
347 | "configuration": [
348 | {
349 | "title": "FpcToolkit",
350 | "properties": {
351 | "fpctoolkit.searchPath": {
352 | "type": "array",
353 | "description": "%config.searchPath%",
354 | "items": {
355 | "type": "string"
356 | }
357 | },
358 | "fpctoolkit.libPath": {
359 | "type": "array",
360 | "description": "%config.libPath%",
361 | "items": {
362 | "type": "string"
363 | }
364 | },
365 | "fpctoolkit.customOptions": {
366 | "type": "array",
367 | "items": {
368 | "type": "string"
369 | },
370 | "description": "%config.customOptions%"
371 | },
372 | "fpctoolkit.env.PP": {
373 | "type": "string",
374 | "markdownDescription": "%config.env.PP%"
375 | },
376 | "fpctoolkit.env.FPCDIR": {
377 | "type": "string",
378 | "markdownDescription": "%config.env.FPCDIR%"
379 | },
380 | "fpctoolkit.env.LAZARUSDIR": {
381 | "type": "string",
382 | "markdownDescription": "%config.env.LAZARUSDIR%"
383 | },
384 | "fpctoolkit.env.FPCTARGET": {
385 | "type": "string",
386 | "markdownDescription": "%config.env.FPCTARGET%",
387 | "examples": [
388 | "linux",
389 | "win32",
390 | "win64",
391 | "Darwin"
392 | ]
393 | },
394 | "fpctoolkit.env.FPCTARGETCPU": {
395 | "type": "string",
396 | "markdownDescription": "%config.env.FPCTARGETCPU%",
397 | "examples": [
398 | "x86_64",
399 | "aarch64",
400 | "i386"
401 | ]
402 | },
403 | "fpctoolkit.format.tabsize": {
404 | "type": "number",
405 | "default": 2,
406 | "markdownDescription": "%config.format.tabsize%"
407 | },
408 | "fpctoolkit.pasls.path": {
409 | "type": "string",
410 | "description": "%config.pasls.path%"
411 | },
412 | "fpctoolkit.format.enabled": {
413 | "type": "boolean",
414 | "default":"true",
415 | "description": "%config.format.enabled%"
416 | },
417 | "fpctoolkit.format.cfgpath": {
418 | "type": "string",
419 | "description": "%config.format.cfgpath%"
420 | }
421 |
422 | }
423 | },
424 | {
425 | "title": "FpcToolkit LanguageServer",
426 | "properties": {
427 | "fpctoolkit.lsp.trace.server": {
428 | "scope": "window",
429 | "type": "string",
430 | "enum": [
431 | "off",
432 | "messages",
433 | "verbose"
434 | ],
435 | "default": "off",
436 | "description": "%lsp.trace.server%"
437 | },
438 | "fpctoolkit.lsp.initializationOptions.program": {
439 | "type": "string",
440 | "description": "%lsp.initializationOptions.program%"
441 | },
442 | "fpctoolkit.lsp.initializationOptions.overloadPolicy": {
443 | "type": "number",
444 | "scope": "application",
445 | "default": 3,
446 | "enum": [
447 | 1,
448 | 2,
449 | 3
450 | ],
451 | "enumDescriptions": [
452 | "%lsp.enum.overloadPolicy_1%",
453 | "%lsp.enum.overloadPolicy_2%",
454 | "%lsp.enum.overloadPolicy_3%"
455 | ],
456 | "description": "%lsp.initializationOptions.overloadPolicy%"
457 | },
458 | "fpctoolkit.lsp.initializationOptions.maximumCompletions": {
459 | "type": "number",
460 | "default": 50,
461 | "markdownDescription": "%lsp.initializationOptions.maximumCompletions%"
462 | },
463 | "fpctoolkit.lsp.initializationOptions.insertCompletionsAsSnippets": {
464 | "type": "boolean",
465 | "default": false,
466 | "description": "%lsp.initializationOptions.insertCompletionsAsSnippets%"
467 | },
468 | "fpctoolkit.lsp.initializationOptions.insertCompletionProcedureBrackets": {
469 | "type": "boolean",
470 | "default": false,
471 | "description": "%lsp.initializationOptions.insertCompletionProcedureBrackets%"
472 | },
473 | "fpctoolkit.lsp.initializationOptions.includeWorkspaceFoldersAsUnitPaths": {
474 | "type": "boolean",
475 | "default": true,
476 | "description": "%lsp.initializationOptions.includeWorkspaceFoldersAsUnitPaths%"
477 | },
478 | "fpctoolkit.lsp.initializationOptions.includeWorkspaceFoldersAsIncludePaths": {
479 | "type": "boolean",
480 | "default": true,
481 | "description": "%lsp.initializationOptions.includeWorkspaceFoldersAsIncludePaths%"
482 | },
483 | "fpctoolkit.lsp.initializationOptions.checkSyntax": {
484 | "type": "boolean",
485 | "scope": "application",
486 | "default": false,
487 | "description": "%lsp.initializationOptions.checkSyntax%"
488 | },
489 | "fpctoolkit.lsp.initializationOptions.publishDiagnostics": {
490 | "type": "boolean",
491 | "scope": "application",
492 | "default": false,
493 | "description": "%lsp.initializationOptions.publishDiagnostics%"
494 | },
495 | "fpctoolkit.lsp.initializationOptions.workspaceSymbols": {
496 | "type": "boolean",
497 | "default": false,
498 | "description": "%lsp.initializationOptions.workspaceSymbols%"
499 | },
500 | "fpctoolkit.lsp.initializationOptions.documentSymbols": {
501 | "type": "boolean",
502 | "default": true,
503 | "description": "%lsp.initializationOptions.documentSymbols%"
504 | },
505 | "fpctoolkit.lsp.initializationOptions.minimalisticCompletions": {
506 | "type": "boolean",
507 | "default": false,
508 | "description": "%lsp.initializationOptions.minimalisticCompletions%"
509 | },
510 | "fpctoolkit.lsp.initializationOptions.showSyntaxErrors": {
511 | "type": "boolean",
512 | "default": true,
513 | "markdownDescription": "%lsp.initializationOptions.showSyntaxErrors%"
514 | }
515 | }
516 | }
517 | ],
518 | "views": {
519 | "explorer": [
520 | {
521 | "id": "FpcProjectExplorer",
522 | "name": "FPC Projects"
523 | }
524 | ]
525 | },
526 | "viewsWelcome": [
527 | {
528 | "view": "FpcProjectExplorer",
529 | "contents": "%views.welcome%",
530 | "when": "!workspace.workspaceFolders"
531 | }
532 | ],
533 | "problemMatchers": [
534 | {
535 | "name": "fpc",
536 | "owner": "external",
537 | "pattern": [
538 | {
539 | "regexp": "Compiling ([^\\s].*(p|pp|pas|lpr|dpr|inc))$",
540 | "file": 1
541 | },
542 | {
543 | "regexp": "^([\\w]+\\.(p|pp|pas|lpr|dpr|inc))\\((\\d+)\\,(\\d+)\\)\\s(Fatal|Error|Warning|Note):(.*)",
544 | "line": 3,
545 | "column": 4,
546 | "severity": 5,
547 | "message": 6,
548 | "loop": true
549 | }
550 | ]
551 | }
552 | ]
553 | },
554 | "scripts": {
555 | "compile": "tsc -p ./",
556 | "lint": "eslint src --ext ts",
557 | "watch": "tsc -watch -p ./",
558 | "package": "vsce package",
559 | "publish": "vsce publish",
560 | "vscode:prepublish": "npm run -S esbuild-base -- --minify",
561 | "esbuild-base": "rimraf out && esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node",
562 | "esbuild": "npm run -S esbuild-base -- --sourcemap",
563 | "esbuild-watch": "npm run -S esbuild-base -- --sourcemap --watch"
564 | },
565 | "dependencies": {
566 | "@types/fs-extra": "9.0.2",
567 | "fs-extra": "9.0.1",
568 | "tsc": "^2.0.4",
569 | "vscode-languageclient": "^8.0.1",
570 | "vscode-nls": "^3.2.5"
571 | },
572 | "devDependencies": {
573 | "@types/glob": "^7.2.0",
574 | "@types/mocha": "^7.0.2",
575 | "@types/node": "^13.13.52",
576 | "@types/vscode": "^1.44.0",
577 | "@typescript-eslint/eslint-plugin": "^5.28.0",
578 | "@typescript-eslint/parser": "^5.28.0",
579 | "esbuild": "^0.14.23",
580 | "eslint": "^8.10.0",
581 | "glob": "^7.2.0",
582 | "mocha": "^9.2.1",
583 | "rimraf": "^3.0.2",
584 | "typescript": "^3.9.10"
585 | },
586 | "homepage": "https://github.com/coolchyni/fpctoolkit#readme"
587 | }
588 |
--------------------------------------------------------------------------------
/package.nls.json:
--------------------------------------------------------------------------------
1 | {
2 | "project.build": "Build",
3 | "project.rebuild": "Clean up and build",
4 | "project.clear": "Clean up",
5 | "project.open": "Open",
6 | "project.newconfig": "New Build Config",
7 | "project.setdefault": "Set As Default",
8 | "task.file": "The project file of FPC. (.lpr,.dpr)",
9 | "task.cwd": "Current path. Use wrokspace root if null.",
10 | "task.cleanExt": "file extensions for clean file in unitOutputDir. use * for clear all file. default:(.o,.ppu,.lfm,.a,.or,.res)",
11 | "task.buildOption.targetOS": "Target OS (-T)",
12 | "task.buildOption.targetCPU": "Target cpu family (-P)",
13 | "task.buildOption.searchPath": "Searchpath for units and other system dependent things.(-Fu)",
14 | "task.buildOption.libPath": "Searchpath for libraries.(-Fl)",
15 | "task.buildOption.unitOutputDir": "Unit output directory.(-FU)",
16 | "task.buildOption.outputFile": "Target file name.(-o)",
17 | "task.buildOption.syntaxMode": "Syntax Mode (-M,{$mode})",
18 | "task.buildOption.optimizationLevel": "Optimization levels (-O)",
19 | "task.buildOption.customOptions": "Custom compile options for fpc.",
20 | "task.buildOption.forceRebuild": "Re-compile all used units, even if the unit sources didn’t change since the last compilation.(-B)",
21 | "task.buildOption.msgIgnore": "Is a list of messages numbers which should not be shown.(-vmxxx)",
22 | "task.inherited":"Task name inheried from.",
23 | "config.searchPath": "Searchpath for units.(-Fu)",
24 | "config.libPath": "Searchpath for libraries.(-Fl)",
25 | "config.customOptions": "Custom compile options for fpc.",
26 | "config.env.PP": "Path to compiler (i.e. `/usr/bin/fpc`, `/usr/bin/ppc386`)",
27 | "config.env.FPCDIR": "Path to FPC sources such as `/usr/local/share/fpcsrc`",
28 | "config.env.LAZARUSDIR": "Path to Lazarus sources as `/usr/local/share/lazsrc`",
29 | "config.env.FPCTARGET": "Target platform (`win32`,`win64`, `linux`, `darwin`)",
30 | "config.env.FPCTARGETCPU": "Target CPU such as `x86_64`",
31 | "config.pasls.path": "Pascal Language Server(pasls) file path.",
32 | "lsp.trace.server": "Traces the communication between VS Code and the language server.",
33 | "lsp.initializationOptions.program": "Path to the main program file for resolving references (if not available the path of the current document will be used)",
34 | "lsp.initializationOptions.overloadPolicy": "Policy which determines how overloaded document symbols are displayed",
35 | "lsp.initializationOptions.maximumCompletions": "Maximum number of completion items to be returned. If the threshold is reached then `CompletionList.isIncomplete = true`",
36 | "lsp.initializationOptions.insertCompletionsAsSnippets": "Procedure completions with parameters are inserted as snippets",
37 | "lsp.initializationOptions.insertCompletionProcedureBrackets": "Procedure completions with parameters (non-snippet) insert empty brackets (and insert as snippet)",
38 | "lsp.initializationOptions.includeWorkspaceFoldersAsUnitPaths": "Workspaces folders will be added to unit paths (i.e. -Fu)",
39 | "lsp.initializationOptions.includeWorkspaceFoldersAsIncludePaths": "Workspaces folders will be added to include paths (i.e. -Fi)",
40 | "lsp.initializationOptions.checkSyntax": "Syntax will be checked when file opens or saves",
41 | "lsp.initializationOptions.publishDiagnostics": "Syntax errors will be published as diagnostics",
42 | "lsp.initializationOptions.workspaceSymbols": "Enable workspace symbols",
43 | "lsp.initializationOptions.documentSymbols": "Enable document symbols",
44 | "lsp.initializationOptions.minimalisticCompletions": "Completions contain a minimal amount of extra information",
45 | "lsp.initializationOptions.showSyntaxErrors": "Syntax errors as shown in the UI with ‘window/showMessage’",
46 | "lsp.enum.overloadPolicy_1": "Duplicate function names appear in the list",
47 | "lsp.enum.overloadPolicy_2": "After the original definition ignore others",
48 | "lsp.enum.overloadPolicy_3": "Add a suffix which denotes the overload count",
49 |
50 | "views.welcome":"No fpc projects found.\n[Create New Project](command:fpctoolkit.project.newproject)",
51 |
52 | "config.format.tabsize": "Table space size.",
53 | "config.format.enabled": "Enable jedi formatter.",
54 | "config.format.cfgpath": "The path of jcfsettings.cfg."
55 |
56 | }
--------------------------------------------------------------------------------
/package.nls.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "project.build": "构建项目",
3 | "project.rebuild": "清理和构建",
4 | "project.clear": "清理项目",
5 | "project.open": "打开",
6 | "project.newconfig": "创建新的配置",
7 | "project.setdefault": "设置为默认任务",
8 | "task.file": "Free Pascal 项目文件. (.lpr,.dpr)",
9 | "task.cwd": "当前工作目录. 如果不设置默认使用vscode工作目录.",
10 | "task.cleanExt": "指定执行清理项目时需要清除的文件名后缀. 输入* 表示清除所有文件. 默认(.o,.ppu,.lfm,.a,.or,.res)",
11 | "task.buildOption.targetOS": "目标操作系统 (-T)",
12 | "task.buildOption.targetCPU": "目标CPU族 (-P)",
13 | "task.buildOption.searchPath": "单元文件搜索路径.(-Fu)",
14 | "task.buildOption.libPath": "库搜索路径.(-Fl)",
15 | "task.buildOption.unitOutputDir": "单元文件输出路径.(-FU)",
16 | "task.buildOption.outputFile": "目标文件名称.(-o)",
17 | "task.buildOption.syntaxMode": "语法模式 (-M,{$mode})",
18 | "task.buildOption.optimizationLevel": "代码优化级别 (-O)",
19 | "task.buildOption.customOptions": "自定义编译选项.",
20 | "task.buildOption.forceRebuild": "强制更新所有单元文件并编译.(-B)",
21 | "task.buildOption.msgIgnore":"指定编译时哪些消息不需要显示.可以指定多个error,warn,note编号。(-vmxxx)",
22 | "task.inherited":"继承任务的名称.",
23 | "config.searchPath": "单元文件搜索路径.(-Fu)",
24 | "config.libPath": "库搜索路径.(-Fl)",
25 | "config.customOptions": "自定义选项.",
26 | "config.env.PP": "编译器位置 (i.e. `/usr/bin/fpc`, `/usr/bin/ppc386`)",
27 | "config.env.FPCDIR": "Free Pascal 源代码位置 如:`/usr/local/share/fpcsrc`",
28 | "config.env.LAZARUSDIR": "Lazarus 源代码位置 如:`/usr/local/share/lazsrc`",
29 | "config.env.FPCTARGET": "目标操作系统 如: (`win32`,`win64`, `linux`, `darwin`)",
30 | "config.env.FPCTARGETCPU": "目标CPU族 如: `x86_64`",
31 | "config.pasls.path": "Pascal Language Server(pasls) 文件位置.",
32 | "lsp.trace.server": "跟踪 VS Code 和 pascal language server之间的通讯信息.",
33 | "lsp.initializationOptions.program": "主程序文件.如果未指定,则使用当前文件.",
34 | "lsp.initializationOptions.overloadPolicy": "指定重复的函数或定义如何显示",
35 | "lsp.initializationOptions.maximumCompletions": "自动代码提示显示的最大数量",
36 | "lsp.initializationOptions.insertCompletionsAsSnippets": "函数或过程参数自动变成模版插入",
37 | "lsp.initializationOptions.insertCompletionProcedureBrackets": "有参数的过程或函数插入时自动忽略参数",
38 | "lsp.initializationOptions.includeWorkspaceFoldersAsUnitPaths": "将当前工作目录添加到单元文件搜索目录(i.e. -Fu)",
39 | "lsp.initializationOptions.includeWorkspaceFoldersAsIncludePaths": "将当前工作目录添加到 include 目录 (i.e. -Fi)",
40 | "lsp.initializationOptions.checkSyntax": "文件打开和保存时进行语法检查",
41 | "lsp.initializationOptions.publishDiagnostics": "语法错误作为诊断信息显示",
42 | "lsp.initializationOptions.workspaceSymbols": "允许显示工作目录的类,函数,过程...",
43 | "lsp.initializationOptions.documentSymbols": "允许显示当前文档的类,函数,过程...",
44 | "lsp.initializationOptions.minimalisticCompletions": "自动代码提示包含最少的信息",
45 | "lsp.initializationOptions.showSyntaxErrors": "弹窗显示语法错误提示 ‘window/showMessage’",
46 | "lsp.enum.overloadPolicy_1": "显示多个名称",
47 | "lsp.enum.overloadPolicy_2": "只显示第一个",
48 | "lsp.enum.overloadPolicy_3": "名称前添加编号",
49 |
50 | "views.welcome":"没有发现工程文件.\n[创建新项目](command:fpctoolkit.project.newproject)",
51 | "config.format.tabsize": "制表符(tab)转空格数.",
52 | "config.format.enabled": "启用源码格式化(使用Jedi).",
53 | "config.format.cfgpath": "格式化配置文件路径(jcfsettings.cfg)."
54 | }
--------------------------------------------------------------------------------
/pascal-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "//",
4 | "blockComment": [ "{", "}" ]
5 | },
6 | "brackets": [
7 | ["{", "}"],
8 | ["[", "]"],
9 | ["(", ")"]
10 | ],
11 | "autoClosingPairs": [
12 | ["{", "}"],
13 | ["[", "]"],
14 | ["(", ")"],
15 | ["<", ">"],
16 | ["'", "'"]
17 | ],
18 | "surroundingPairs": [
19 | ["{", "}"],
20 | ["[", "]"],
21 | ["(", ")"],
22 | ["<", ">"],
23 | ["'", "'"]
24 | ],
25 | "folding": {
26 | "markers": {
27 | "start": "^\\s*\\{\\$REGION(\\s\\'.*\\')?\\}",
28 | "end": "^\\s*\\{\\$ENDREGION\\}"
29 | }
30 | }
31 |
32 |
33 |
34 | }
--------------------------------------------------------------------------------
/snippets/pascal.json:
--------------------------------------------------------------------------------
1 | {
2 | "array const":{
3 | "prefix":"arrayc",
4 | "body":[
5 | "array[${1:0}..${2:1}] of ${3:type} = ($4,$0);"
6 | ],
7 | "description":"array declaration(const)"
8 | },
9 | "array var":{
10 | "prefix":"array",
11 | "body":[
12 | "array[${1:0}..${2:1}] of ${0:type};"
13 | ],
14 | "description":"array declaration(var)"
15 | },
16 | "begin end": {
17 | "prefix": "begin",
18 | "body": [
19 | "begin",
20 | "\t$0",
21 | "end;"
22 | ],
23 | "description": "Begin end"
24 | },
25 | "case end": {
26 | "prefix": "case",
27 | "body": [
28 | "case $1 of",
29 | "\t$0",
30 | "end;"
31 | ],
32 | "description": "case end"
33 | },
34 | "class (no parts)": {
35 | "prefix": "classd",
36 | "body": [
37 | "T$1 = class(${2:ancestor})",
38 | "\t$3",
39 | "end;"
40 | ],
41 | "description": "class (no parts)"
42 | },
43 | "class (with Create/Destroy)": {
44 | "prefix": "classc",
45 | "body": [
46 | "T${1:ClassName} = class(T${2:ancestor})",
47 | "private",
48 | "\t$0",
49 | "protected",
50 | "\t",
51 | "public",
52 | "\tconstructor Create; override;",
53 | "\tdestructor Destroy; override;",
54 | "published",
55 | "\t",
56 | "end;"
57 | ],
58 | "description": "class (with Create/Destroy)"
59 | },
60 | "constructor Create": {
61 | "prefix": "Create",
62 | "body": [
63 | "constructor Create(); ${1:override;}"
64 | ],
65 | "description": "constructor descendant"
66 | },
67 | "destructor Destroy": {
68 | "prefix": "Destroy",
69 | "body": [
70 | "destructor Destroy; override;$0"
71 | ],
72 | "description": "destructor"
73 | },
74 | "Create object with finally": {
75 | "prefix": "CreateF",
76 | "body": [
77 | "${1:ObjectName} := ${2:TObject}.Create($3);",
78 | "try",
79 | " $2",
80 | "finally",
81 | " ${1:ObjectName}.Free;",
82 | "end;"
83 | ],
84 | "description": "Create an object and free it in finally block"
85 | },
86 | "else end": {
87 | "prefix": "else",
88 | "body": [
89 | "else",
90 | "begin",
91 | "\t$0",
92 | "end;"
93 | ],
94 | "description": "else end"
95 | },
96 | "enum": {
97 | "prefix": "enum",
98 | "body": [
99 | "T${1:EnumName} = (${2:meOne}, $0);"
100 | ],
101 | "description": "enum"
102 | },
103 | "for begin end": {
104 | "prefix": "for",
105 | "body": [
106 | "for ${1:i} := ${2:0} to ${3:max} do",
107 | "begin",
108 | "\t$0",
109 | "end;"
110 | ],
111 | "description": "for begin end"
112 | },
113 | "for in end": {
114 | "prefix": "forin",
115 | "body": [
116 | "for ${1:MyElem} in ${2:MyList} do",
117 | "begin",
118 | "\t$0",
119 | "end;"
120 | ],
121 | "description": "for in end"
122 | },
123 | "for downto": {
124 | "prefix": "ford",
125 | "body": [
126 | "for ${1:i} := ${2:max} downto ${3:0} do",
127 | "begin",
128 | "\t$0",
129 | "end;"
130 | ],
131 | "description": "for downto"
132 | },
133 | "for (no begin end)": {
134 | "prefix": "fors",
135 | "body": [
136 | "for ${1:i} := ${2:0} to ${3:max} do",
137 | "\t$0"
138 | ],
139 | "description": "for (no begin end)"
140 | },
141 | "function end": {
142 | "prefix": "function",
143 | "body": [
144 | "function ${1:MyFunction}(${2}):${3};",
145 | "begin",
146 | "\t$0",
147 | "end;"
148 | ],
149 | "description": "function end"
150 | },
151 | "if (no begin end)": {
152 | "prefix": "ifn",
153 | "body": [
154 | "if ${1} then \t$0"
155 | ],
156 | "description": "if (no begin end)"
157 | },
158 | "if end": {
159 | "prefix": "if",
160 | "body": [
161 | "if ${1} then",
162 | "begin",
163 | "\t$0",
164 | "end;"
165 | ],
166 | "description": "if end"
167 | },
168 | "if else (no begin end)": {
169 | "prefix": "ifen",
170 | "body": [
171 | "if ${1} then",
172 | "\t$2",
173 | "else",
174 | "\t$3"
175 | ],
176 | "description": "if else (no begin end)"
177 | },
178 | "if else end": {
179 | "prefix": "ife",
180 | "body": [
181 | "if ${1} then",
182 | "begin",
183 | "\t$2",
184 | "end",
185 | "else",
186 | "begin",
187 | "\t$3",
188 | "end;"
189 | ],
190 | "description": "if else end"
191 | },
192 | "if not Assigned (no begin end)": {
193 | "prefix": "ifnass",
194 | "body": [
195 | "if not Assigned(${1}) then",
196 | "\t${1} := T${1}.Create(${2});$0"
197 | ],
198 | "description": "if not Assigned (no begin end)"
199 | },
200 | "if nil (no begin end)": {
201 | "prefix": "ifnil",
202 | "body": [
203 | "if $1 = nil then",
204 | "\t$1 := T${2:ClassName}.Create($3);$0"
205 | ],
206 | "description": "if nil (no begin end)"
207 | },
208 | "procedure end": {
209 | "prefix": "procedure",
210 | "body": [
211 | "procedure ${1:MyProcedure}(${2});",
212 | "begin",
213 | "\t$0",
214 | "end;"
215 | ],
216 | "description": "procedure"
217 | },
218 | "property getter": {
219 | "prefix": "prop",
220 | "body": [
221 | "property ${1:name}: ${2:type} read Get${1} write Set${1};$0"
222 | ],
223 | "description": "property getter"
224 | },
225 | "property field": {
226 | "prefix": "propf",
227 | "body": [
228 | "property ${1:name}: ${2:type} read F${1:name} write F${1:name};$0"
229 | ],
230 | "description": "property field"
231 | },
232 | "property read only field": {
233 | "prefix": "proprof",
234 | "body": [
235 | "property ${1:name}: ${2:type} read F${1:name};$0"
236 | ],
237 | "description": "property read only field"
238 | },
239 | "property read only field with func": {
240 | "prefix": "proprof",
241 | "body": [
242 | "property ${1:name}: ${2:type} read F${1:name};$0"
243 | ],
244 | "description": "property read only field"
245 | },
246 |
247 | "property get and set with function ": {
248 | "prefix": "property get and set with function",
249 | "body": [
250 | "procedure Set${1:Name}(const Value: ${2:TType});",
251 | "function Get${1:Name}: ${2:TType};",
252 | "property ${1:Name}: ${2:TType} read Get${1:Name} write Set${1:Name};"
253 | ],
254 | "description": "property get and set with function"
255 | },
256 | "property get with function": {
257 | "prefix": "property get with function",
258 | "body": [
259 | "function Get${1:Name}: ${2:TType};",
260 | "property ${1:Name}: ${2:TType} read Get${1:Name};"
261 | ],
262 | "description": "property get with function"
263 | },
264 | "raise": {
265 | "prefix": "raise",
266 | "body": [
267 | "raise ${1:Exception}.Create('${2:Error Message}');$0"
268 | ],
269 | "description": "raise"
270 | },
271 | "region": {
272 | "prefix": "region",
273 | "body": [
274 | "{\\$REGION '${1:MyRegion}'}",
275 | "\t$0",
276 | "{\\$ENDREGION}"
277 | ],
278 | "description": "region"
279 | },
280 | "repeat until": {
281 | "prefix": "repeat",
282 | "body": [
283 | "repeat",
284 | "\t$0",
285 | "until (${1:True});"
286 | ],
287 | "description": "repeat until"
288 | },
289 |
290 | "try finally": {
291 | "prefix": "tryf",
292 | "body": [
293 | "try",
294 | "\t$0",
295 | "finally",
296 | "\t$1",
297 | "end;"
298 | ],
299 | "description": "try finally"
300 | },
301 | "try except": {
302 | "prefix": "trye",
303 | "body": [
304 | "try",
305 | "\t$0",
306 | "except",
307 | "\ton ${1:e}: ${2:Exception} do",
308 | "end;"
309 | ],
310 | "description": "try except"
311 | },
312 | "finally end": {
313 | "prefix": "finally",
314 | "body": [
315 | "finally",
316 | " $1",
317 | "end;"
318 | ],
319 | "description": "finally end"
320 | },
321 | "except end": {
322 | "prefix": "except",
323 | "body": [
324 | "except",
325 | " on E: Exception do",
326 | " begin",
327 | " $1",
328 | " end;",
329 | "end;"
330 | ],
331 | "description": "try except end"
332 | },
333 | "try object finally": {
334 | "prefix": "trycf",
335 | "body": [
336 | "${1:variable} := ${2:TComponent}.Create(${3});",
337 | "try",
338 | "\t$0",
339 | "finally",
340 | "\tFreeAndNil(${1:variable});",
341 | "end;"
342 | ],
343 | "description": "try object finally"
344 | },
345 | "out": {
346 | "prefix": "out",
347 | "body": [
348 | "out"
349 | ],
350 | "description": "out"
351 | },
352 | "then": {
353 | "prefix": "then",
354 | "body": [
355 | "then",
356 | "begin",
357 | " $1",
358 | "end;"
359 | ],
360 | "description": "then with begin end"
361 | },
362 | "then else": {
363 | "prefix": "thene",
364 | "body": [
365 | "then",
366 | "begin",
367 | " $1",
368 | "end",
369 | "else",
370 | "begin",
371 | " $2",
372 | "end;"
373 | ],
374 | "description": "then else with begin end"
375 | },
376 | "while do": {
377 | "prefix": "while",
378 | "body": [
379 | "while $1 do",
380 | "begin",
381 | " $2",
382 | "end;"
383 | ],
384 | "description": "while do"
385 | },
386 | "do": {
387 | "prefix": "do",
388 | "body": [
389 | "do",
390 | " $1"
391 | ],
392 | "description": "do"
393 | },
394 | "until": {
395 | "prefix": "until",
396 | "body": [
397 | "until ($1);"
398 | ],
399 | "description": "until"
400 | },
401 | "private": {
402 | "prefix": "private",
403 | "body": [
404 | "private"
405 | ],
406 | "description": "private"
407 | },
408 | "protected": {
409 | "prefix": "protected",
410 | "body": [
411 | "protected"
412 | ],
413 | "description": "protected"
414 | },
415 | "public": {
416 | "prefix": "public",
417 | "body": [
418 | "public"
419 | ],
420 | "description": "public"
421 | },
422 | "published": {
423 | "prefix": "published",
424 | "body": [
425 | "published"
426 | ],
427 | "description": "published"
428 | },
429 | "strict private": {
430 | "prefix": "strict private",
431 | "body": [
432 | "strict private"
433 | ],
434 | "description": "strict private"
435 | },
436 | "strict protected": {
437 | "prefix": "strict protected",
438 | "body": [
439 | "strict protected"
440 | ],
441 | "description": "strict protected"
442 | },
443 | "class": {
444 | "prefix": "class",
445 | "body": [
446 | "class"
447 | ],
448 | "description": "class"
449 | },
450 | "record": {
451 | "prefix": "record",
452 | "body": [
453 | "record"
454 | ],
455 | "description": "record"
456 | },
457 | "interface": {
458 | "prefix": "interface",
459 | "body": [
460 | "interface"
461 | ],
462 | "description": "interface"
463 | },
464 | "implementation": {
465 | "prefix": "implementation",
466 | "body": [
467 | "implementation"
468 | ],
469 | "description": "implementation"
470 | },
471 | "class procedure": {
472 | "prefix": "class procedure",
473 | "body": [
474 | "class procedure"
475 | ],
476 | "description": "class procedure"
477 | },
478 | "class function": {
479 | "prefix": "class function",
480 | "body": [
481 | "class function"
482 | ],
483 | "description": "class function"
484 | },
485 | "cdecl": {
486 | "prefix": "cdecl",
487 | "body": [
488 | "cdecl"
489 | ],
490 | "description": "cdecl"
491 | },
492 | "stdcall": {
493 | "prefix": "stdcall",
494 | "body": [
495 | "stdcall"
496 | ],
497 | "description": "stdcall"
498 | },
499 | "external": {
500 | "prefix": "external",
501 | "body": [
502 | "external"
503 | ],
504 | "description": "external"
505 | },
506 | "static": {
507 | "prefix": "static",
508 | "body": [
509 | "static"
510 | ],
511 | "description": "static"
512 | },
513 | "virtual": {
514 | "prefix": "virtual",
515 | "body": [
516 | "virtual"
517 | ],
518 | "description": "virtual"
519 | },
520 | "override": {
521 | "prefix": "override",
522 | "body": [
523 | "override"
524 | ],
525 | "description": "override"
526 | },
527 | "reintroduce": {
528 | "prefix": "reintroduce",
529 | "body": [
530 | "reintroduce"
531 | ],
532 | "description": "reintroduce"
533 | },
534 | "overload": {
535 | "prefix": "overload",
536 | "body": [
537 | "overload"
538 | ],
539 | "description": "overload"
540 | },
541 | "mode": {
542 | "prefix": "mode",
543 | "body": [
544 | "{\\$mode ${1|delphi,objfpc|}}{\\$H+}"
545 | ],
546 | "description": "{$mode }"
547 | },
548 |
549 |
550 | "unit with class(ObjFPC)": {
551 | "prefix": "unit with class",
552 | "body": [
553 | "unit $1;",
554 | "",
555 | "{\\$mode objfpc}{\\$H+}",
556 | "",
557 | "interface",
558 | "uses",
559 | "\tSysUtils, Classes;",
560 | "",
561 | "type",
562 | "\tT$1 = class(T${2:Object})",
563 | "\tprivate",
564 | "\t$0",
565 | "\tprotected",
566 | "\t\t",
567 | "\tpublic",
568 | "\t\tconstructor Create;",
569 | "\t\tdestructor Destroy; override;",
570 | "\tpublished",
571 | "\t\t",
572 | "end;",
573 | "",
574 | "implementation",
575 | "constructor T$1.Create;",
576 | "begin",
577 | "\tinherited Create;",
578 | "\t",
579 | "end;",
580 | "\t",
581 | "destructor T$1.Destroy;",
582 | "begin",
583 | "\tinherited Destroy;",
584 | "\t",
585 | "end;",
586 | "",
587 | "end."
588 | ],
589 | "description": "unit with class"
590 | },
591 | "unit (FPC)": {
592 | "prefix": "unit",
593 | "body": [
594 | "unit ${1:unit_name};",
595 | "",
596 | "{\\$mode objfpc}{\\$H+}",
597 | "",
598 | "interface",
599 | "\t",
600 | "uses",
601 | "\tSysUtils${2:, Classes};",
602 | "\t",
603 | "implementation",
604 | "\t",
605 | "$0",
606 | "\t",
607 | "end."
608 | ],
609 | "description": "unit template"
610 | },
611 | "unit with class(Delphi)": {
612 | "prefix": "unit with class",
613 | "body": [
614 | "unit $1;",
615 | "",
616 | "{\\$mode delphi}{\\$H+}",
617 | "",
618 | "interface",
619 | "uses",
620 | "\tSysUtils, Classes;",
621 | "",
622 | "type",
623 | "\tT$1 = class(T${2:Object})",
624 | "\tprivate",
625 | "\t$0",
626 | "\tprotected",
627 | "\t\t",
628 | "\tpublic",
629 | "\t\tconstructor Create;",
630 | "\t\tdestructor Destroy; override;",
631 | "\tpublished",
632 | "\t\t",
633 | "end;",
634 | "",
635 | "implementation",
636 | "constructor T$1.Create;",
637 | "begin",
638 | "\tinherited Create;",
639 | "\t",
640 | "end;",
641 | "\t",
642 | "destructor T$1.Destroy;",
643 | "begin",
644 | "\tinherited Destroy;",
645 | "\t",
646 | "end;",
647 | "",
648 | "end."
649 | ],
650 | "description": "unit with class"
651 | },
652 | "unit (Delphi)": {
653 | "prefix": "unit",
654 | "body": [
655 | "unit ${1:unit_name};",
656 | "",
657 | "{\\$mode delphi}{\\$H+}",
658 | "",
659 | "interface",
660 | "\t",
661 | "uses",
662 | "\tSysUtils${2:, Classes};",
663 | "\t",
664 | "implementation",
665 | "\t",
666 | "$0",
667 | "\t",
668 | "end."
669 | ],
670 | "description": "unit template"
671 | },
672 | "specialize":{
673 | "prefix":"specialize",
674 | "body":[
675 | "specialize $0;"
676 | ],
677 | "description":"specialize declaration"
678 | }
679 | }
--------------------------------------------------------------------------------
/src/commands.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { FpcItem } from './providers/project';
3 | import * as fs from 'fs';
4 | import * as fs2 from 'fs-extra';
5 | import path = require('path');
6 | import { BuildMode, FpcTask, FpcTaskDefinition, FpcTaskProvider, taskProvider } from './providers/task';
7 | import { CompileOption } from './languageServer/options';
8 | import { configuration } from './common/configuration'
9 | import { type } from 'os';
10 | import { client } from './extension';
11 | import { TextEditor, TextEditorEdit } from 'vscode';
12 |
13 |
14 | export class FpcCommandManager {
15 | constructor(private workspaceRoot: string) {
16 |
17 | }
18 | registerAll(context: vscode.ExtensionContext) {
19 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.build', this.ProjectBuild));
20 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.rebuild', this.ProjectReBuild));
21 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.clean', this.projectClean));
22 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.opensetting', this.ProjectOpen));
23 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.newproject', this.ProjectNew));
24 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.add', this.ProjectAdd));
25 | context.subscriptions.push(vscode.commands.registerCommand('fpctoolkit.project.setdefault', this.projectSetDefault));
26 |
27 | context.subscriptions.push(vscode.commands.registerTextEditorCommand('fpctoolkit.code.complete',this.CodeComplete));
28 | }
29 | ProjectAdd = async (node: FpcItem) => {
30 | if (node.level === 0) {
31 | let config = vscode.workspace.getConfiguration('tasks', vscode.Uri.file(this.workspaceRoot));
32 | let inp = await vscode.window.showQuickPick(['debug', 'release', 'other...'], { canPickMany: false });
33 | if (!inp) {
34 | return;
35 | }
36 | let label: string | undefined;
37 | let customOption = '-dDEBUG';
38 | let isDebug=false;
39 | switch (inp) {
40 | case 'debug':
41 | isDebug=true;
42 | label = 'debug';
43 | break;
44 | case 'release':
45 | label = 'release';
46 | customOption = '-dRELEASE';
47 | break;
48 |
49 | default:
50 | label = await vscode.window.showInputBox({ prompt: 'Input build label:' });
51 |
52 | break;
53 | }
54 | if (!label) {
55 | return;
56 | }
57 | let v = {
58 | "label": label,
59 | "file": node.label,
60 | "type": "fpc",
61 | "buildOption": {
62 | "syntaxMode": "ObjFPC",
63 | "unitOutputDir": "./out",
64 | "customOptions": [
65 | customOption
66 | ]
67 | }
68 | };
69 | if(isDebug){
70 | v.buildOption.customOptions=[customOption,'-gw2'];
71 | }
72 |
73 | let tasks = config.tasks;
74 | if (tasks) {
75 | tasks.push(v);
76 | } else {
77 | tasks = [v];
78 | }
79 | config.update(
80 | "tasks",
81 | tasks,
82 | vscode.ConfigurationTarget.WorkspaceFolder
83 | );
84 | }
85 |
86 | };
87 | ProjectBuild = async (node: FpcItem) => {
88 | if (node.level === 0) {
89 |
90 | } else {
91 | vscode.tasks.fetchTasks({ type: 'fpc' }).then((e) => {
92 | e.forEach((task) => {
93 | //vscode.window.showInformationMessage(task.name);
94 | if (task.name === node.label) {
95 | let newtask=taskProvider.taskMap.get(task.name);
96 | if(newtask){
97 | (newtask as FpcTask).BuildMode=BuildMode.normal;
98 | }
99 | vscode.tasks.executeTask(task);
100 |
101 | return;
102 | }
103 |
104 | });
105 | });
106 |
107 | }
108 |
109 | };
110 |
111 | ProjectReBuild = async (node: FpcItem) => {
112 |
113 | if (node.level === 0) {
114 |
115 | } else {
116 | await this.projectClean(node);
117 | this.ProjectBuild(node);
118 |
119 | // vscode.tasks.fetchTasks({ type: 'fpc' }).then((e) => {
120 |
121 | // for (const task of e) {
122 | // if (task.name === node.label) {
123 | // let newtask=taskProvider.taskMap.get(task.name);
124 | // if(newtask){
125 | // (newtask as FpcTask).BuildMode=BuildMode.rebuild;
126 | // }
127 |
128 | // vscode.tasks.executeTask(task).then((e)=>{
129 | // console.log(e.task.name);
130 | // });
131 |
132 | // return;
133 | // }
134 |
135 | // }
136 | // });
137 |
138 | }
139 |
140 | };
141 | ProjectOpen = async (node?: FpcItem) => {
142 |
143 | let file = path.join(this.workspaceRoot, ".vscode", "tasks.json");
144 | let doc = await vscode.workspace.openTextDocument(file);
145 | let te = await vscode.window.showTextDocument(doc, vscode.ViewColumn.One);
146 |
147 | };
148 | ProjectNew = async () => {
149 |
150 | let s = `program main;
151 | {$mode objfpc}{$H+}
152 | uses
153 | classes,sysutils;
154 | begin
155 |
156 | end.`;
157 |
158 | let file = path.join(this.workspaceRoot, "main.lpr");
159 |
160 |
161 | fs.writeFile(file, s, () => {
162 | let f = vscode.workspace.openTextDocument(file);
163 | f.then((doc) => {
164 | vscode.window.showTextDocument(doc, vscode.ViewColumn.One)
165 | .then((e: vscode.TextEditor) => {
166 | let pos = new vscode.Position(2, 4);
167 | e.selection = new vscode.Selection(pos, pos);
168 | });
169 |
170 | });
171 |
172 | });
173 |
174 | let config = vscode.workspace.getConfiguration('tasks', vscode.Uri.file(this.workspaceRoot));
175 |
176 | let v = {
177 | "label": "debug",
178 | "file": "main.lpr",
179 | "type": "fpc",
180 | "presentation": {
181 | "showReuseMessage": false,
182 | "clear": true,
183 | "revealProblems": "onProblem"
184 | },
185 | "buildOption": {
186 | "unitOutputDir": "./out",
187 | "customOptions": [
188 | "-dDEBUG"
189 | ]
190 | }
191 | };
192 | let tasks = config.tasks;
193 | if (tasks) {
194 | tasks.push(v);
195 | } else {
196 | tasks = [v];
197 | }
198 | config.update(
199 | "tasks",
200 | tasks,
201 | vscode.ConfigurationTarget.WorkspaceFolder
202 | );
203 |
204 | };
205 | projectClean = async (node: FpcItem) => {
206 |
207 | let definition = taskProvider.GetTaskDefinition(node.label);
208 |
209 | let dir = definition?.buildOption?.unitOutputDir;
210 | if (!dir) { return; }
211 | if (!path.isAbsolute(dir)) {
212 |
213 | if (definition?.cwd) {
214 | let cur_dir=definition.cwd;
215 | if(cur_dir.startsWith('./') || cur_dir.startsWith('.\\')){
216 | cur_dir=path.join(this.workspaceRoot,definition.cwd);
217 | }
218 | dir = path.join(cur_dir, dir);
219 | } else {
220 | dir = path.join(this.workspaceRoot, dir);
221 | }
222 | }
223 |
224 | let cleanExt = definition?.cleanExt;
225 | if (fs.existsSync(dir)) {
226 | try {
227 | let exts = ['.o', '.ppu', '.lfm', '.a', '.or', '.res','.rsj','.obj'];
228 | let isall = false;
229 | if (cleanExt) {
230 | if ((cleanExt).trim() == '*') {
231 | isall = true;
232 | }
233 | let tmps = (cleanExt).split(',');
234 | for (const s of tmps) {
235 | exts.push(s);
236 | }
237 | }
238 | let files = fs.readdirSync(dir);
239 | for (let index = 0; index < files.length; index++) {
240 | let file = files[index].toLowerCase();
241 | let ext = path.extname(file);
242 |
243 | if (isall || exts.includes(ext)) {
244 | try {
245 | fs2.removeSync(path.join(dir, file));
246 | } catch {
247 |
248 | }
249 |
250 | }
251 | }
252 |
253 | } catch {
254 |
255 | }
256 | }
257 | };
258 |
259 | projectSetDefault = async (node: FpcItem) => {
260 | let config = vscode.workspace.getConfiguration('tasks', vscode.Uri.file(this.workspaceRoot));
261 | let tasks=config.tasks;
262 | for (const task of tasks) {
263 | if(task.label===node.label){
264 | if(typeof(task.group)==='object'){
265 | task.group.isDefault=true;
266 | }else{
267 | task.group={kind:task.group,isDefault:true};
268 | }
269 | client.restart();
270 | }else{
271 | if(typeof(task.group)==='object'){
272 | task.group.isDefault=undefined;
273 | }
274 | }
275 |
276 |
277 | }
278 | config.update(
279 | "tasks",
280 | tasks,
281 | vscode.ConfigurationTarget.WorkspaceFolder
282 | );
283 | }
284 |
285 |
286 | CodeComplete= async (textEditor: TextEditor, edit: TextEditorEdit) => {
287 | client.doCodeComplete(textEditor);
288 |
289 | }
290 | }
291 |
--------------------------------------------------------------------------------
/src/common/configuration.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ConfigurationChangeEvent, Event, EventEmitter, workspace,
3 | WorkspaceConfiguration, ConfigurationTarget, Uri
4 | } from "vscode";
5 |
6 | const extensionName = "fpctoolkit";
7 |
8 | class Configuration
9 | {
10 | private configuration: WorkspaceConfiguration;
11 | private configurationWs: WorkspaceConfiguration;
12 | private _onDidChange = new EventEmitter();
13 |
14 |
15 | // get onDidChange(): Event
16 | // {
17 | // return this._onDidChange.event;
18 | // }
19 |
20 |
21 | constructor()
22 | {
23 | this.configuration = workspace.getConfiguration(extensionName);
24 | this.configurationWs = workspace.getConfiguration();
25 | workspace.onDidChangeConfiguration(this.onConfigurationChanged, this);
26 | }
27 |
28 |
29 | private onConfigurationChanged(event: ConfigurationChangeEvent)
30 | {
31 | if (event.affectsConfiguration(extensionName))
32 | {
33 | this.configuration = workspace.getConfiguration(extensionName);
34 | this._onDidChange.fire(event);
35 | }
36 | }
37 |
38 |
39 | public get(key: string, defaultValue?: T): T
40 | {
41 | return this.configuration.get(key, defaultValue!);
42 | }
43 |
44 |
45 | /**
46 | * Include entire settings key. This is just workspace.getConfiguration().
47 | * Example:
48 | * getGlobal("terminal.integrated.shell.windows", "")
49 | */
50 | public getVs(key: string, defaultValue?: T): T
51 | {
52 | return this.configurationWs.get(key, defaultValue!);
53 | }
54 |
55 |
56 | public updateVs(key: string, value: any): Thenable
57 | {
58 | return this.configurationWs.update(key, value, ConfigurationTarget.Global);
59 | }
60 |
61 |
62 | public updateVsWs(key: string, value: any): Thenable
63 | {
64 | return this.configurationWs.update(key, value, ConfigurationTarget.Workspace);
65 | }
66 |
67 |
68 | public update(key: string, value: any): Thenable
69 | {
70 | return this.configuration.update(key, value, ConfigurationTarget.Global);
71 | }
72 |
73 |
74 | public updateWs(key: string, value: any): Thenable
75 | {
76 | return this.configuration.update(key, value, ConfigurationTarget.Workspace);
77 | }
78 |
79 |
80 | // public updateWsf(section: string, value: any, uri?: Uri): Thenable
81 | // {
82 | // uri = uri || (workspace.workspaceFolders ? workspace.workspaceFolders[0].uri : undefined);
83 | // return workspace.getConfiguration(extensionName, uri).update(section, value, ConfigurationTarget.WorkspaceFolder);
84 | // }
85 |
86 |
87 | // public inspect(section: string)
88 | // {
89 | // return this.configuration.inspect(section);
90 | // }
91 |
92 | }
93 |
94 | export const configuration = new Configuration();
--------------------------------------------------------------------------------
/src/common/escape.ts:
--------------------------------------------------------------------------------
1 | //https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#8-colors
2 |
3 | export enum TE_Style {
4 | Black = '\u001b[30m',
5 | Red = '\u001b[31m',
6 | Green = '\u001b[32m',
7 | Yellow = '\u001b[33m',
8 | Blue = '\u001b[34m',
9 | Magenta = '\u001b[35m',
10 | Cyan = '\u001b[36m',
11 | White = '\u001b[37m',
12 |
13 | BrightBlack = '\u001b[30;1m',
14 | BrightRed = '\u001b[31;1m',
15 | BrightGreen = '\u001b[32;1m',
16 | BrightYellow = '\u001b[33;1m',
17 | BrightBlue = '\u001b[34;1m',
18 | BrightMagenta = '\u001b[35;1m',
19 | BrightCyan = '\u001b[36;1m',
20 | BrightWhite = '\u001b[37;1m',
21 |
22 | BackgroundBlack = '\u001b[40m',
23 | BackgroundRed = '\u001b[41m',
24 | BackgroundGreen = '\u001b[42m',
25 | BackgroundYellow = '\u001b[43m',
26 | BackgroundBlue = '\u001b[44m',
27 | BackgroundMagenta = '\u001b[45m',
28 | BackgroundCyan = '\u001b[46m',
29 | BackgroundWhite = '\u001b[47m',
30 |
31 |
32 | BackgroundBrightBlack = '\u001b[40;1m',
33 | BackgroundBrightRed = '\u001b[41;1m',
34 | BackgroundBrightGreen = '\u001b[42;1m',
35 | BackgroundBrightYellow = '\u001b[43;1m',
36 | BackgroundBrightBlue = '\u001b[44;1m',
37 | BackgroundBrightMagenta = '\u001b[45;1m',
38 | BackgroundBrightCyan = '\u001b[46;1m',
39 | BackgroundBrightWhite = '\u001b[47;1m',
40 |
41 | Bold = '\u001b[1m',
42 | Underline = '\u001b[4m',
43 | Reversed = '\u001b[7m',
44 |
45 | Reset = '\u001b[0m'
46 | }
47 | export class TerminalEscape {
48 |
49 | constructor() {
50 |
51 | }
52 | static apply({ msg, style }: { msg: string; style: TE_Style[]; }) {
53 | return style.join('') + msg + TE_Style.Reset;
54 | }
55 | }
--------------------------------------------------------------------------------
/src/common/util.ts:
--------------------------------------------------------------------------------
1 | import path = require("path");
2 | import * as vscode from 'vscode';
3 | /**
4 | * @File : util.ts
5 | * @Author : (coolchyni)
6 | * @Link :
7 | * @Date : 2/13/2022, 11:32:21 AM
8 | * some function copy form https://github.com/microsoft/vscode-cpptools/blob/main/Extension/src/common.ts
9 | */
10 |
11 | export let extensionPath: string;
12 | export let extensionContext: vscode.ExtensionContext | undefined;
13 | export function setExtensionContext(context: vscode.ExtensionContext): void {
14 | extensionContext = context;
15 | extensionPath = extensionContext.extensionPath;
16 | }
17 | export function setExtensionPath(path: string): void {
18 | extensionPath = path;
19 | }
20 |
21 | export function getExtensionFilePath(extensionfile: string): string {
22 | return path.resolve(extensionPath, extensionfile);
23 | }
24 | export function isVsCodeInsiders(): boolean {
25 | return extensionPath.includes(".vscode-insiders") ||
26 | extensionPath.includes(".vscode-server-insiders") ||
27 | extensionPath.includes(".vscode-exploration") ||
28 | extensionPath.includes(".vscode-server-exploration");
29 | }
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | // The module 'vscode' contains the VS Code extensibility API
2 | // Import the module and reference it with the alias vscode in your code below
3 | import * as vscode from 'vscode';
4 | import { FpcItem, FpcProjectProvider } from './providers/project';
5 | import { diagCollection, FpcTaskProvider,taskProvider } from './providers/task';
6 | import { FpcCommandManager } from './commands';
7 | import * as util from './common/util';
8 | import {TLangClient} from './languageServer/client';
9 | import { configuration } from './common/configuration';
10 | import { JediFormatter } from './formatter';
11 | import { format } from 'path';
12 | import * as MyCodeAction from './languageServer/codeaction';
13 | export let client:TLangClient;
14 | export let formatter:JediFormatter;
15 | export let logger:vscode.OutputChannel;
16 |
17 | // this method is called when your extension is activated
18 | // your extension is activated the very first time the command is executed
19 | export async function activate(context: vscode.ExtensionContext) {
20 |
21 | if (!vscode.workspace.workspaceFolders) {
22 | return;
23 | }
24 |
25 | logger=vscode.window.createOutputChannel('fpctoolkit');
26 |
27 | vscode.window.onDidChangeVisibleTextEditors(onDidChangeVisibleTextEditors);
28 | vscode.workspace.onDidChangeTextDocument(onDidChangeTextDocument);
29 | util.setExtensionContext(context);
30 | const workspaceRoot = vscode.workspace.workspaceFolders[0].uri.fsPath;
31 |
32 |
33 | let commands = new FpcCommandManager(workspaceRoot);
34 | commands.registerAll(context);
35 |
36 | formatter=new JediFormatter();
37 | formatter.doInit();
38 |
39 | let ProjectProvider= new FpcProjectProvider(workspaceRoot,context);
40 | vscode.window.registerTreeDataProvider("FpcProjectExplorer", ProjectProvider);
41 |
42 | //taskProvider=new FpcTaskProvider(workspaceRoot);
43 | context.subscriptions.push(vscode.tasks.registerTaskProvider(
44 | FpcTaskProvider.FpcTaskType,
45 | taskProvider
46 | )
47 | );
48 |
49 |
50 |
51 | MyCodeAction.activate(context);
52 |
53 | client=new TLangClient(ProjectProvider);
54 | await client.doInit();
55 | client.start();
56 |
57 |
58 | }
59 |
60 | function onDidChangeTextDocument(e:vscode.TextDocumentChangeEvent){
61 | if(e.contentChanges.length>0){
62 | if(!diagCollection.has(e.document.uri)){ return ;}
63 |
64 |
65 | for (const change of e.contentChanges) {
66 | let newline=(change.text.match(/\n/g) || '').length+1;
67 | if(change.range.isSingleLine && (newline<2)){
68 | continue;
69 | }
70 | let diags= diagCollection.get(e.document.uri);
71 | if(!diags){return;}
72 |
73 | let oldline=change.range.end.line-change.range.start.line+1;
74 |
75 | let lines_change=newline-oldline;
76 | let newdiags=[];
77 | for (const diag of diags) {
78 | if(change.range.contains(diag.range)){//remove it if contains
79 | continue;
80 | }
81 |
82 | if(diag.range.start.line>=change.range.start.line){
83 | diag.range=new vscode.Range(diag.range.start.line+lines_change,diag.range.start.character,diag.range.end.line+lines_change,diag.range.end.character)
84 | }
85 | newdiags.push(diag)
86 | }
87 | diagCollection.set(e.document.uri, newdiags);
88 | }
89 |
90 |
91 |
92 | }
93 |
94 | }
95 | function onDidChangeVisibleTextEditors(editors: readonly vscode.TextEditor[]): void {
96 | // Process delayed didOpen for any visible editors we haven't seen before
97 | editors.forEach(editor => {
98 | if ((editor.document.uri.scheme === "file") && (editor.document.languageId === "objectpascal" || editor.document.languageId === "pascal" )) {
99 | editor.options.tabSize=configuration.get('format.tabsize',2);
100 | client.onDidChangeVisibleTextEditor(editor);
101 | }
102 | });
103 | }
104 | // this method is called when your extension is deactivated
105 | export function deactivate() {
106 | if (!client) {
107 | return undefined;
108 | }
109 | return client.stop();
110 | }
111 |
--------------------------------------------------------------------------------
/src/formatter.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as ChildProcess from "child_process";
3 | import * as util from './common/util';
4 | import path = require('path');
5 | import { configuration } from './common/configuration';
6 | import { env } from 'process';
7 | import * as fs from 'fs';
8 | import { client, logger } from './extension';
9 | import { Console } from 'console';
10 |
11 | export class JediFormatter {
12 | private jcfpath:string;
13 | private default_cfg:string;
14 | private is_win:boolean=true;
15 | constructor() {
16 | const plat: NodeJS.Platform = process.platform;
17 | const arch = process.arch;
18 | let extensionProcessName = '';
19 |
20 | if (arch === 'x64') {
21 | if (plat === 'win32') {
22 | extensionProcessName = 'win32/jcf.exe';
23 | } else if (plat === 'linux') {
24 | extensionProcessName = 'x86_64-linux/jcf';
25 | } else if (plat == 'darwin') {
26 | extensionProcessName = 'x86_64-darwin/jcf';
27 | }
28 | else {
29 | throw "Invalid Platform";
30 | }
31 | } else if (arch === 'arm64') {
32 | if (plat === 'linux') {
33 | extensionProcessName = 'aarch64-linux/jcf';
34 | } else if (plat == 'darwin') {
35 | extensionProcessName = 'x86_64-darwin/jcf';
36 | }
37 | else if (plat == 'win32') {
38 | extensionProcessName = 'win32/jcf.exe';
39 | } else {
40 | throw "Invalid Platform";
41 | }
42 | } else {
43 | throw "Invalid arch";
44 | }
45 | this.is_win=plat==='win32';
46 |
47 | this.jcfpath = path.resolve(util.getExtensionFilePath("bin"), extensionProcessName);
48 | if(!this.is_win){
49 | fs.chmodSync(this.jcfpath,755);
50 | }
51 | this.default_cfg=path.resolve(util.getExtensionFilePath("bin"),'jcfsettings.cfg');
52 | let cfg_path='';
53 | if(this.is_win){
54 | cfg_path=env.LOCALAPPDATA+'/lazarus/jcfsettings.cfg';
55 | }else{
56 | cfg_path=env.HOME+'/.lazarus/jcfsettings.cfg';
57 | };
58 | if(fs.existsSync(cfg_path)){
59 | this.default_cfg=cfg_path;
60 | }
61 |
62 |
63 | }
64 | getCfgConfig():string{
65 | let cfg=configuration.get("format.cfgpath","");
66 | if(cfg==""){
67 | cfg=this.default_cfg;
68 | }
69 | return cfg;
70 | }
71 | doInit() {
72 | let _this = this;
73 | let enable=configuration.get('format.enabled',true);
74 | if(!enable) return;
75 | // 👍 formatter implemented using API
76 | vscode.languages.registerDocumentFormattingEditProvider('objectpascal', {
77 | provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.ProviderResult {
78 | let cfg_path=_this.getCfgConfig();
79 | let proc= ChildProcess.spawn(_this.jcfpath, ['-inplace', '-y','-config='+cfg_path,'-F' ,document.fileName] );
80 | logger.appendLine(proc.spawnargs.join(' '));
81 | proc.stdout.on('data', (data) => {
82 | logger.appendLine(data);
83 | console.log(`stdout: ${data}`);
84 | });
85 |
86 | proc.stderr.on('data', (data) => {
87 | logger.appendLine(data);
88 | console.error(`stderr: ${data}`);
89 | });
90 |
91 | proc.on('close', (code) => {
92 | console.log(`child process exited with code ${code}`);
93 | });
94 | proc.unref();
95 | return [];
96 | }
97 | });
98 |
99 | }
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/src/languageServer/client.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @File : client.ts
3 | * @Author : (coolchyni)
4 | * @Link :
5 | * @Date : 2/16/2022, 11:26:06 PM
6 | */
7 | import path = require('path');
8 | import * as vscode from 'vscode';
9 | import { workspace } from 'vscode';
10 | import {
11 | State,
12 | NotificationType,
13 | LanguageClient,
14 | ServerOptions,
15 | Executable,
16 | LanguageClientOptions,
17 | ShowMessageNotification,
18 | ShowMessageParams,
19 | MessageType,
20 | ExecuteCommandRequest,
21 | ExecuteCommandParams,
22 | ErrorHandler,
23 | Message,
24 | ErrorHandlerResult,
25 | ErrorAction,
26 | CloseHandlerResult,
27 | CloseAction} from 'vscode-languageclient/node';
28 |
29 | import { FpcProjectProvider } from '../providers/project';
30 | import * as util from '../common/util';
31 | import { CompileOption, InitializationOptions } from "./options";
32 | import { env } from 'process';
33 | import * as fs from 'fs-extra';
34 | import { client, logger } from '../extension';
35 | import { ClientRequest } from 'http';
36 |
37 | interface InputRegion {
38 | startLine: number;
39 | startCol:number;
40 | endLine: number;
41 | endCol:number;
42 | }
43 |
44 | interface DecorationRangesPair {
45 | decoration: vscode.TextEditorDecorationType;
46 | ranges: vscode.Range[];
47 | }
48 |
49 | interface InactiveRegionParams {
50 | uri: string;
51 | fileVersion: number;
52 | regions: InputRegion[];
53 | }
54 |
55 | // Notifications from the server
56 | const InactiveRegionNotification: NotificationType = new NotificationType('pasls/inactiveRegions');
57 |
58 | //set cursor pos
59 | interface SetSelectionParams {
60 | uri: string;
61 | /**
62 | * The position at which the selection starts.
63 | * This position might be before or after {@link Selection.active active}.
64 | */
65 | anchor: vscode.Position;
66 |
67 | /**
68 | * The position of the cursor.
69 | * This position might be before or after {@link Selection.anchor anchor}.
70 | */
71 | active: vscode.Position;
72 | }
73 | const SetSelectionNotification: NotificationType = new NotificationType('pasls/setSelection');
74 |
75 | function GetEnvironmentVariables(): {} {
76 | // load environment variables from settings which are used for CodeTools
77 | const plat = process.platform;
78 | let userEnvironmentVariables = {};
79 | let keys: string[] = ['PP', 'FPCDIR', 'LAZARUSDIR', 'FPCTARGET', 'FPCTARGETCPU'];
80 | let settingEnvironmentVariables = workspace.getConfiguration('fpctoolkit.env');
81 | Object.keys(settingEnvironmentVariables).forEach(key => {
82 | if (keys.includes(key)) {
83 | if (settingEnvironmentVariables[key]) {
84 | userEnvironmentVariables[key] = settingEnvironmentVariables[key];
85 | }
86 | }
87 | });
88 | //set default value
89 | let PP = settingEnvironmentVariables.get('PP');
90 | if (PP === undefined || PP === '') //not init
91 | {
92 | if (plat === 'win32') {
93 | ///3.2.2/bin/i386-win32/fpc.exe
94 | //search lazarus
95 | let dirs = ['C:/lazarus/fpc', 'C:/FPC'];
96 | let ver_test = /\d+\.\d+\.\d+/;
97 | for (const _dir of dirs) {
98 | if (fs.pathExistsSync(_dir)) {
99 | let subdirs = fs.readdirSync(_dir);
100 | for (const fpcver of subdirs) {
101 | if (ver_test.test(fpcver)) { //found it
102 | if (_dir.startsWith('C:/lazarus')) {
103 | userEnvironmentVariables['LAZARUSDIR'] = 'C:/lazarus';
104 | env['LAZARUSDIR'] = userEnvironmentVariables['LAZARUSDIR'];
105 | }
106 | userEnvironmentVariables['PP'] = path.join(_dir, fpcver, 'bin', 'i386-win32', 'fpc.exe');
107 | userEnvironmentVariables['FPCDIR'] = path.join(_dir, fpcver, 'source');
108 | env['PP'] = userEnvironmentVariables['PP'];
109 |
110 | return userEnvironmentVariables;
111 | }
112 | }
113 | }
114 | }
115 | } else {
116 | let dirs = ['/usr/bin/fpc', '/usr/local/bin/fpc'];
117 | let ver_test = new RegExp('\d+\.\d+\.\d+');
118 | for (const _dir of dirs) {
119 | if (fs.existsSync(_dir)) {
120 | userEnvironmentVariables['PP'] = _dir;
121 | }
122 | }
123 | if (fs.existsSync('/usr/local/share/fpcsrc')) {
124 | userEnvironmentVariables['FPCDIR'] = '/usr/local/share/fpcsrc';
125 | }
126 | }
127 | }
128 |
129 | env['PP'] = userEnvironmentVariables['PP'];
130 | env['LAZARUSDIR'] = userEnvironmentVariables['LAZARUSDIR'];
131 |
132 | return userEnvironmentVariables;
133 | }
134 | interface myConfiguration extends vscode.WorkspaceConfiguration {
135 | cwd: string;
136 | }
137 | export class TLangClient implements ErrorHandler {
138 | private client: LanguageClient | undefined;
139 | private targetOS?: string;
140 | private targetCPU?: string;
141 | private inactiveRegionsDecorations = new Map();
142 | constructor(
143 | public projProvider: FpcProjectProvider
144 | ) {
145 | this.client = undefined;
146 | };
147 |
148 | /**
149 | * An error has occurred while writing or reading from the connection.
150 | *
151 | * @param error - the error received
152 | * @param message - the message to be delivered to the server if know.
153 | * @param count - a count indicating how often an error is received. Will
154 | * be reset if a message got successfully send or received.
155 | */
156 | error(error: Error, message: Message | undefined, count: number | undefined): ErrorHandlerResult{
157 | logger.appendLine(error.name+' '+error.message);
158 | return {action:ErrorAction.Continue} as ErrorHandlerResult;
159 | }
160 | /**
161 | * The connection to the server got closed.
162 | */
163 | closed(): CloseHandlerResult{
164 | logger.appendLine("Server closed.");
165 | return {action:CloseAction.Restart} as CloseHandlerResult;
166 | }
167 |
168 | private getLanguageServerFileName(): string {
169 | let extensionProcessName: string = 'pasls';
170 | let paslspath=vscode.workspace.getConfiguration('fpctoolkit.pasls').get('path');
171 |
172 |
173 | const plat: NodeJS.Platform = process.platform;
174 | const arch = process.arch;
175 | if (arch === 'x64') {
176 | this.targetCPU = 'x86_64';
177 | if (plat === 'win32') {
178 | extensionProcessName = 'win32/pasls.exe';
179 | this.targetOS = 'win64';
180 | } else if (plat === 'linux') {
181 | extensionProcessName = 'x86_64-linux/pasls';
182 | this.targetOS = 'linux';
183 | } else if (plat == 'darwin') {
184 | extensionProcessName = 'x86_64-darwin/pasls';
185 | this.targetOS = 'darwin';
186 | }
187 | else {
188 | throw "Invalid Platform";
189 | }
190 | } else if (arch === 'arm64') {
191 | this.targetCPU = 'aarch64';
192 | if (plat === 'linux') {
193 | extensionProcessName = 'aarch64-linux/pasls';
194 | this.targetOS = 'linux';
195 | } else if (plat == 'darwin') {
196 | extensionProcessName = 'x86_64-darwin/pasls';
197 | this.targetOS = 'darwin';
198 | }
199 | else if (plat == 'win32') {
200 | this.targetOS = 'win32';
201 | extensionProcessName = 'win32/pasls.exe';
202 | } else {
203 | throw "Invalid Platform";
204 | }
205 | } else {
206 | throw "Invalid arch";
207 | }
208 | if(paslspath && paslspath.length>0){
209 | return paslspath;
210 | }
211 | return path.resolve(util.getExtensionFilePath("bin"), extensionProcessName);
212 | };
213 | async doOnReady() {
214 | this.client?.onNotification(ShowMessageNotification.type, (e: ShowMessageParams) => {
215 | //vscode.window.showErrorMessage(e.message);
216 |
217 | switch (e.type) {
218 | case MessageType.Info:
219 | vscode.window.showInformationMessage(e.message);
220 | break;
221 | case MessageType.Warning:
222 | vscode.window.showWarningMessage(e.message);
223 | break;
224 | case MessageType.Error:
225 | if ((e as any).hasFile) {
226 | let f = e.message.split('@')
227 | let file = f[0].split(' ')[0];
228 | let pos = f[1].split(':');
229 |
230 | let position: vscode.Position = new vscode.Position(Number.parseInt(pos[0]), Number.parseInt(pos[1]));
231 |
232 | let diag=new vscode.Diagnostic(new vscode.Range(position,position),e.message);
233 |
234 | this.client?.diagnostics?.set( vscode.Uri.parse(file),[diag]);
235 |
236 |
237 | vscode.window.showErrorMessage(e.message, 'View Error').then(item => {
238 | if (item === 'View Error') {
239 | vscode.workspace.openTextDocument(file).then(doc => {
240 |
241 | let position: vscode.Position = new vscode.Position(Number.parseInt(pos[0]), Number.parseInt(pos[1]));
242 | vscode.window.showTextDocument(doc, { selection: new vscode.Selection(position, position) });
243 | });
244 |
245 | }
246 |
247 | });
248 |
249 | } else {
250 | vscode.window.showErrorMessage(e.message);
251 | }
252 |
253 |
254 | break;
255 |
256 | default:
257 | break;
258 | }
259 |
260 |
261 | });
262 | this.client?.onNotification(InactiveRegionNotification, (params: InactiveRegionParams) => {
263 | //const settings: CppSettings = new CppSettings(this.RootUri);
264 | const opacity: number | undefined = 0.3;//settings.inactiveRegionOpacity;
265 | if (opacity !== null && opacity !== undefined) {
266 | let backgroundColor: string | undefined = "";//settings.inactiveRegionBackgroundColor;
267 | if (backgroundColor === "") {
268 | backgroundColor = undefined;
269 | }
270 | let color: string | undefined = "";//settings.inactiveRegionForegroundColor;
271 | if (color === "") {
272 | color = undefined;
273 | }
274 | const decoration: vscode.TextEditorDecorationType = vscode.window.createTextEditorDecorationType({
275 | opacity: opacity.toString(),
276 | backgroundColor: backgroundColor,
277 | color: color,
278 | rangeBehavior: vscode.DecorationRangeBehavior.OpenOpen
279 | });
280 | // We must convert to vscode.Ranges in order to make use of the API's
281 | const ranges: vscode.Range[] = [];
282 | params.regions.forEach(element => {
283 | const newRange: vscode.Range = new vscode.Range(element.startLine-1, element.startCol-1, element.endLine-1, element.endCol-1);
284 | ranges.push(newRange);
285 | });
286 | // Find entry for cached file and act accordingly
287 | const valuePair: DecorationRangesPair | undefined = this.inactiveRegionsDecorations.get(params.uri);
288 | if (valuePair) {
289 | // Disposing of and resetting the decoration will undo previously applied text decorations
290 | valuePair.decoration.dispose();
291 | valuePair.decoration = decoration;
292 | // As vscode.TextEditor.setDecorations only applies to visible editors, we must cache the range for when another editor becomes visible
293 | valuePair.ranges = ranges;
294 | } else { // The entry does not exist. Make a new one
295 | const toInsert: DecorationRangesPair = {
296 | decoration: decoration,
297 | ranges: ranges
298 | };
299 | this.inactiveRegionsDecorations.set(params.uri, toInsert);
300 | }
301 | //if (settings.dimInactiveRegions && params.fileVersion === openFileVersions.get(params.uri)) {
302 | // Apply the decorations to all *visible* text editors
303 | const editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === params.uri);
304 | for (const e of editors) {
305 | e.setDecorations(decoration, ranges);
306 | }
307 | //}
308 | }
309 |
310 | });
311 |
312 | this.client?.onNotification(SetSelectionNotification, (params: SetSelectionParams) => {
313 | let uri=vscode.Uri.parse(params.uri);
314 | vscode.workspace.openTextDocument(uri).then(doc => {
315 | setTimeout(() => {
316 | vscode.window.showTextDocument(doc, { selection: new vscode.Selection(params.anchor, params.active) });
317 | }, 500);
318 | });
319 | });
320 |
321 | }
322 | async doInit() {
323 | //lsp
324 |
325 | console.log("Greetings from pascal-language-server 🙏");
326 |
327 | // Load the path to the language server from settings
328 | //let executable: string = workspace.getConfiguration('pascalLanguageServer').get("executable")!;
329 | let executable: string = this.getLanguageServerFileName();
330 | if(process.platform!='win32'){
331 | fs.chmod(executable,755);
332 | }
333 | // TODO: download the executable for the active platform
334 | // https://github.com/genericptr/pascal-language-server/releases/download/x86_64-darwin/pasls
335 | // if (!executable) {
336 | // let target = 'x86_64-darwin';
337 | // executable = context.asAbsolutePath(path.join('bin', target, 'pasls'));
338 | // }
339 |
340 | console.log("executable: " + executable);
341 |
342 | let run: Executable = {
343 | command: executable,
344 | options: {
345 | env: GetEnvironmentVariables()
346 | }
347 | };
348 | let debug: Executable = run;
349 |
350 | let serverOptions: ServerOptions = {
351 | run,
352 | debug
353 | };
354 |
355 | //Connect to language server via socket
356 |
357 | //rpcjson
358 | // The server is a started as a separate app and listens on port 5007
359 | // let connectionInfo = {
360 | // port: 9999
361 | // };
362 | // let serverOptions = () => {
363 |
364 | // let socket = net.connect(connectionInfo);
365 | // socket.on("data",(data:Buffer)=>{
366 | // console.info(data.toString());
367 | // });
368 |
369 | // let result: StreamInfo = {
370 | // writer: socket,
371 | // reader: socket
372 | // };
373 | // return Promise.resolve(result);
374 | // };
375 |
376 | var initializationOptions = new InitializationOptions();
377 |
378 | let opt = await this.projProvider.GetDefaultTaskOption();
379 | if (opt != undefined) {
380 | initializationOptions.updateByCompileOption(opt);
381 | } else {
382 | opt = new CompileOption();
383 | opt.buildOption!.targetCPU = this.targetCPU;
384 | opt.buildOption!.targetOS = this.targetOS;
385 | }
386 |
387 | // client extensions configure their server
388 | let clientOptions: LanguageClientOptions = {
389 | initializationOptions: initializationOptions,
390 | errorHandler: this,
391 | // workspaceFolder: folder,
392 | documentSelector: [
393 | { scheme: 'file', language: 'objectpascal' },
394 | { scheme: 'untitled', language: 'objectpascal' }
395 | ]
396 | }
397 |
398 | this.client = new LanguageClient('fpctoolkit.lsp', 'Free Pascal Language Server', serverOptions, clientOptions);
399 |
400 | };
401 | public onDidChangeVisibleTextEditor(editor: vscode.TextEditor): void {
402 |
403 | // Apply text decorations to inactive regions
404 | const valuePair: DecorationRangesPair | undefined = this.inactiveRegionsDecorations.get(editor.document.uri.toString());
405 | if (valuePair) {
406 | editor.setDecorations(valuePair.decoration, valuePair.ranges); // VSCode clears the decorations when the text editor becomes invisible
407 | }
408 |
409 | }
410 |
411 | async start(): Promise {
412 | await this.client?.start();
413 | await this.doOnReady();
414 | };
415 | async stop(): Promise {
416 | this.client?.stop();
417 | };
418 |
419 | async restart(): Promise {
420 |
421 | await this.client?.stop();
422 | await this.doInit();
423 | await this.client?.start();
424 | await this.doOnReady();
425 |
426 | };
427 |
428 | async doCodeComplete(editor:vscode.TextEditor): Promise {
429 | let sel=editor.selection.start;
430 | var req:ExecuteCommandParams={
431 | command:"CompleteCode",
432 | arguments:[
433 | editor.document.uri.toString(),
434 | sel.line.toString(),
435 | sel.character.toString()
436 | ]
437 | };
438 | let result:ExecuteCommandParams=await this.client?.sendRequest(ExecuteCommandRequest.type,req);
439 |
440 | if(result.arguments![0]=='true'){
441 |
442 | let newLine=Number.parseInt( result.arguments![3] );
443 | let newCharacter=Number.parseInt(result.arguments![2]);
444 | // let newTopLine=Number.parseInt(result.arguments![3]);
445 |
446 | let blocktop=Number.parseInt(result.arguments![4]);
447 | if(blocktop==0)
448 | {
449 | return ;
450 | }
451 | // let blockContent=result.arguments![5];
452 |
453 | let pos=new vscode.Position(newLine,newCharacter);
454 | setTimeout(() => {
455 | vscode.window.showTextDocument(editor.document, { selection: new vscode.Selection(pos,pos) });
456 | }, 200);
457 |
458 | }
459 |
460 |
461 | }
462 |
463 | async getUnitPath( unitnames:string[]): Promise {
464 |
465 | var req:ExecuteCommandParams={
466 | command:"GetUnitPath",
467 | arguments:unitnames
468 | };
469 | let result:ExecuteCommandParams=await this.client?.sendRequest(ExecuteCommandRequest.type,req);
470 |
471 |
472 | if(result.arguments){
473 | return result.arguments;
474 | }else{
475 | return [];
476 | }
477 |
478 | }
479 | }
--------------------------------------------------------------------------------
/src/languageServer/codeaction.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------
2 | * Copyright (C) Microsoft Corporation. All rights reserved.
3 | *--------------------------------------------------------*/
4 | // sample
5 | // https://github.com/microsoft/vscode-extension-samples/blob/main/code-actions-sample/src/extension.ts
6 |
7 | import { match } from 'assert';
8 | import { disconnect } from 'process';
9 | import * as vscode from 'vscode';
10 | import { diagCollection } from '../providers/task';
11 |
12 | const COMMAND_UNUSED = 'fpctoolkit.code-actions.remove_unused_variable';
13 |
14 | export function activate(context: vscode.ExtensionContext) {
15 | // context.subscriptions.push(
16 | // vscode.languages.registerCodeActionsProvider('objectpascal', new Emojizer(), {
17 | // providedCodeActionKinds: Emojizer.providedCodeActionKinds
18 | // }));
19 |
20 | // const emojiDiagnostics = vscode.languages.createDiagnosticCollection("emoji");
21 | // context.subscriptions.push(emojiDiagnostics);
22 |
23 |
24 |
25 | context.subscriptions.push(
26 | vscode.languages.registerCodeActionsProvider('objectpascal', new FpcCodeAction(), {
27 | providedCodeActionKinds: FpcCodeAction.providedCodeActionKinds
28 | })
29 | );
30 |
31 | context.subscriptions.push(
32 | vscode.commands.registerCommand(COMMAND_UNUSED, (document:vscode.TextDocument,diag:vscode.Diagnostic,variable:string) => {
33 | let edit=new vscode.WorkspaceEdit();
34 | let line=document.lineAt(diag.range.start.line);
35 | let linetext=line.text.trim();
36 | var has_var=false;
37 | if(linetext.substring(0,4).toLocaleLowerCase()=='var ')
38 | {
39 | linetext=linetext.substring(4,linetext.length)
40 | has_var=true;
41 | }
42 | let isdelete=false;
43 | let ret=linetext.split(/,|:/);
44 | if(ret.length<=2){
45 | if(has_var){
46 | edit.replace(document.uri,line.range,"var");
47 | }else{
48 | edit.delete(document.uri,line.rangeIncludingLineBreak);
49 | isdelete=true;
50 | }
51 | }else{
52 | ret=ret.map(v=>v.trim()).filter(v=>v!=variable);
53 | linetext=has_var?'var ':' '+ret.slice(0,-1).join(', ')+': '+ret[ret.length-1];
54 | edit.replace(document.uri,line.range,linetext);
55 | }
56 |
57 | let diags= diagCollection.get(document.uri);
58 | if(!diags){
59 | vscode.workspace.applyEdit(edit);
60 | return;
61 | }
62 | if(!isdelete){
63 | //delete fixed diag
64 |
65 | var newdiags=[];
66 | for (const item of diags) {
67 | if(item===diag)
68 | {
69 | continue;
70 | }
71 |
72 | //chagne diag pos use workspace.onDidChangeTextDocument
73 | // if(isdelete && item.range.start.line>=line.range.start.line){
74 | // item.range=new vscode.Range(item.range.start.line-1,item.range.start.character,item.range.end.line-1,item.range.end.character)
75 | // }
76 | newdiags.push(item)
77 | }
78 | diagCollection.set(document.uri, newdiags);
79 | }
80 |
81 |
82 | vscode.workspace.applyEdit(edit);
83 |
84 | })
85 | );
86 | }
87 |
88 | /**
89 | * Provides code actions for converting :) to a smiley emoji.
90 | */
91 | // export class Emojizer implements vscode.CodeActionProvider {
92 |
93 | // public static readonly providedCodeActionKinds = [
94 | // vscode.CodeActionKind.QuickFix
95 | // ];
96 |
97 | // public provideCodeActions(document: vscode.TextDocument, range: vscode.Range): vscode.CodeAction[] | undefined {
98 | // if (!this.isAtStartOfSmiley(document, range)) {
99 | // return;
100 | // }
101 |
102 | // const replaceWithSmileyCatFix = this.createFix(document, range, '😺');
103 |
104 | // const replaceWithSmileyFix = this.createFix(document, range, '😀');
105 | // // Marking a single fix as `preferred` means that users can apply it with a
106 | // // single keyboard shortcut using the `Auto Fix` command.
107 | // replaceWithSmileyFix.isPreferred = true;
108 |
109 | // const replaceWithSmileyHankyFix = this.createFix(document, range, '💩');
110 |
111 | // const commandAction = this.createCommand();
112 |
113 | // return [
114 | // replaceWithSmileyCatFix,
115 | // replaceWithSmileyFix,
116 | // replaceWithSmileyHankyFix,
117 | // commandAction
118 | // ];
119 | // }
120 |
121 | // private isAtStartOfSmiley(document: vscode.TextDocument, range: vscode.Range) {
122 | // const start = range.start;
123 | // const line = document.lineAt(start.line);
124 | // return line.text[start.character] === ':' && line.text[start.character + 1] === ')';
125 | // }
126 |
127 | // private createFix(document: vscode.TextDocument, range: vscode.Range, emoji: string): vscode.CodeAction {
128 | // const fix = new vscode.CodeAction(`Convert to ${emoji}`, vscode.CodeActionKind.QuickFix);
129 | // fix.edit = new vscode.WorkspaceEdit();
130 | // fix.edit.replace(document.uri, new vscode.Range(range.start, range.start.translate(0, 2)), emoji);
131 | // return fix;
132 | // }
133 |
134 | // private createCommand(): vscode.CodeAction {
135 | // const action = new vscode.CodeAction('Learn more...', vscode.CodeActionKind.Empty);
136 | // action.command = { command: COMMAND, title: 'Learn more about emojis', tooltip: 'This will open the unicode emoji page.' };
137 | // return action;
138 | // }
139 | // }
140 |
141 | /**
142 | * Provides code actions corresponding to diagnostic problems.
143 | */
144 | export class FpcCodeAction implements vscode.CodeActionProvider {
145 |
146 | public static readonly providedCodeActionKinds = [
147 | vscode.CodeActionKind.QuickFix
148 | ];
149 |
150 | provideCodeActions(document: vscode.TextDocument, range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, token: vscode.CancellationToken): vscode.CodeAction[] {
151 | // for each diagnostic entry that has the matching `code`, create a code action command
152 | return context.diagnostics
153 | .filter(diagnostic =>{
154 | return diagnostic.code === 5025;
155 | } )
156 | .map(diagnostic => this.createCommandCodeAction(document,diagnostic));
157 | }
158 |
159 | private createCommandCodeAction(document: vscode.TextDocument,diagnostic: vscode.Diagnostic): vscode.CodeAction {
160 | let matchs=diagnostic.message.match(/Local variable "(.*?)".*?not used/)!;
161 |
162 | let variable=matchs[1];
163 |
164 | const fix = new vscode.CodeAction('Remove variable `'+variable+'`', vscode.CodeActionKind.QuickFix);
165 | fix.command = { command: COMMAND_UNUSED, title: 'Remove unused variable.', tooltip: 'Remove unused variable.' };
166 | fix.command.arguments=[document, diagnostic,variable];
167 | fix.diagnostics = [diagnostic];
168 | //fix.isPreferred = true;
169 | return fix;
170 | }
171 | }
--------------------------------------------------------------------------------
/src/languageServer/options.ts:
--------------------------------------------------------------------------------
1 | import internal = require('stream');
2 | import * as vscode from 'vscode';
3 | import * as fs from 'fs';
4 | import * as path from 'path';
5 | import { configuration } from '../common/configuration';
6 | import { BuildOption, FpcTaskDefinition } from '../providers/task';
7 | export class CompileOption {
8 | /**
9 | * Compile Option
10 | */
11 | public type: string = "fpc";
12 | public cwd: string = "";
13 | public label: string = '';
14 | public file: string = '';
15 | public windows?: { customOptions?: string[] };
16 | public linux?: { customOptions?: string[] };
17 | public darwin?: { customOptions?: string[] };
18 |
19 | public presentation = {
20 | showReuseMessage: false,
21 | clear: true,
22 | revealProblems: "onProblem"
23 | };
24 | public buildOption?:BuildOption;
25 |
26 |
27 | constructor(
28 |
29 | taskDefinition?: FpcTaskDefinition,
30 | workspaceRoot?:string
31 |
32 | ) {
33 | if (taskDefinition) {
34 | this.file = taskDefinition.file??"";
35 | this.label = taskDefinition.file??"untitled";
36 | this.windows = taskDefinition.windows;
37 | this.buildOption = taskDefinition.buildOption;
38 | if(workspaceRoot){
39 | if (taskDefinition.cwd) {
40 | this.cwd = path.join(workspaceRoot, taskDefinition.cwd);
41 | } else {
42 | this.cwd = workspaceRoot;
43 | }
44 | }else{
45 | this.cwd=taskDefinition.cwd??"";
46 | }
47 |
48 |
49 | } else {
50 | this.buildOption = {
51 | unitOutputDir: "./out",
52 | customOptions: [
53 | "-dDEBUG"
54 | ]
55 | };
56 | }
57 |
58 |
59 | }
60 |
61 | toOptionString() {
62 | let fpccfg = configuration;
63 | let globalOption = {
64 | customOptions: fpccfg.get('customOptions'),
65 | libPath: fpccfg.get('libPath'),
66 | searchPath: fpccfg.get('searchPath'),
67 | };
68 | let plat = process.platform;
69 | var plat_options:string[]|undefined;
70 | if (plat == 'win32') {
71 | plat_options=this.windows?.customOptions;
72 | } else if (plat == 'linux') {
73 | plat_options=this.linux?.customOptions;
74 | } else if (plat == 'darwin') {
75 | plat_options=this.darwin?.customOptions;
76 | }
77 |
78 | let s: string = '';
79 | plat_options?.forEach((e) => {
80 | s += e + " ";
81 | });
82 | if (this.buildOption?.targetOS) {
83 | s += "-T" + this.buildOption!.targetOS + " ";
84 | }
85 | if (this.buildOption?.targetCPU) {
86 | s += "-P" + this.buildOption!.targetCPU + " ";
87 | }
88 | if(this.buildOption?.forceRebuild){
89 | s +='-B '
90 | }
91 | if(this.buildOption?.msgIgnore && this.buildOption.msgIgnore.length>0){
92 | s+='-vm'+this.buildOption.msgIgnore.join(',')+' ';
93 | }
94 | if (this.buildOption?.outputFile) {
95 | let outfile = this.buildOption!.outputFile;
96 | if (outfile.startsWith(".")) {
97 | outfile = path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, outfile);
98 | }
99 | let dir = path.dirname(outfile);
100 | if (!fs.existsSync(dir)) {
101 | try {
102 | fs.mkdirSync(dir, { recursive: true });
103 | } catch (error) {
104 | vscode.window.showErrorMessage("Can't create output directory.(" + dir + ")");
105 | }
106 |
107 | }
108 | s += "-o" + this.buildOption!.outputFile + " ";
109 | }
110 |
111 | globalOption?.searchPath?.forEach((e) => {
112 | s += "-Fu" + e + " ";
113 | });
114 | globalOption?.libPath?.forEach((e) => {
115 | s += "-Fl" + e + " ";
116 | });
117 |
118 |
119 | this.buildOption?.searchPath?.forEach((e) => {
120 | s += "-Fu" + e + " ";
121 | });
122 | this.buildOption?.libPath?.forEach((e) => {
123 | s += "-Fl" + e + " ";
124 | });
125 |
126 | if (this.buildOption?.unitOutputDir) {
127 | let dir = this.buildOption!.unitOutputDir;
128 |
129 | if (dir.startsWith(".")) {
130 | dir = path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, dir);
131 | }
132 |
133 | if (!fs.existsSync(dir)) {
134 | try {
135 | fs.mkdirSync(dir, { recursive: true });
136 | } catch (error) {
137 | vscode.window.showErrorMessage("Can't create unit output directory.(" + dir + ")");
138 | }
139 |
140 | }
141 | s += "-FU" + this.buildOption!.unitOutputDir + " ";
142 | }
143 |
144 | if (this.buildOption?.optimizationLevel) {
145 | s += "-O" + this.buildOption!.optimizationLevel + " ";
146 | }
147 |
148 | if (this.buildOption?.syntaxMode) {
149 | s += "-M" + this.buildOption!.syntaxMode + " ";
150 | }
151 | globalOption?.customOptions?.forEach((e) => {
152 | s += e + " ";
153 | });
154 | this.buildOption?.customOptions?.forEach((e) => {
155 | s += e + " ";
156 | });
157 |
158 |
159 | return s;
160 | }
161 |
162 | }
163 | export class TaskInfo {
164 | ischanged: boolean = false;
165 | tasks: any;
166 | }
167 |
168 |
169 | export class InitializationOptions {
170 | //current work path
171 | public cwd: string | undefined;
172 | // Path to the main program file for resolving references
173 | // if not available the path of the current document will be used
174 | public program: string | undefined;
175 | // Path to SQLite3 database for symbols
176 | public symbolDatabase: string | undefined;
177 | // FPC compiler options (passed to Code Tools)
178 | public fpcOptions: Array = [];
179 | // Maximum number of completion items to be returned
180 | // if the threshold is reached then CompletionList.isIncomplete = true
181 | public maximumCompletions: number = 100;
182 | // Policy which determines how overloaded document symbols are displayed
183 | public overloadPolicy: number | undefined;
184 | // procedure completions with parameters are inserted as snippets
185 | public insertCompletionsAsSnippets: boolean | undefined;
186 | // procedure completions with parameters (non-snippet) insert
187 | // empty brackets (and insert as snippet)
188 | public insertCompletionProcedureBrackets: boolean | undefined;
189 | // workspaces folders will be added to unit paths (i.e. -Fu)
190 | public includeWorkspaceFoldersAsUnitPaths: boolean | undefined;
191 | // workspaces folders will be added to include paths (i.e. -Fi)
192 | public includeWorkspaceFoldersAsIncludePaths: boolean | undefined;
193 | // syntax will be checked when file opens or saves
194 | public checkSyntax: boolean | undefined;
195 | // syntax errors will be published as diagnostics
196 | public publishDiagnostics: boolean | undefined;
197 | // enable workspace symbols
198 | public workspaceSymbols: boolean | undefined;
199 | // enable document symbols
200 | public documentSymbols: boolean | undefined;
201 | // completions contain a minimal amount of extra information
202 | public minimalisticCompletions: boolean | undefined;
203 | // syntax errors as shown in the UI with ‘window/showMessage’
204 | public showSyntaxErrors: boolean | undefined;
205 | // ignores completion items like "begin" and "var" which may interfer with IDE snippets
206 | public ignoreTextCompletions: boolean | undefined;
207 |
208 | constructor() {
209 | let cfg = vscode.workspace.getConfiguration('fpctoolkit.lsp.initializationOptions');
210 | this.program = cfg.get('program');
211 | this.maximumCompletions = cfg.get('maximumCompletions', 100);
212 | this.fpcOptions = cfg.get>("fpcOptions", []);
213 | this.overloadPolicy = cfg.get("overloadPolicy");
214 | this.insertCompletionsAsSnippets = cfg.get('insertCompletionsAsSnippets');
215 | this.insertCompletionsAsSnippets = cfg.get('insertCompletionsAsSnippets');
216 | this.includeWorkspaceFoldersAsIncludePaths = cfg.get('insertCompletionsAsSnippets');
217 | this.includeWorkspaceFoldersAsUnitPaths = cfg.get('includeWorkspaceFoldersAsUnitPaths');
218 | this.checkSyntax = cfg.get('checkSyntax');
219 | this.publishDiagnostics = cfg.get('publishDiagnostics');
220 | this.workspaceSymbols = cfg.get('workspaceSymbols');
221 | this.documentSymbols = cfg.get('documentSymbols');
222 | this.minimalisticCompletions = cfg.get('minimalisticCompletions');
223 | this.showSyntaxErrors = cfg.get('showSyntaxErrors');
224 | this.ignoreTextCompletions = cfg.get('ignoreTextCompletions');
225 | }
226 | public updateByCompileOption(opt: CompileOption) {
227 | this.cwd = opt.cwd;
228 | this.program = opt.file;
229 | let fpcOptions: Array = this.fpcOptions;
230 | let newopt = opt.toOptionString().split(' ');
231 | newopt.forEach((s) => {
232 | //if (s.startsWith('-Fi') || s.startsWith('-Fu') || s.startsWith('-d') || s.startsWith('-M')) {
233 | if (!s.startsWith('-v')) { //-v will raise error ,hide it
234 | fpcOptions.push(s);
235 | }
236 | });
237 |
238 | }
239 | }
--------------------------------------------------------------------------------
/src/providers/project.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as fs from 'fs';
3 | import * as path from 'path';
4 | import { basename, normalize } from 'path';
5 | import { CompileOption, TaskInfo } from '../languageServer/options';
6 | import { openStdin } from 'process';
7 | import { FpcTaskDefinition, FpcTaskProvider, taskProvider } from './task';
8 | import { Command } from 'vscode-languageserver-types';
9 | //import { visit, JSONVisitor } from "jsonc-parser";
10 | import { pathExists } from 'fs-extra';
11 | import { Event } from 'vscode-languageclient';
12 | import { clearTimeout } from 'timers';
13 | import { TIMEOUT } from 'dns';
14 |
15 | export class FpcProjectProvider implements vscode.TreeDataProvider {
16 |
17 | private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
18 | readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event;
19 | private watch!: vscode.FileSystemWatcher;
20 | private watchlpr!: vscode.FileSystemWatcher;
21 | public defaultFtpItem?: FpcItem = undefined;
22 | private config!:vscode.WorkspaceConfiguration;
23 | private defaultCompileOption?:CompileOption=undefined;
24 | private timeout?:NodeJS.Timeout=undefined;
25 | constructor(private workspaceRoot: string, context: vscode.ExtensionContext) {
26 | const subscriptions = context.subscriptions;
27 | const name = 'FpcProjectExplorer';
28 | subscriptions.push(vscode.commands.registerCommand(name + ".open", async (item: FpcItem) => { await this.open(item); }, this));
29 |
30 | this.watch = vscode.workspace.createFileSystemWatcher(path.join(workspaceRoot,".vscode","tasks.json"), false);
31 | this.watch.onDidChange(async (url) => {
32 | taskProvider.clean();
33 | if(this.timeout!=undefined){
34 | clearTimeout(this.timeout);
35 | }
36 | this.timeout=setTimeout(()=>{
37 | this.checkDefaultAndRefresh();
38 | },1000);
39 | });
40 | this.watch.onDidDelete(() => {
41 | this.refresh();
42 | });
43 |
44 | this.watchlpr = vscode.workspace.createFileSystemWatcher("**/*.lpr", false, true, false);
45 | this.watchlpr.onDidCreate(() => {
46 | this.refresh();
47 | });
48 | this.watchlpr.onDidDelete(() => {
49 | this.refresh();
50 | });
51 |
52 | }
53 |
54 |
55 | dispose() {
56 | throw new Error("Method not implemented.");
57 | }
58 |
59 |
60 | /*TreeDataProvider*/
61 | refresh(): void {
62 | this._onDidChangeTreeData.fire();
63 | }
64 |
65 | async checkDefaultAndRefresh():Promise{
66 | let oldCompileOption=this.defaultCompileOption;
67 | if(oldCompileOption==undefined){
68 | taskProvider.refresh();
69 | this.refresh();
70 | return;
71 | }
72 |
73 | //default task setting changed
74 | let newCompileOption=await this.GetDefaultTaskOption();
75 | if(oldCompileOption.toOptionString()!=newCompileOption.toOptionString()){
76 | taskProvider.refresh();
77 | }
78 | this.refresh();
79 |
80 |
81 |
82 | }
83 | getTreeItem(element: FpcItem): vscode.TreeItem {
84 | return element;
85 | }
86 |
87 | getChildren(element?: FpcItem | undefined): vscode.ProviderResult {
88 |
89 |
90 | if (element) {
91 | this.defaultFtpItem=undefined;
92 | let items: FpcItem[] = [];
93 |
94 | element.tasks?.forEach((task) => {
95 | let item = new FpcItem(
96 | 1,
97 | task.label,
98 | vscode.TreeItemCollapsibleState.None,
99 | element.file,
100 | element.fileexist,
101 | task.group?.isDefault,
102 | [task]
103 | );
104 | items.push(item);
105 | if (item.isDefault) {
106 | this.defaultFtpItem = item;
107 | }
108 | });
109 | if(!this.defaultFtpItem && items.length>0){
110 | this.defaultFtpItem=items[0];
111 | this.defaultFtpItem.description='default';
112 | this.defaultFtpItem.isDefault=true;
113 | }
114 | return Promise.resolve(items);
115 |
116 | } else {
117 | //root node
118 |
119 | var itemMaps: Map = new Map();
120 | this.config = vscode.workspace.getConfiguration('tasks', vscode.Uri.file(this.workspaceRoot));
121 | //create info for pass tasks as pointer
122 | //var info =new TaskInfo();
123 | //info.tasks=config.tasks;
124 |
125 |
126 | this.config?.tasks?.forEach((e: any) => {
127 | if (e.type === 'fpc') {
128 | if (!itemMaps.has(e.file)) {
129 | itemMaps.set(
130 | e.file,
131 | new FpcItem(
132 | 0,
133 | path.basename(e.file),
134 | vscode.TreeItemCollapsibleState.Expanded,
135 | e.file,
136 | true,
137 | e.group?.isDefault,
138 | [e]
139 | )
140 | );
141 | } else {
142 | itemMaps.get(e.file)?.tasks?.push(e);
143 | }
144 | }
145 |
146 | });
147 | let items: FpcItem[] = [];
148 |
149 |
150 | vscode.workspace.workspaceFolders!.forEach(item => {
151 | let files = fs.readdirSync(item.uri.fsPath);
152 | for (let index = 0; index < files.length; index++) {
153 |
154 | let file = files[index];
155 |
156 | if (file.toLowerCase().endsWith('.lpr') || file.toLowerCase().endsWith('.dpr')) {
157 | try {
158 | if (itemMaps.has(file)) {
159 | itemMaps.get(file)!.fileexist = true;
160 | continue;
161 | }
162 |
163 | itemMaps.set(
164 | file,
165 | new FpcItem(
166 | 0,
167 | file,
168 | vscode.TreeItemCollapsibleState.Expanded,
169 | file,
170 | true,
171 | false
172 |
173 | )
174 | );
175 |
176 | } catch (error) {
177 | vscode.window.showErrorMessage("FPCToolkit:" + Error(error).message);
178 | }
179 |
180 |
181 | }
182 | }
183 | });
184 |
185 | for (const e of itemMaps.values()) {
186 | items.push(e);
187 | }
188 |
189 |
190 | //});
191 | // if(info.ischanged){
192 | // config.update("tasks",info.tasks,vscode.ConfigurationTarget.WorkspaceFolder);
193 | // }
194 |
195 | return Promise.resolve(items);
196 | }
197 |
198 | return Promise.resolve([]);
199 |
200 | }
201 | async GetDefaultTaskOption(): Promise {
202 |
203 | //refresh tasks
204 | await vscode.tasks.fetchTasks({type:'fpc'});
205 |
206 | let cfg=vscode.workspace.getConfiguration('tasks', vscode.Uri.file(this.workspaceRoot));
207 | let opt: CompileOption|undefined=undefined;
208 | let is_first=true;
209 | if (cfg?.tasks != undefined) {
210 | for (const e of cfg?.tasks) {
211 | if (e.type === 'fpc') {
212 | if (e.group?.isDefault) {
213 | let def=taskProvider.GetTaskDefinition(e.label);
214 |
215 | opt = new CompileOption(def,this.workspaceRoot);
216 | this.defaultCompileOption=opt;
217 | return opt;
218 | }
219 | if(is_first){
220 | is_first=false;
221 | let def=taskProvider.GetTaskDefinition(e.label);
222 | opt = new CompileOption(def,this.workspaceRoot);
223 | }
224 |
225 | }
226 | }
227 | }
228 | if(!opt){
229 | opt=new CompileOption();
230 | }
231 | this.defaultCompileOption=opt;
232 | return opt;
233 | }
234 | private findJsonDocumentPosition(documentText: string, taskItem: FpcItem) {
235 | // const me = this;
236 | // let inScripts = false;
237 | // let inTasks = false;
238 | // let inTaskLabel: any;
239 | // let scriptOffset = 0;
240 |
241 |
242 | // const visitor: JSONVisitor =
243 | // {
244 | // onError: () => {
245 | // return scriptOffset;
246 | // },
247 | // onObjectEnd: () => {
248 | // if (inScripts) {
249 | // inScripts = false;
250 | // }
251 | // },
252 | // onLiteralValue: (value: any, offset: number, _length: number) => {
253 | // if (inTaskLabel) {
254 | // if (typeof value === "string") {
255 | // if (inTaskLabel === "label" || inTaskLabel === "script") {
256 |
257 | // if (taskItem.label === value) {
258 | // scriptOffset = offset;
259 | // }
260 | // }
261 | // }
262 | // inTaskLabel = undefined;
263 | // }
264 | // },
265 | // onObjectProperty: (property: string, offset: number, _length: number) => {
266 | // if (property === "tasks") {
267 | // inTasks = true;
268 | // if (!inTaskLabel) { // select the script section
269 | // scriptOffset = offset;
270 | // }
271 | // }
272 | // else if ((property === "label" || property === "script") && inTasks && !inTaskLabel) {
273 | // inTaskLabel = "label";
274 | // if (!inTaskLabel) { // select the script section
275 | // scriptOffset = offset;
276 | // }
277 | // }
278 | // else { // nested object which is invalid, ignore the script
279 | // inTaskLabel = undefined;
280 | // }
281 | // }
282 | // };
283 |
284 | // visit(documentText, visitor);
285 |
286 | // //log.methodDone("find json document position", 3, " ", false, [["position", scriptOffset]]);
287 | // return scriptOffset;
288 | return documentText.indexOf('"label": "'+taskItem.label+'"');
289 | }
290 | private async open(selection: FpcItem) {
291 |
292 | let taskfile = vscode.Uri.file(path.join(this.workspaceRoot, '.vscode', 'tasks.json'))
293 |
294 | fs.existsSync(taskfile.fsPath)
295 | {
296 | const document: vscode.TextDocument = await vscode.workspace.openTextDocument(taskfile);
297 | const offset = this.findJsonDocumentPosition(document.getText(), selection);
298 | const position = document.positionAt(offset);
299 | await vscode.window.showTextDocument(document, { selection: new vscode.Selection(position, position) });
300 | }
301 | }
302 |
303 | }
304 |
305 | export class FpcItem extends vscode.TreeItem {
306 |
307 |
308 | constructor(
309 | public readonly level: number,
310 | public readonly label: string,
311 | public readonly collapsibleState: vscode.TreeItemCollapsibleState,
312 | public readonly file: string,
313 | public fileexist: boolean,
314 | public isDefault: boolean,
315 | public tasks?: any[]
316 | ) {
317 | super(label, collapsibleState);
318 | if (level === 0) {
319 | this.contextValue = 'fpcproject';
320 | } else {
321 | this.contextValue = 'fpcbuild';
322 | }
323 | this.tooltip = `${basename(this.label)} `;
324 | if (this.level > 0) {
325 | this.description = this.isDefault ? 'default' : '';
326 |
327 | const command = {
328 | command: "FpcProjectExplorer.open", // commandId is a string that contains the registered id ('myExtension.debugMessage')
329 | title: '',
330 | arguments: [this]
331 | };
332 | this.command = command;
333 | }
334 |
335 | this.iconPath=this.level? new vscode.ThemeIcon('wrench'):path.join(__filename, '..','..', 'images','pascal-project.png');
336 |
337 | //https://code.visualstudio.com/api/references/icons-in-labels
338 |
339 | //this.command!.command= "workbench.action.tasks.configureTaskRunner";
340 | //this.command!.arguments?.push(this.id);
341 |
342 | }
343 |
344 |
345 | // iconPath = {
346 | // light: this.level?'$(gripper)':path.join(__filename, '..','..', 'images', this.level ? 'build.png' : 'pascal-project.png'),
347 | // dark: path.join(__filename, '..','..', 'images', this.label ? 'build.png' : 'pascal-project.png')
348 | // };
349 |
350 |
351 | }
--------------------------------------------------------------------------------
/src/providers/task.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 | import * as vscode from 'vscode';
6 | import { CompileOption } from '../languageServer/options';
7 | import * as ChildProcess from "child_process";
8 | import path = require('path');
9 | import { TerminalEscape, TE_Style } from '../common/escape';
10 | import * as fs from 'fs';
11 | import { client } from '../extension';
12 | import { DiagnosticSeverity } from 'vscode';
13 |
14 | export class BuildOption {
15 | targetOS?: string;
16 | targetCPU?: string;
17 | customOptions?: string[];
18 | libPath?: string[];
19 | outputFile?: string;
20 | unitOutputDir?: string;
21 | optimizationLevel?: number;
22 | searchPath?: string[];
23 | syntaxMode?: string;
24 | forceRebuild?: boolean = false;
25 | msgIgnore?: Number[];
26 | };
27 |
28 | export class BuildEvent{
29 | before_build?: string[];
30 | after_build_success?:string[];
31 | after_build_failure?:string[];
32 | }
33 |
34 | export class FpcTaskDefinition implements vscode.TaskDefinition {
35 | [name: string]: any;
36 | readonly type: string = 'fpc';
37 | file?: string;
38 | cwd?: string;
39 | cleanExt?: string;
40 | inherited?: string;
41 | buildOption?: BuildOption;
42 | buildEvent?:BuildEvent;
43 | }
44 |
45 |
46 | export class FpcTaskProvider implements vscode.TaskProvider {
47 | static FpcTaskType = 'fpc';
48 | private defineMap: Map = new Map();
49 | public taskMap: Map = new Map();
50 | public GetTaskDefinition(name: string): FpcTaskDefinition | undefined {
51 | let result = this.defineMap.get(name);
52 | if (result && result.inherited) {
53 | let base = this.defineMap.get(result.inherited);
54 | if (base) {
55 | let realDefinition = new FpcTaskDefinition();
56 | this.mergeDefinition(base, realDefinition);
57 | this.mergeDefinition(result, realDefinition);
58 | return realDefinition;
59 |
60 | }
61 | }
62 | return result;
63 | }
64 | constructor(private workspaceRoot: string, private cwd: string | undefined = undefined) {
65 | }
66 |
67 | public async clean() {
68 | this.defineMap.clear();
69 | this.taskMap.clear();
70 | }
71 | public async provideTasks(): Promise {
72 | return this.getTasks();
73 | }
74 |
75 | public resolveTask(_task: vscode.Task): vscode.Task | undefined {
76 | if (this.taskMap.has(_task.name)) {
77 | let task = this.taskMap.get(_task.name);
78 | task!.definition = _task.definition;
79 | return task;
80 | } else {
81 | const file: string = _task.definition.file;
82 | if (file) {
83 | const definition: FpcTaskDefinition = _task.definition;
84 | if (_task.definition.cwd) {
85 | this.cwd = this.workspaceRoot + '/' + _task.definition.cwd;
86 | }
87 | let task = this.getTask(_task.name, definition.file, definition);
88 | this.taskMap.set(_task.name, task);
89 | return task;
90 | }
91 | }
92 |
93 | return undefined;
94 | }
95 |
96 | private async getTasks(): Promise {
97 | return [];
98 | }
99 | private mergeDefinition(from: FpcTaskDefinition, to: FpcTaskDefinition) {
100 | to.file = to.file ?? from.file;
101 | to.cwd = to.cwd ?? from.cwd;
102 | to.cleanExt = to.cleanExt ?? from.cleanExt;
103 | if (from.buildOption != undefined) {
104 | if (to.buildOption === undefined) {
105 | to.buildOption = Object.assign({}, from.buildOption);
106 | }
107 | else {
108 | to.buildOption.customOptions = ([] as string[]).concat(from.buildOption.customOptions ?? [], to.buildOption.customOptions ?? []);
109 | to.buildOption.libPath = ([] as string[]).concat(from.buildOption.libPath ?? [], to.buildOption.libPath ?? []);
110 | to.buildOption.searchPath = ([] as string[]).concat(from.buildOption.searchPath ?? [], to.buildOption.searchPath ?? []);
111 | to.buildOption.msgIgnore = ([] as Number[]).concat(from.buildOption.msgIgnore ?? [], to.buildOption.msgIgnore ?? []);
112 |
113 | to.buildOption.optimizationLevel = to.buildOption.optimizationLevel ?? from.buildOption.optimizationLevel;
114 | to.buildOption.outputFile = to.buildOption.outputFile ?? from.buildOption.outputFile;
115 | to.buildOption.syntaxMode = to.buildOption.syntaxMode ?? from.buildOption.syntaxMode;
116 | to.buildOption.targetCPU = to.buildOption.targetCPU ?? from.buildOption.targetCPU;
117 | to.buildOption.targetOS = to.buildOption.targetOS ?? from.buildOption.targetOS;
118 | to.buildOption.unitOutputDir = to.buildOption.unitOutputDir ?? from.buildOption.unitOutputDir;
119 | to.buildOption.forceRebuild = to.buildOption.forceRebuild ?? from.buildOption.forceRebuild;
120 |
121 | }
122 | }
123 |
124 | }
125 | public getTask(name: string, file?: string, definition?: FpcTaskDefinition): vscode.Task {
126 | // if (definition?.inherited) {
127 | // let pdefine = this.defineMap.get(definition.inherited);
128 | // if (pdefine) {
129 | // let realDefinition = new FpcTaskDefinition();
130 | // this.mergeDefinition(definition, realDefinition);
131 | // this.mergeDefinition(pdefine, realDefinition);
132 | // this.defineMap.set(name, realDefinition);
133 | // let task = new FpcTask(this.cwd ? this.cwd : this.workspaceRoot, name, file!, definition, realDefinition);
134 | // return task;
135 | // }
136 |
137 | // }
138 | this.defineMap.set(name, definition!);
139 | let task = new FpcTask(this.cwd ? this.cwd : this.workspaceRoot, name, file!, definition!);
140 |
141 |
142 | // task.presentationOptions.clear = true;
143 | // task.presentationOptions.echo = true;
144 | // task.presentationOptions.focus = false;
145 | // task.presentationOptions.showReuseMessage = false;
146 | // task.presentationOptions.reveal = vscode.TaskRevealKind.Always;
147 | // task.presentationOptions.panel = vscode.TaskPanelKind.Shared;
148 | // task.presentationOptions.revealProblems='onProblem';
149 | //(task.presentationOptions as any)["revealProblems"]="onProblem";
150 |
151 | //task.problemMatchers.push('$fpc');
152 |
153 |
154 | return task;
155 | }
156 |
157 | public refresh() {
158 | client.restart();
159 | }
160 | }
161 |
162 | export enum BuildMode {
163 | normal,
164 | rebuild
165 | }
166 | export class FpcTask extends vscode.Task {
167 | private _BuildMode: BuildMode = BuildMode.normal;
168 | public get BuildMode(): BuildMode {
169 | return this._BuildMode;
170 | }
171 | public set BuildMode(value: BuildMode) {
172 | this._BuildMode = value;
173 | }
174 | constructor(cwd: string, name: string, file: string, taskDefinition: FpcTaskDefinition) {
175 |
176 | super(
177 | taskDefinition,
178 | vscode.TaskScope.Workspace,
179 | `${name}`,
180 | FpcTaskProvider.FpcTaskType,
181 | //new vscode.ShellExecution(`${fpcpath} ${taskDefinition.file} ${buildOptionString}`)
182 | new FpcCustomExecution(async (): Promise => {
183 | // // When the task is executed, this callback will run. Here, we setup for running the task.
184 | // let terminal = new FpcBuildTaskTerminal(workspaceRoot, fpcpath!);
185 | //terminal.args = `${taskDefinition?.file} ${buildOptionString}`.split(' ');
186 |
187 | //taskProvider.GetTaskDefinition()
188 | let buildOptionString: string = '';
189 | let realDefinition=taskProvider.GetTaskDefinition(name);
190 | if (realDefinition === undefined) {
191 | realDefinition = taskDefinition;
192 | }
193 | if (realDefinition?.buildOption) {
194 | let opt: CompileOption = new CompileOption(realDefinition);
195 | buildOptionString = opt.toOptionString();
196 | }
197 | if (!buildOptionString) {
198 | buildOptionString = "";
199 | }
200 |
201 | if (!realDefinition) {
202 | realDefinition = {
203 | type: FpcTaskProvider.FpcTaskType,
204 | file: file,
205 |
206 | };
207 |
208 | }
209 | buildOptionString += '-vq '; //show message numbers
210 |
211 | let fpcpath = process.env['PP'];// configuration.get('env.PP');
212 | if (fpcpath === '') {
213 | fpcpath = 'fpc';
214 | }
215 |
216 | let terminal = new FpcBuildTaskTerminal(cwd, fpcpath!);
217 | if(taskDefinition.buildEvent){
218 | if(taskDefinition.buildEvent.before_build){
219 | let commands=taskDefinition.buildEvent.before_build;
220 | terminal.event_before_build=()=>{
221 | for (const cmd of commands) {
222 | let result=ChildProcess.execSync(cmd);
223 | terminal.emit(result.toString())
224 | }
225 | }
226 | }
227 | if(taskDefinition.buildEvent.after_build_failure || taskDefinition.buildEvent.after_build_success){
228 | let commands_failure=taskDefinition.buildEvent.after_build_failure;
229 | let commands_success=taskDefinition.buildEvent.after_build_success;
230 | terminal.event_after_build=(success)=>{
231 | if(success && commands_success){
232 | for (const cmd of commands_success) {
233 | let result=ChildProcess.execSync(cmd);
234 | terminal.emit(result.toString())
235 | }
236 | }else if(commands_failure)
237 | for (const cmd of commands_failure) {
238 | let result=ChildProcess.execSync(cmd);
239 | terminal.emit(result.toString())
240 | }
241 |
242 | }
243 |
244 | }
245 |
246 | }
247 |
248 | terminal.args = `${taskDefinition?.file} ${buildOptionString}`.split(' ');
249 | if (this._BuildMode == BuildMode.rebuild) {
250 | terminal.args.push('-B');
251 | }
252 | return terminal;
253 |
254 | })
255 | );
256 | //this.TaskBuildOptionString = buildOptionString;
257 | }
258 |
259 |
260 | }
261 |
262 | class FpcCustomExecution extends vscode.CustomExecution {
263 |
264 | }
265 | export var diagCollection: vscode.DiagnosticCollection = vscode.languages.createDiagnosticCollection('fpc');
266 |
267 | class FpcBuildTaskTerminal implements vscode.Pseudoterminal, vscode.TerminalExitStatus {
268 | private writeEmitter = new vscode.EventEmitter();
269 | onDidWrite: vscode.Event = this.writeEmitter.event;
270 | private closeEmitter = new vscode.EventEmitter();
271 | onDidClose: vscode.Event = this.closeEmitter.event;
272 |
273 | public event_before_build?:()=>void;
274 | public event_after_build?:(success:boolean)=>void;
275 |
276 | private process?: ChildProcess.ChildProcess;
277 | protected buffer: string = "";
278 | protected errbuf: string = "";
279 |
280 | private diagMaps: Map;
281 | public args: string[] = [];
282 |
283 | constructor(private cwd: string, private fpcpath: string) {
284 | this.diagMaps = new Map();
285 | this.onDidClose((e) => {
286 | //vscode.window.showInformationMessage('onDidClose');
287 | });
288 | }
289 | code: number | undefined;
290 |
291 | // private static inst?: FpcBuildTaskTerminal;
292 | // static getInstance(workspaceRoot?: string, fpcpath?: string): FpcBuildTaskTerminal {
293 | // if (FpcBuildTaskTerminal.inst) {
294 | // return FpcBuildTaskTerminal.inst;
295 | // } else {
296 | // FpcBuildTaskTerminal.inst = new FpcBuildTaskTerminal(workspaceRoot!, fpcpath!);
297 | // return FpcBuildTaskTerminal.inst;
298 | // }
299 |
300 | // }
301 | clear() {
302 |
303 | }
304 | open(initialDimensions: vscode.TerminalDimensions | undefined): void {
305 | //vscode.window.createTerminal()
306 | // At this point we can start using the terminal.
307 | this.doBuild();
308 | }
309 |
310 | close(): void {
311 |
312 | }
313 |
314 |
315 | async buildend() {
316 | let units = Array.from(this.diagMaps.keys());
317 |
318 | // The terminal has been closed. Shutdown the build.
319 | diagCollection.clear();
320 | let has_error: boolean = false;
321 | for (const iter of this.diagMaps) {
322 | let key = iter[0];
323 | let item = iter[1];
324 | let uri: vscode.Uri | undefined = undefined;
325 | if (fs.existsSync(key)) {
326 | uri = vscode.Uri.file(key);
327 | }
328 | if (!uri) {
329 | let unit = key.split(".")[0];
330 |
331 | let unitpaths = await client.getUnitPath([unit]);
332 | if (unitpaths.length < 1) {
333 | return;
334 | }
335 | let unitpath = unitpaths[0];
336 | //let uri:vscode.Uri|undefined=vscode.Uri.file(unitpath);
337 | if (unitpath == '') {
338 | uri = this.findFile(key)!;
339 | } else {
340 | uri = vscode.Uri.file(unitpath);
341 | }
342 | }
343 |
344 | if (uri) {
345 | diagCollection.set(uri, item);
346 | } else {
347 | diagCollection.set(vscode.Uri.file(key), item);
348 | }
349 | if (!has_error) {
350 |
351 | item.forEach((d) => {
352 | if (d.severity === 0) {
353 | has_error = true;
354 | }
355 | });
356 | }
357 | }
358 |
359 | if (has_error) {
360 | vscode.commands.executeCommand('workbench.actions.view.problems');
361 | }
362 | }
363 | findFile(filename: string): vscode.Uri | undefined {
364 |
365 | let f = path.join(this.cwd, filename);
366 | if (fs.existsSync(f)) {
367 | return vscode.Uri.file(f);
368 | }
369 | for (let index = 0; index < this.args.length; index++) {
370 | const e = this.args[index];
371 | if (e.startsWith('-Fu')) {
372 | let f2 = e.substring(3);
373 | if (f2.startsWith('.')) {
374 | f = path.join(this.cwd, f2, filename);
375 | } else {
376 | f = path.join(f2, filename);
377 | }
378 | if (fs.existsSync(f)) {
379 | return vscode.Uri.file(f);
380 | }
381 | }
382 | }
383 | return undefined;
384 | }
385 |
386 |
387 | private async doBuild(): Promise {
388 | return new Promise((resolve) => {
389 |
390 | this.buffer = "";
391 | this.errbuf = "";
392 | this.diagMaps.clear();
393 | if(this.event_before_build){
394 | this.event_before_build();
395 | }
396 | this.emit(TerminalEscape.apply({ msg: `${this.fpcpath} ${this.args.join(' ')}\r\n`, style: [TE_Style.Bold] }));
397 | this.process = ChildProcess.spawn(this.fpcpath, this.args, { cwd: this.cwd });
398 |
399 | this.process.stdout?.on('data', this.stdout.bind(this));
400 | this.process.stderr?.on('data', this.stderr.bind(this));
401 | this.process.on('close', (code) => {
402 |
403 | this.writeEmitter.fire(`Exited with code ${code}.\r\nBuild complete. \r\n\r\n`);
404 | this.buildend().then(() => {
405 | this.closeEmitter.fire(code);
406 | });
407 | if(this.event_after_build){
408 | this.event_after_build(code==0);
409 | }
410 | //This is a exitcode,not zero meens failure.
411 |
412 |
413 | resolve(0);
414 | });
415 |
416 | });
417 | }
418 |
419 |
420 | emit(msg: string) {
421 | this.writeEmitter.fire(msg + '\r\n');
422 | }
423 | stdout(data: any) {
424 | if (typeof data === "string") {
425 | this.buffer += data;
426 | }
427 | else {
428 | this.buffer += data.toString("utf8");
429 | }
430 | const end = this.buffer.lastIndexOf('\n');
431 | if (end !== -1) {
432 | this.onOutput(this.buffer.substr(0, end));
433 | this.buffer = this.buffer.substr(end + 1);
434 | }
435 | // if (this.buffer.length) {
436 | // this.emit(this.buffer);
437 | // }
438 | }
439 |
440 | stderr(data: any) {
441 | if (typeof data === "string") {
442 | this.emit(TerminalEscape.apply({ msg: data, style: [TE_Style.Yellow] }));
443 |
444 | }
445 | else {
446 | this.emit(TerminalEscape.apply({ msg: data.toString("utf8"), style: [TE_Style.Yellow] }));
447 | }
448 | }
449 | getDiagnosticSeverity(level: string) {
450 | switch (level) {
451 | case 'Fatal':
452 | case 'Error':
453 | return vscode.DiagnosticSeverity.Error;
454 | case 'Warning':
455 | return vscode.DiagnosticSeverity.Warning;
456 | case 'Note':
457 | return vscode.DiagnosticSeverity.Information;
458 | case 'Hint':
459 | return vscode.DiagnosticSeverity.Hint;
460 | default:
461 | return vscode.DiagnosticSeverity.Information;
462 | }
463 | }
464 | onOutput(lines: string) {
465 | let ls = lines.split('\n');
466 | let cur_file = "";
467 | let reg = /^(([-:\w\\\/]+)\.(p|pp|pas|lpr|dpr|inc))\(((\d+)(\,(\d+))?)\)\s(Fatal|Error|Warning|Note|Hint): \((\d+)\) (.*)/
468 | ls.forEach(line => {
469 |
470 | let matchs = reg.exec(line);
471 |
472 | if (matchs) {
473 |
474 | let ln = Number(matchs[5]);
475 | let col = Number(matchs[7]);
476 | let file = matchs[1];
477 | let unit = matchs[2];
478 | let level = matchs[8];
479 | let msgcode = matchs[9];
480 | let msg = matchs[10];
481 | // this.emit(
482 | // TerminalEscape.apply({ msg: file+"("+ln+','+col +") ", style: TE_Style.Blue })+
483 | // TerminalEscape.apply({ msg: level+":"+msg, style: TE_Style.Red })
484 | // );
485 |
486 | let diag = new vscode.Diagnostic(
487 | new vscode.Range(new vscode.Position(ln - 1, col - 1), new vscode.Position(ln - 1, col - 1)),
488 | msg,
489 | this.getDiagnosticSeverity(level)
490 | );
491 | diag.code = Number.parseInt(msgcode);
492 |
493 | // if(msg.match(/ Local variable ".*?".*?(?:not|never) used/))
494 | // {
495 | // diag.code='variable-not-used';
496 | // }
497 | let basename = path.basename(file);
498 | // if((cur_file=="")||(path.basename(cur_file)!=path.basename(file))){
499 | // cur_file=file;
500 | // }
501 | if (this.diagMaps?.has(basename)) {
502 |
503 | this.diagMaps.get(basename)?.push(diag);
504 | } else {
505 |
506 | this.diagMaps.set(basename, [diag]);
507 |
508 | }
509 | if (diag.severity == DiagnosticSeverity.Error) {
510 | this.emit(TerminalEscape.apply({ msg: line, style: [TE_Style.Red] }));
511 | } else {
512 | this.emit(TerminalEscape.apply({ msg: line, style: [TE_Style.Cyan] }));
513 | }
514 |
515 | } else if (line.startsWith('Error:') || line.startsWith('Fatal:')) { //Fatal|Error|Warning|Note
516 | this.emit(TerminalEscape.apply({ msg: line, style: [TE_Style.Red] }));
517 |
518 | } else if (line.startsWith('Warning:')) {
519 | this.emit(TerminalEscape.apply({ msg: line, style: [TE_Style.BrightYellow] }));
520 | }
521 | else {
522 | this.emit(line);
523 | }
524 | });
525 | }
526 |
527 | }
528 |
529 | export let taskProvider: FpcTaskProvider;
530 |
531 | if (vscode.workspace.workspaceFolders) {
532 | const workspaceRoot = vscode.workspace.workspaceFolders[0].uri.fsPath;
533 | taskProvider = new FpcTaskProvider(workspaceRoot);
534 | }
535 |
536 |
--------------------------------------------------------------------------------
/syntaxes/fpc.tmLanguage:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fileTypes
6 |
7 | dpr
8 | lpr
9 | pp
10 | pas
11 |
12 | foldingStartMarker
13 | \b(?i:(function|package|procedure|try|type))\b
14 | foldingStopMarker
15 | \b(?i:(end))\b
16 | keyEquivalent
17 | ^~P
18 | name
19 | Pascal
20 | patterns
21 |
22 |
23 | match
24 | \b(?i:(absolute|abstract|all|and|and_then|array|as|asm|assembler|attribute|begin|bindable|case|class|const|constructor|destructor|delay|div|do|downto|else|end|except|export|exports|external|far|file|finalization|finally|for|forward|generic|goto|if|inc|implementation|import|in|index|inherited|initialization|inline|interface|interrupt|is|label|library|mod|module|near|nil|not|object|of|only|operator|or|or_else|otherwise|out|override|overload|packed|pow|private|property|protected|public|published|qualified|record|repeat|resident|restricted|segment|set|shl|shr|then|to|try|type|unit|until|uses|value|var|view|virtual|while|with|xor|write|writeln|specialize))\b
25 | name
26 | keyword.control.pascal
27 |
28 |
29 | captures
30 |
31 | 1
32 |
33 | name
34 | storage.type.prototype.pascal
35 |
36 | 2
37 |
38 | name
39 | entity.name.function.prototype.pascal
40 |
41 |
42 | match
43 | \b(?i:(function|procedure))\b\s+(\w+(\.\w+)?)(\(.*?\))?;\s*(?=(?i:attribute|forward|external))
44 | name
45 | meta.function.prototype.pascal
46 |
47 |
48 |
49 | captures
50 |
51 | 1
52 |
53 | name
54 | storage.type.function.pascal
55 |
56 | 2
57 |
58 | name
59 | entity.name.function.pascal
60 |
61 |
62 | match
63 | \b(?i:(function|procedure|program))\b\s+(\w+(\.\w+)?)
64 | name
65 | meta.function.pascal
66 |
67 |
68 |
69 | captures
70 |
71 | 1
72 |
73 | name
74 | storage.type.function.pascal
75 |
76 | 2
77 |
78 | name
79 | entity.name.function.pascal
80 |
81 |
82 | match
83 | \b(?i:(Shortint|Integer|Longint|Byte|Word|Boolean|WordBool|LongBool|ByteBool|Real|Single|Double|Extended|Comp|String|Char|Length|Upcase|textbackground|textcolor|gotoxy|crt|clrscr|readkey|read|readln))\b
84 | name
85 | meta.function.pascal
86 |
87 |
88 |
89 |
90 | match
91 | \b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\b
92 | name
93 | constant.numeric.pascal
94 |
95 |
96 | captures
97 |
98 | 1
99 |
100 | name
101 | punctuation.definition.comment.pascal
102 |
103 |
104 | match
105 | (--).*$\n?
106 | name
107 | comment.line.double-dash.pascal.one
108 |
109 |
110 | captures
111 |
112 | 1
113 |
114 | name
115 | punctuation.definition.comment.pascal
116 |
117 |
118 | match
119 | (//).*$\n?
120 | name
121 | comment.line.double-slash.pascal.two
122 |
123 |
124 | begin
125 | \(\*
126 | captures
127 |
128 | 0
129 |
130 | name
131 | punctuation.definition.comment.pascal
132 |
133 |
134 | end
135 | \*\)
136 | name
137 | comment.block.pascal.one
138 |
139 |
140 | begin
141 | \{
142 | captures
143 |
144 | 0
145 |
146 | name
147 | punctuation.definition.comment.pascal
148 |
149 |
150 | end
151 | \}
152 | name
153 | comment.block.pascal.two
154 |
155 |
156 | applyEndPatternLast
157 | 1
158 | begin
159 | '
160 | beginCaptures
161 |
162 | 0
163 |
164 | name
165 | punctuation.definition.string.begin.pascal
166 |
167 |
168 | end
169 | '
170 | endCaptures
171 |
172 | 0
173 |
174 | name
175 | punctuation.definition.string.end.pascal
176 |
177 |
178 | name
179 | string.quoted.single.pascal
180 | patterns
181 |
182 |
183 | match
184 | ''
185 | name
186 | constant.character.escape.apostrophe.pascal
187 |
188 |
189 |
190 |
191 | scopeName
192 | source.pascal
193 | uuid
194 | F42FA544-6B1C-11D9-9517-000D93589AF6
195 |
196 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "lib": [
7 | "es6"
8 | ],
9 | "suppressImplicitAnyIndexErrors":true,
10 | "sourceMap": true,
11 | "rootDir": "src",
12 | "strict": true /* enable all strict type-checking options */
13 | /* Additional Checks */
14 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
15 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
16 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
17 | },
18 | "exclude": [
19 | "node_modules",
20 | ".vscode-test"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------