├── .editorconfig
├── .github
├── dependabot.yaml
└── workflows
│ ├── release.yml
│ └── tests.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── DCO
├── Jenkinsfile
├── LICENSE
├── README.md
├── USAGE_DATA.md
├── docs
├── Features.md
├── JavaFeatures.md
├── PropertiesFeatures.md
└── res
│ ├── MPFormatter.gif
│ ├── MPJavaCodeLens.png
│ ├── MPJavaCompletion.gif
│ ├── MPJavaHover.gif
│ ├── MPJavaNavigation.gif
│ ├── MPJavaNavigationConfig.gif
│ ├── MPJavaValidationAndQuickFix.gif
│ ├── MPJumpToJavaDefinition.gif
│ ├── MPPropertiesDetection.png
│ ├── MPPropertyCompletion.gif
│ ├── MPPropertyHover.gif
│ ├── MPPropertyQuickFix.gif
│ ├── MPPropertyValueDefinition.gif
│ ├── MPShowAsTreeOutline.png
│ ├── MPShowAsTreeSetting.png
│ └── WorkspaceSymbolsJakartaREST.gif
├── eslint.config.mjs
├── gulpfile.js
├── icons
└── logo.png
├── images
├── componentDiagram.png
├── debugConfig.png
├── debugConfigMenu.png
├── deployment.png
├── propertiesSupport.png
├── runDebugger.png
├── runDebuggerVSCodeTests.png
└── runExtension.png
├── language-support
└── properties-support
│ ├── language-configuration.json
│ ├── microprofile-properties-injections.tmLanguage.json
│ └── microprofile-properties.tmLanguage.json
├── package-lock.json
├── package.json
├── schemas
└── package.schema.json
├── src
├── definitions
│ ├── commands.ts
│ ├── lspCommandKind.ts
│ └── microProfileLSRequestNames.ts
├── extension.ts
├── languageServer
│ ├── javaServerStarter.ts
│ ├── plugin.ts
│ └── requirements.ts
├── lsp-commands.ts
├── test
│ ├── resources
│ │ ├── no-lsp4mp-extension-package.json
│ │ └── quarkus-package.json
│ ├── runTest.ts
│ └── suite
│ │ ├── extension.test.ts
│ │ ├── index.ts
│ │ └── languageServer
│ │ ├── documentSelectorPlugin.test.ts
│ │ ├── plugin.test.ts
│ │ └── requirements.test.ts
├── util
│ ├── javaServerMode.ts
│ ├── telemetry.ts
│ └── workspaceUtils.ts
└── yaml
│ ├── YamlConstants.ts
│ └── YamlSchema.ts
├── tsconfig.json
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
22 | [package.json]
23 | indent_style = space
24 | indent_size = 2
25 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "npm"
4 | directory: "/"
5 | schedule:
6 | interval: "cron"
7 | cronjob: "0 8 * * 2,4"
8 | open-pull-requests-limit: 10
9 | groups:
10 | eslint:
11 | patterns:
12 | - "eslint"
13 | - "@eslint/js"
14 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Build & Release VS Code MicroProfile
2 |
3 | on:
4 | schedule:
5 | - cron: "0 8 * * *"
6 | workflow_dispatch:
7 | inputs:
8 | LSP4MP_TAG:
9 | description: "branch/tag of LSP4MP to build."
10 | type: string
11 | default: master
12 | publishPreRelease:
13 | description: "Publish a pre-release ?"
14 | required: true
15 | type: choice
16 | options:
17 | - "true"
18 | - "false"
19 | default: "true"
20 | publishToMarketPlace:
21 | description: "Publish to VS Code Marketplace ?"
22 | required: true
23 | type: choice
24 | options:
25 | - "true"
26 | - "false"
27 | default: "false"
28 | publishToOVSX:
29 | description: "Publish to OpenVSX Registry ?"
30 | required: true
31 | type: choice
32 | options:
33 | - "true"
34 | - "false"
35 | default: "false"
36 | jobs:
37 | should-build-change:
38 | runs-on: ubuntu-latest
39 | outputs:
40 | repo-cache-hit: ${{ steps.cache-last-commit.outputs.cache-hit }}
41 | steps:
42 | - uses: actions/checkout@v4
43 | with:
44 | repository: "eclipse/lsp4mp"
45 | fetch-depth: 2
46 | path: lsp4mp
47 | - uses: actions/checkout@v4
48 | with:
49 | repository: "redhat-developer/vscode-microprofile"
50 | fetch-depth: 2
51 | path: vscode-microprofile
52 | - run: |
53 | pushd lsp4mp
54 | git rev-parse HEAD >> ../lastCommit
55 | popd
56 | pushd vscode-microprofile
57 | git rev-parse HEAD >> ../lastCommit
58 | - name: Check New Changes
59 | id: cache-last-commit
60 | uses: actions/cache@v4
61 | with:
62 | path: lastCommit
63 | key: lastCommit-${{ hashFiles('lastCommit') }}
64 | packaging-job:
65 | runs-on: ubuntu-latest
66 | needs: should-build-change
67 | if: ${{ needs.should-build-change.outputs.repo-cache-hit != 'true' || github.event_name != 'schedule' }}
68 | steps:
69 | - name: Checkout LSP4MP
70 | uses: actions/checkout@v4
71 | with:
72 | repository: eclipse/lsp4mp
73 | ref: ${{ inputs.LSP4MP_TAG }}
74 | path: lsp4mp
75 | - name: Cache Maven local repository
76 | uses: actions/cache@v4
77 | with:
78 | path: |
79 | ~/.m2/repository
80 | ~/.m2/wrapper
81 | !~/.m2/repository/org/eclipse/lsp4mp
82 | key: maven-local-${{ hashFiles('**/pom.xml') }}
83 | - name: Set Up Java
84 | uses: actions/setup-java@v4
85 | with:
86 | java-version: '21'
87 | distribution: 'adopt'
88 | - name: Check Out VS Code MicroProfile
89 | uses: actions/checkout@v4
90 | with:
91 | path: vscode-microprofile
92 | - name: Set Up NodeJS
93 | uses: actions/setup-node@v4
94 | with:
95 | node-version: '20'
96 | - name: Install NodeJS dependencies
97 | run: npm install -g typescript "@vscode/vsce" "ovsx"
98 | - name: Build Extension
99 | run: |
100 | pushd vscode-microprofile
101 | echo "EXT_VERSION=$(cat package.json | jq -r .version)" >> $GITHUB_ENV
102 | npm install
103 | npm run build
104 | npm run vscode:prepublish
105 | - name: Test vscode-microprofile
106 | run: |
107 | pushd vscode-microprofile
108 | xvfb-run --auto-servernum npm run test --silent
109 | continue-on-error: true
110 | - name: Prepare Pre-Release
111 | if: ${{ github.event_name == 'schedule' || inputs.publishPreRelease == 'true' }}
112 | run: |
113 | pushd vscode-microprofile
114 | npx gulp prepare_pre_release
115 | echo "publishPreReleaseFlag=--pre-release" >> $GITHUB_ENV
116 | - name: Package vscode-microprofile
117 | run: |
118 | pushd vscode-microprofile
119 | vsce package ${{ env.publishPreReleaseFlag }} -o ../vscode-microprofile-${{ env.EXT_VERSION }}-${GITHUB_RUN_NUMBER}.vsix
120 | - name: Upload VSIX Artifacts
121 | uses: actions/upload-artifact@v4
122 | with:
123 | name: vscode-microprofile
124 | path: |
125 | vscode-microprofile-${{ env.EXT_VERSION }}-${{github.run_number}}.vsix
126 | if-no-files-found: error
127 | - name: Publish to GH Release Tab
128 | if: ${{ inputs.publishToMarketPlace == 'true' && inputs.publishToOVSX == 'true' }}
129 | uses: "marvinpinto/action-automatic-releases@919008cf3f741b179569b7a6fb4d8860689ab7f0"
130 | with:
131 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
132 | automatic_release_tag: "${{ env.EXT_VERSION }}"
133 | title: "${{ env.EXT_VERSION }}"
134 | draft: true
135 | files: |
136 | vscode-microprofile-${{ env.EXT_VERSION }}-${{ github.run_number }}.vsix
137 | release-job:
138 | environment: ${{ (inputs.publishToMarketPlace == 'true' || inputs.publishToOVSX == 'true') && 'release' || 'pre-release' }}
139 | runs-on: ubuntu-latest
140 | needs: packaging-job
141 | steps:
142 | - name: Set Up NodeJS
143 | uses: actions/setup-node@v4
144 | with:
145 | node-version: '20'
146 | - name: Install dependencies
147 | run: |
148 | npm install -g typescript "@vscode/vsce" "ovsx"
149 | - name: Download VSIX
150 | uses: actions/download-artifact@v4
151 | - name: Publish to VS Code Marketplace
152 | if: ${{ github.event_name == 'schedule' || inputs.publishToMarketPlace == 'true' || inputs.publishPreRelease == 'true' }}
153 | run: |
154 | vsce publish -p ${{ secrets.VSCODE_MARKETPLACE_TOKEN }} --packagePath vscode-microprofile/vscode-microprofile-*-${GITHUB_RUN_NUMBER}.vsix
155 | - name: Publish to OpenVSX Registry
156 | if: ${{ github.event_name == 'schedule' || inputs.publishToOVSX == 'true' || inputs.publishPreRelease == 'true' }}
157 | run: |
158 | ovsx publish -p ${{ secrets.OVSX_MARKETPLACE_TOKEN }} --packagePath vscode-microprofile/vscode-microprofile-*-${GITHUB_RUN_NUMBER}.vsix
159 | post-release-job:
160 | if: ${{ inputs.publishToMarketPlace == 'true' && inputs.publishToOVSX == 'true' }}
161 | runs-on: ubuntu-latest
162 | needs: release-job
163 | steps:
164 | - name: Check Out VS Code MicroProfile
165 | uses: actions/checkout@v4
166 | - name: Set Up NodeJS
167 | uses: actions/setup-node@v4
168 | with:
169 | node-version: '20'
170 | - name: Upversion for Development
171 | run: |
172 | tag=`npm version --no-git-tag-version patch`
173 | git config --global user.email "vscode-microprofile-bot@users.noreply.github.com"
174 | git config --global user.name "vscode-microprofile-bot"
175 | git commit -am "Upversion to ${tag#v}"
176 | git push origin
177 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 | on: [push, pull_request]
3 | jobs:
4 | tests:
5 | runs-on: ${{ matrix.os }}
6 | strategy:
7 | matrix:
8 | os: [macos-latest, ubuntu-latest, windows-latest]
9 | include:
10 | - os: macos-latest
11 | label: 'darwin'
12 | - os: ubuntu-latest
13 | label: 'linux'
14 | steps:
15 | - name: Check out repository code
16 | uses: actions/checkout@v2
17 | - uses: actions/setup-node@v2
18 | with:
19 | node-version: '18.15'
20 | - name: Install build tools
21 | run: npm i -g vsce
22 | - name: Install dependencies
23 | run: npm i
24 | - name: Compile extension
25 | run: npm run vscode:prepublish
26 | - run: vsce package
27 | - name: eslint
28 | run: npm run eslint
29 | - name: Tests
30 | run: xvfb-run --auto-servernum npm run test --silent
31 | if: runner.os == 'Linux'
32 | - name: Tests
33 | run: npm run test --slient
34 | if: runner.os != 'Linux'
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | test-resources
3 | dist
4 | server/**
5 | jars/**
6 | node_modules
7 | .vscode-test/
8 | *.vsix
9 | .DS_Store
10 |
11 |
--------------------------------------------------------------------------------
/.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 | "amodio.tsl-problem-matcher"
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 | "env": {
17 | "VSCODE_REDHAT_TELEMETRY_DEBUG": "true"
18 | },
19 | "outFiles": [
20 | "${workspaceFolder}/dist/**/*.js"
21 | ],
22 | "preLaunchTask": "npm: watch"
23 | },
24 | {
25 | "name": "Run Extension & Wait for remote debugger",
26 | "type": "extensionHost",
27 | "request": "launch",
28 | "runtimeExecutable": "${execPath}",
29 | "args": [
30 | "--extensionDevelopmentPath=${workspaceRoot}"
31 | ],
32 | "outFiles": [
33 | "${workspaceRoot}/dist/**/*.js"
34 | ],
35 | "preLaunchTask": "npm: watch",
36 | "env": {
37 | "SUSPEND_SERVER": "true"
38 | }
39 | },
40 | {
41 | "name": "Extension Tests",
42 | "type": "extensionHost",
43 | "request": "launch",
44 | "runtimeExecutable": "${execPath}",
45 | "args": [
46 | "--extensionDevelopmentPath=${workspaceFolder}",
47 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
48 | ],
49 | "outFiles": [
50 | "${workspaceFolder}/out/test/**/*.js"
51 | ],
52 | "preLaunchTask": "npm: pretest"
53 | }
54 | ]
55 | }
56 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true, // set this to false to include "out" folder in search results
8 | ".vscode-test": true,
9 | "dist": true,
10 | },
11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
12 | "typescript.tsc.autoDetect": "off"
13 | }
14 |
--------------------------------------------------------------------------------
/.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 | "problemMatcher": [
10 | "$ts-webpack-watch",
11 | "$eslint-stylish"
12 | ],
13 | "isBackground": true,
14 | "presentation": {
15 | "reveal": "never"
16 | },
17 | "group": {
18 | "kind": "build",
19 | "isDefault": true
20 | }
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .gitignore
3 | .travis.yml
4 | .vscode-test/
5 | node_modules/
6 | src/
7 | out/
8 | images/
9 | tsconfig.json
10 | webpack.config.js
11 | test-resources/**
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Tools for MicroProfile Changelog
2 |
3 | ## [0.14.0](https://github.com/redhat-developer/vscode-microprofile/milestone/15?closed=1) (April 22, 2025)
4 |
5 | ### Performance
6 | * Skip making a fake project if only sources are being scanned. See [eclipse-lsp4mp/lsp4mp#494](https://github.com/eclipse-lsp4mp/lsp4mp/pull/494).
7 |
8 | ### Bug Fixes
9 | * Do not suggest method or field snippets when the cursor is outside the top level type declaration. See [eclipse-lsp4mp/lsp4mp#476](https://github.com/eclipse-lsp4mp/lsp4mp/pull/476).
10 | * Guard against annotation binding failing to resolve. See [eclipse-lsp4mp/lsp4mp#492](https://github.com/eclipse-lsp4mp/lsp4mp/pull/492).
11 | * Fix cases where the JDT component would sometimes fail to find an inner class. See [eclipse-lsp4mp/lsp4mp#479](https://github.com/eclipse-lsp4mp/lsp4mp/pull/479), [#480](https://github.com/eclipse-lsp4mp/lsp4mp/pull/480).
12 |
13 | ## [0.13.0](https://github.com/redhat-developer/vscode-microprofile/milestone/14?closed=1) (October 22, 2024)
14 |
15 | ### Bug Fixes
16 |
17 | - Cannot publish to OpenVSX due to out of date NodeJS. See [#303](https://github.com/redhat-developer/vscode-microprofile/issues/303).
18 | - Codelens for REST endpoints should resolve variable references. See [lsp4mp#467](https://github.com/eclipse/lsp4mp/pull/467).
19 | - Prevent duplicate properties when generating them. See [lsp4mp#465](https://github.com/eclipse/lsp4mp/pull/465).
20 | - Prevent error on empty name symbol. See [lsp4mp#462](https://github.com/eclipse/lsp4mp/pull/462).
21 |
22 | ### Build
23 |
24 | - Bump webpack from 5.94.0 to 5.95.0. See [#296](https://github.com/redhat-developer/vscode-microprofile/pull/296).
25 | - Update vscode-redhat-telemetry to 0.9.0. See [#293](https://github.com/redhat-developer/vscode-microprofile/pull/293).
26 | - Update NodeJS in CD pipeline to NodeJS 20. See [#304](https://github.com/redhat-developer/vscode-microprofile/pull/304).
27 |
28 | ## [0.12.0](https://github.com/redhat-developer/vscode-microprofile/milestone/13?closed=1) (August 26, 2024)
29 |
30 | ### Enhancements
31 |
32 | - Resolve system properties/environment variables while browsing the application.properties values. See [eclipse/lsp4mp#448](https://github.com/eclipse/lsp4mp/issues/448).
33 | - Add support for @Startup healthcheck diagnostic. See [eclipse/lsp4mp#443](https://github.com/eclipse/lsp4mp/issues/443).
34 |
35 | ### Bug Fixes
36 |
37 | - NPE with Workspace Symbol when LSP client return null as SymbolInformation List. See [eclipse/lsp4mp#457](https://github.com/eclipse/lsp4mp/pull/457).
38 | - Unrecognized property mp.messaging.* when Channel annotation is used along with Multi. See [eclipse/lsp4mp#451](https://github.com/eclipse/lsp4mp/pull/451).
39 | - fix: synchronized projectLabels + collect codeLens when project is loaded. See [eclipse/lsp4mp#444](https://github.com/eclipse/lsp4mp/pull/444).
40 |
41 | ### Build
42 |
43 | - Set encoding as false for gulp.src to treat content as binary.. See [#209](https://github.com/redhat-developer/vscode-microprofile/pull/209).
44 | - Update eclipse.jdt.ls to 1.39.0-SNAPSHOT. See [eclipse/lsp4mp#454](https://github.com/eclipse/lsp4mp/pull/454).
45 | - Add About files to JDT extension bundles & Maven artifacts. See [eclipse/lsp4mp#437](https://github.com/eclipse/lsp4mp/pull/437).
46 | - Fix tests for release workflow. See [#185](https://github.com/redhat-developer/vscode-microprofile/pull/185).
47 |
48 | ## [0.11.0](https://github.com/redhat-developer/vscode-microprofile/milestone/12?closed=1) (February 1, 2024)
49 |
50 | ### Bug Fixes
51 |
52 | * Fixed `textDocument/documentSymbol` request failures when properties start with `.`. See [178](https://github.com/redhat-developer/vscode-microprofile/issues/178).
53 | * Fixed quick fixes not being applied. See [#171](https://github.com/redhat-developer/vscode-microprofile/issues/171).
54 | * Fixed broken properties completion. See [eclipse/lsp4mp#432](https://github.com/eclipse/lsp4mp/pull/432).
55 |
56 | ## [0.10.0](https://github.com/redhat-developer/vscode-microprofile/milestone/11?closed=1) (October 5, 2023)
57 |
58 | ### Bug Fixes
59 |
60 | * Properly handle `StackOverflowError` in `MicroProfileDelegateCommandHandler.getMicroProfileProjectInfo`. See [eclipse/lsp4mp#418](https://github.com/eclipse/lsp4mp/issues/418).
61 | * Fix `NullPointerException` in `TestJaxRsInfoProvider.canProvideJaxRsMethodInfoForClass`. See [eclipse/lsp4mp#424](https://github.com/eclipse/lsp4mp/issues/424).
62 | * Fix `canProvideJaxRsMethodInfoForClass` for default JAX-RS. See [eclipse/lsp4mp#420](https://github.com/eclipse/lsp4mp/pull/420).
63 |
64 | ## [0.9.0](https://github.com/redhat-developer/vscode-microprofile/milestone/10?closed=1) (August 8, 2023)
65 |
66 | ### Enhancements
67 |
68 | * Improve completion performance of `microprofile-config.properties` (remove unnecessary parameters in response). See [eclipse/lsp4mp#410](https://github.com/eclipse/lsp4mp/issues/410).
69 | * YAML support activation trigger should be more selective. See [#160](https://github.com/redhat-developer/vscode-microprofile/issues/160).
70 |
71 | ### Bug Fixes
72 |
73 | * Exception on "class extends XXX" autocompletion. See [#161](https://github.com/redhat-developer/vscode-microprofile/issues/161).
74 |
75 | ### Build
76 |
77 | * Bump semver from `5.7.1` to `5.7.2`. See [#162](https://github.com/redhat-developer/vscode-microprofile/pull/162).
78 | * Bump word-wrap from `1.2.3` to `1.2.4`. See [#164](https://github.com/redhat-developer/vscode-microprofile/pull/164).
79 |
80 | ## [0.8.0](https://github.com/redhat-developer/vscode-microprofile/milestone/8?closed=1) (June 15, 2023)
81 |
82 | ### Enhancements
83 |
84 | * Improve completion performance in properties files (resolve support, and item defaults). See [eclipse/lsp4mp#389](https://github.com/eclipse/lsp4mp/issues/389).
85 | * Warning for type declarations that are incorrectly annotated while their methods are annotated with `@Query`/`@Mutation`. See [eclipse/lsp4mp#355](https://github.com/eclipse/lsp4mp/issues/355).
86 |
87 | ## [0.7.1](https://github.com/redhat-developer/vscode-microprofile/milestone/9?closed=1) (April 12, 2023)
88 |
89 | ### Bug Fixes
90 |
91 | * Fix context-aware snippets in projects that use Project Lombok. See [#155](https://github.com/redhat-developer/vscode-microprofile/issues/155).
92 |
93 | ## [0.7.0](https://github.com/redhat-developer/vscode-microprofile/milestone/7?closed=1) (April 4, 2023)
94 |
95 | ### Enhancements
96 |
97 | * Validation for GraphQL `@Query` and `@Mutation` methods with `void` return type. See [eclipse/lsp4mp#348](https://github.com/eclipse/lsp4mp/issues/348), [eclipse/lsp4mp#359](https://github.com/eclipse/lsp4mp/issues/359).
98 | * Navigate to REST endpoints using workspace symbols. See [eclipse/lsp4mp#87](https://github.com/eclipse/lsp4mp/issues/87).
99 | * Validate lists in `@ConfigProperty`'s `defaultValue`. See [#143](https://github.com/redhat-developer/vscode-microprofile/issues/143).
100 | * Show config property documentation when hovering over the key in a properties file. See [#135](https://github.com/redhat-developer/vscode-microprofile/pull/135).
101 | * Make Java file snippets context-aware. See [eclipse/lsp4mp#108](https://github.com/eclipse/lsp4mp/issues/108).
102 | * Upgrade to vscode-languageclient 8.y.z. See [#146](https://github.com/redhat-developer/vscode-microprofile/issues/146).
103 | * Migrate from `find-java-home` to `jdk-utils`. See [#140](https://github.com/redhat-developer/vscode-microprofile/issues/140).
104 |
105 | ### Bug Fixes
106 |
107 | * Hover fails in properties files when the Java language server is loading. See [eclipse/lsp4mp#375](https://github.com/eclipse/lsp4mp/issues/375).
108 | * Definition sometimes fails on property values in a properties file. See [eclipse/lsp4mp#374](https://github.com/eclipse/lsp4mp/issues/374).
109 | * Adjust go to definition range for property keys to include the offset between the property key and `=`. See [redhat-developer/quarkus-ls#323](https://github.com/redhat-developer/quarkus-ls/issues/323).
110 | * Fix `NullPointerException` during go to definition in properties files. See [eclipse/lsp4mp#372](https://github.com/eclipse/lsp4mp/issues/372).
111 | * Fix `NullPointerException` on shutdown when LSP client doesn't define extendedClientCapabilities. See [eclipse/lsp4mp#363](https://github.com/eclipse/lsp4mp/pull/363).
112 | * Completion causes Exceptions when typing in a Java file. See [eclipse/lsp4mp#347](https://github.com/eclipse/lsp4mp/issues/347).
113 | * Support the `jakarta` namespace (JakartaEE 9+). See [eclipse/lsp4mp#344](https://github.com/eclipse/lsp4mp/issues/344).
114 | * Hovering over properties file fails with `NullPointerException` when there are multiple definitions of a property. See [eclipse/lsp4mp#341](https://github.com/eclipse/lsp4mp/issues/341).
115 | * `config_ordinal` appears as a property even in non-MicroProfile projects. See [eclipse/lsp4mp#312](https://github.com/eclipse/lsp4mp/issues/312).
116 | * Quick fix to assign a value to a property now handles the prefix set by `@ConfigProperties` properly. See [eclipse/lsp4mp#303](https://github.com/eclipse/lsp4mp/issues/303).
117 | * Change wording of "Unknown property" error message to "Unrecognized property". See [eclipse/lsp4mp#290](https://github.com/eclipse/lsp4mp/issues/290).
118 |
119 | ### Build
120 |
121 | * Use `vsce` from namespace `@vscode`. See [#141](https://github.com/redhat-developer/vscode-microprofile/pull/141).
122 |
123 | ## [0.6.0](https://github.com/redhat-developer/vscode-microprofile/milestone/6?closed=1) (December 1, 2022)
124 |
125 | ### Enhancements
126 |
127 | * Display property value as inlay hint. See [#108](https://github.com/redhat-developer/vscode-microprofile/pull/108).
128 | * Property evaluation should support the environment variable default value notation. See [eclipse/lsp4mp#241](https://github.com/eclipse/lsp4mp/issues/241).
129 | * Manage static properties using a `staticProvider` extension point. See [eclipse/lsp4mp#44](https://github.com/eclipse/lsp4mp/issues/44).
130 | * Improve code action performance with `CodeAction#data` & `resolveCodeAction`. See [#124](https://github.com/redhat-developer/vscode-microprofile/pull/124), [eclipse/lsp4mp#171](https://github.com/eclipse/lsp4mp/issues/171).
131 | * Diagnostics for mp-reactive-messaging `@Incoming`/`@Outgoing` annotation. See [eclipse/lsp4mp#58](https://github.com/eclipse/lsp4mp/issues/58).
132 | * Only activate extension if Java project is present. See [#114](https://github.com/redhat-developer/vscode-microprofile/issues/114).
133 |
134 | ### Bug Fixes
135 |
136 | * Don't throw an error popup when MicroProfile LS cancels the inlay hint process. See [#123](https://github.com/redhat-developer/vscode-microprofile/pull/123).
137 | * Java source code not validated upon start. See [eclipse/lsp4mp#301](https://github.com/eclipse/lsp4mp/issues/301).
138 | * `ClassCastException` thrown (and caught) when using invalid `@ConfigProperty` default value. See [eclipse/lsp4mp#295](https://github.com/eclipse/lsp4mp/issues/295).
139 | * Improve handling of `@ConfigProperties` for validation. See [eclipse/lsp4mp#304](https://github.com/eclipse/lsp4mp/issues/304).
140 | * Support for the `config_ordinal` property in `microprofile-config.properties`. See [eclipse/lsp4mp#289](https://github.com/eclipse/lsp4mp/issues/289).
141 | * Display property value when hovering over a key that isn't defined in the application. See [eclipse/lsp4mp#285](https://github.com/eclipse/lsp4mp/issues/285).
142 | * REST client code lens only shows up for `GET` annotations. See [eclipse/lsp4mp#94](https://github.com/eclipse/lsp4mp/issues/94).
143 | * JAXRS code lens URL should always appear above method declaration. See [eclipse/lsp4mp#194](https://github.com/eclipse/lsp4mp/issues/194).
144 | * Support `microprofile-health` 3.0 and later. See [eclipse/lsp4mp#314](https://github.com/eclipse/lsp4mp/issues/314).
145 | * Make `microprofile.tools.server.vmargs` setting application scoped. See [#121](https://github.com/redhat-developer/vscode-microprofile/pull/121).
146 | * Disable JVM logging to avoid language server failure. See [#118](https://github.com/redhat-developer/vscode-microprofile/issues/118).
147 | * Fix inlay hints & definitions when project returns empty properties. See [eclipse/lsp4mp#311](https://github.com/eclipse/lsp4mp/pull/311).
148 | * Fix code lens when no configuration sources available. See [eclipse/lsp4mp#315](https://github.com/eclipse/lsp4mp/issues/315).
149 | * `@ConfigProperties` validation should check the annotation's fully qualified name. See [eclipse/lsp4mp#304](https://github.com/eclipse/lsp4mp/issues/304).
150 | * Fix typo in `mpirc` snippet. See [eclipse/lsp4mp#325](https://github.com/eclipse/lsp4mp/issues/325).
151 |
152 | ### Build
153 |
154 | * Add support for pre-releases. See [#113](https://github.com/redhat-developer/vscode-microprofile/pull/113).
155 | * Update node in CI and CD to 14. See [#106](https://github.com/redhat-developer/vscode-microprofile/pull/106).
156 | * Update Jenkinsfile to use Java 17. See [#111](https://github.com/redhat-developer/vscode-microprofile/pull/111).
157 | * Update vscode-redhat-telemetry to 0.5.2. See [#131](https://github.com/redhat-developer/vscode-microprofile/pull/131).
158 | * Update Target Platform to 1.16.0-SNAPSHOT version of JDT-LS target. See [eclipse/lsp4mp#288](https://github.com/eclipse/lsp4mp/pull/288).
159 | * JDT.LS dependency on tests should be optional. See [eclipse/lsp4mp#286](https://github.com/eclipse/lsp4mp/issues/286).
160 | * Copy over `ModelTextDocuments#computeModelAsyncCompose` from quarkus-ls into commons package. See [eclipse/lsp4mp#257](https://github.com/eclipse/lsp4mp/issues/257).
161 | * Move VS Code workspace configuration into correct folder. See [eclipse/lsp4mp#145](https://github.com/eclipse/lsp4mp/pull/145).
162 |
163 | ## [0.5.0](https://github.com/redhat-developer/vscode-microprofile/milestone/5?closed=1) (July 25, 2022)
164 |
165 | ### Enhancements
166 |
167 | * Colorize profile part in properties. See [#96](https://github.com/redhat-developer/vscode-microprofile/issues/96).
168 | * Added textmate grammar support for property expressions. See [#95](https://github.com/redhat-developer/vscode-microprofile/pull/95).
169 | * Delay revalidation and handle validation cancellation correctly. See [eclipse/lsp4mp#252](https://github.com/eclipse/lsp4mp/pull/252).
170 | * Property file with property expressions (without default value) are flagged as wrong. See [eclipse/lsp4mp#225](https://github.com/eclipse/lsp4mp/issues/225), [eclipse/lsp4mp#227](https://github.com/eclipse/lsp4mp/issues/227).
171 | * Improved MicroProfile property value expression diagnostic message. See [eclipse/lsp4mp#242](https://github.com/eclipse/lsp4mp/pull/242).
172 |
173 | ### Bug Fixes
174 |
175 | * Language Server attempts to calculate code actions for stale diagnostics. See [eclipse/lsp4mp#272](https://github.com/eclipse/lsp4mp/issues/272).
176 | * Hovering property value fails with NPE. See [eclipse/lsp4mp#265](https://github.com/eclipse/lsp4mp/issues/265).
177 | * Completing property name with existing value will replace current value with default value. See [eclipse/lsp4mp#264](https://github.com/eclipse/lsp4mp/issues/264).
178 | * Empty completion when completion is triggered before the assign `=`. See [eclipse/lsp4mp#255](https://github.com/eclipse/lsp4mp/issues/255).
179 | * Improve validation by handling some known corner cases. [eclipse/lsp4mp#249](https://github.com/eclipse/lsp4mp/issues/249), [eclipse/lsp4mp#235](https://github.com/eclipse/lsp4mp/issues/235), [eclipse/lsp4mp#233](https://github.com/eclipse/lsp4mp/issues/233), [eclipse/lsp4mp#232](https://github.com/eclipse/lsp4mp/issues/232), [eclipse/lsp4mp#228](https://github.com/eclipse/lsp4mp/issues/228).
180 |
181 | ### Build
182 |
183 | * Bump terser from 5.6.1 to 5.14.2. See [#102](https://github.com/redhat-developer/vscode-microprofile/pull/102).
184 | * Remove ejs dependency. See [#97](https://github.com/redhat-developer/vscode-microprofile/pull/97).
185 |
186 | ### Documentation
187 |
188 | * Add DCO information to `CONTRIBUTING.md`. See [#99](https://github.com/redhat-developer/vscode-microprofile/issues/99).
189 |
190 |
191 | ## [0.4.0](https://github.com/redhat-developer/vscode-microprofile/milestone/4?closed=1) (March 24, 2022)
192 |
193 | ### Enhancements
194 |
195 | * Support validation and code actions for `@ConfigProperty`. See [eclipse/lsp4mp#90](https://github.com/eclipse/lsp4mp/issues/90), [eclipse/lsp4mp#176](https://github.com/eclipse/lsp4mp/issues/176) and [eclipse/lsp4mp#147](https://github.com/eclipse/lsp4mp/issues/147).
196 | * Completion for properties defined using `@ConfigProperties`. See [eclipse/lsp4mp#80](https://github.com/eclipse/lsp4mp/issues/80).
197 | * Support validation for `@Retry` annotation and its member values. See [eclipse/lsp4mp#191](https://github.com/eclipse/lsp4mp/pull/191) and [eclipse/lsp4mp#196](https://github.com/eclipse/lsp4mp/issues/196).
198 | * Diagnostics for `@Asynchronous`, `@Bulkhead` & `@Timeout` annotations. See [eclipse/lsp4mp#74](https://github.com/eclipse/lsp4mp/issues/74), [eclipse/lsp4mp#184](https://github.com/eclipse/lsp4mp/pull/184), [eclipse/lsp4mp#185](https://github.com/eclipse/lsp4mp/pull/185).
199 | * Support the `@ApplicationPath` annotation to handle the project URL. See [eclipse/lsp4mp#179](https://github.com/eclipse/lsp4mp/issues/179).
200 | * Diagnostics for invalid annotation parameter values. See [eclipse/lsp4mp#77](https://github.com/eclipse/lsp4mp/issues/77).
201 | * Reference only property declared in properties file in property expression. See [eclipse/lsp4mp#205](https://github.com/eclipse/lsp4mp/issues/205).
202 | * Support for default value inside properties expression. See [eclipse/lsp4mp#201](https://github.com/eclipse/lsp4mp/issues/201).
203 | * Use redhat.java embedded JRE to launch the MicroProfile language server. See [#84](https://github.com/redhat-developer/vscode-microprofile/issues/84).
204 | * Add settings and code action to ignore unassigned property warnings. See [#65](https://github.com/redhat-developer/vscode-microprofile/pull/65) and [eclipse/lsp4mp#187](https://github.com/eclipse/lsp4mp/pull/187).
205 | * Binary dynamic properties should be generated after an update. See [eclipse/lsp4mp#159](https://github.com/eclipse/lsp4mp/pull/159).
206 | * Support for config profiles. See [#73](https://github.com/redhat-developer/vscode-microprofile/pull/73).
207 |
208 | ### Bug Fixes
209 |
210 | * Provide API to configure root path of JAX RS resources. See [eclipse/lsp4mp#174](https://github.com/eclipse/lsp4mp/pull/174).
211 | * Fix bug with missing definition hover for multiple annotation members. See [eclipse/lsp4mp#216](https://github.com/eclipse/lsp4mp/pull/216).
212 | * Support optional property reference hover for annotation members. See [eclipse/lsp4mp#211](https://github.com/eclipse/lsp4mp/pull/211).
213 | * Do not rebuild list of configuration properties when MicroProfile config sources are updated in the build directory. See [eclipse/lsp4mp#162](https://github.com/eclipse/lsp4mp/issues/162).
214 | * Deadlock when client is sending burst of request. See [eclipse/lsp4mp#177](https://github.com/eclipse/lsp4mp/issues/177).
215 | * Exclude the method that's being annotated when showing completion for fallback method. See [eclipse/lsp4mp#148](https://github.com/eclipse/lsp4mp/issues/148).
216 | * SingleMemberAnnotation diagnostics not supported by annotationValidator. See [eclipse/lsp4mp#188](https://github.com/eclipse/lsp4mp/issues/188).
217 | * Add 'shouldLanguageServerExitOnShutdown' to ExtendedClientCapabilities. See [eclipse/lsp4mp#172](https://github.com/eclipse/lsp4mp/pull/172).
218 | * Update find-java-home to correctly detect java binary where it is symbolically linked. See [#81](https://github.com/redhat-developer/vscode-microprofile/issues/81).
219 |
220 | ### Build
221 |
222 | * Use ovsx<0.3.0 to ensure we build with Node v12. See [#87](https://github.com/redhat-developer/vscode-microprofile/pull/87).
223 |
224 | ### Other
225 |
226 | * Add features documentation for properties/java files. See [#64](https://github.com/redhat-developer/vscode-microprofile/issues/64).
227 | * Move to vscode-languageclient 7.0.0. See [#68](https://github.com/redhat-developer/vscode-microprofile/pull/68).
228 | * Add support for `shouldServerExitOnShutdown` capability. See [#69](https://github.com/redhat-developer/vscode-microprofile/issues/69).
229 | * Update vscode-redhat-telemetry to 0.4.2. See [#74](https://github.com/redhat-developer/vscode-microprofile/pull/74).
230 | * Update follow-redirects and mocha. See [#86](https://github.com/redhat-developer/vscode-microprofile/pull/86).
231 |
232 | ## [0.3.0](https://github.com/redhat-developer/vscode-microprofile/milestone/3?closed=1) (July 22, 2021)
233 |
234 | ### Enhancements
235 |
236 | * Completion for `fallbackMethod` in `@Fallback` annotation. See [eclipse/lsp4mp#34](https://github.com/eclipse/lsp4mp/issues/34).
237 | * Remove dependency on vscode-commons. See [#55](https://github.com/redhat-developer/vscode-microprofile/issues/55).
238 |
239 | ### Build
240 |
241 | * Migrate to eslint from tslint. See [#53](https://github.com/redhat-developer/vscode-microprofile/issues/53).
242 | * Use registry.npmjs.com in `package-lock.json`. See [#50](https://github.com/redhat-developer/vscode-microprofile/pull/50).
243 | * Migrate to GitHub Actions from travis-ci.org. See [#59](https://github.com/redhat-developer/vscode-microprofile/issues/59).
244 |
245 | ## [0.2.0](https://github.com/redhat-developer/vscode-microprofile/milestone/2?closed=1) (April 7, 2021)
246 |
247 | ### Enhancements
248 |
249 | * Support arbitrary number of member values in `PropertiesHoverParticipant`. See [eclipse/lsp4mp#124](https://github.com/eclipse/lsp4mp/pull/124).
250 | * Add extension point to contribute properties to exclude from validation. See [eclipse/lsp4mp#95](https://github.com/eclipse/lsp4mp/issues/95).
251 | * Definition support from Java to properties for `ConfigProperty/name`. See [eclipse/lsp4mp#88](https://github.com/eclipse/lsp4mp/issues/88).
252 | * Automatically infer package names when inserting class snippets. See [eclipse/lsp4mp#60](https://github.com/eclipse/lsp4mp/issues/60).
253 | * Support `handle-as` for metadata properties. See [eclipse/lsp4mp#39](https://github.com/eclipse/lsp4mp/issues/39).
254 | * Display the different values for the different profiles in Java `@ConfigProperty` Hover. See [eclipse/lsp4mp#98](https://github.com/eclipse/lsp4mp/issues/98).
255 | * Add startup and shutdown telemetry. See [#46](https://github.com/redhat-developer/vscode-microprofile/issues/46)
256 |
257 | ### Bug Fixes
258 |
259 | * Wait for the language server to stop before exiting. See [#39](https://github.com/redhat-developer/vscode-microprofile/issues/39).
260 | * Trailing tab causes infinite loop in parser. See [eclipse/lsp4mp#112](https://github.com/eclipse/lsp4mp/issues/112).
261 | * Prevent NPEs when working with MP 4.0 features. See [eclipse/lsp4mp#119](https://github.com/eclipse/lsp4mp/issues/119).
262 | * Enhance the error message when out of bounds is detected. See [eclipse/lsp4mp#114](https://github.com/eclipse/lsp4mp/pull/114).
263 | * Use `kill -0` instead of `ps -p` in `ParentProcessWatcher`. See [eclipse/lsp4mp#110](https://github.com/eclipse/lsp4mp/issues/110).
264 | * Wrong/Missing Log Levels in property files. See [eclipse/lsp4mp#15](https://github.com/eclipse/lsp4mp/pull/105).
265 | * `mp.messaging` properties now work for Emitters. See [eclipse/lsp4mp#127](https://github.com/eclipse/lsp4mp/pull/127).
266 |
267 | ## [0.1.1] (September 23, 2020)
268 | * Update name to "Tools for MicroProfile". See [#23](https://github.com/redhat-developer/vscode-microprofile/issues/23)
269 |
270 | ## [0.1.0](https://github.com/redhat-developer/vscode-microprofile/milestone/1?closed=1) (September 21, 2020)
271 |
272 | ### Enhancements
273 |
274 | * Add new setting for property expression validation. See [#18](https://github.com/redhat-developer/vscode-microprofile/pull/18).
275 | * Update extension displayName to MicroProfile Tools. See [#9](https://github.com/redhat-developer/vscode-microprofile/pull/9).
276 | * Remove quarkus-properties language and collect document selectors from extensions. See [#8](https://github.com/redhat-developer/vscode-microprofile/pull/8).
277 | * Java snippets for `microprofile rest client`. See [lsp4mp#55](https://github.com/eclipse/lsp4mp/issues/55).
278 | * CDI scope diagnostics for `mp metrics @Gauge`. See [lsp4mp#46](https://github.com/eclipse/lsp4mp/issues/46).
279 | * Highlight support for property expression. See [lsp4mp#40](https://github.com/eclipse/lsp4mp/issues/40).
280 | * Diagnostics for ` mp-fault-tolerance fallbackMethod` . See [lsp4mp#33](https://github.com/eclipse/lsp4mp/issues/33).
281 | * Java `snippets for jax-rs`. See [lsp4mp#31](https://github.com/eclipse/lsp4mp/issues/31).
282 | * Snippets for new `microprofile health liveness / readiness checks`. See [lsp4mp#28](https://github.com/eclipse/lsp4mp/issues/28).
283 | * Properties support for `microprofile-graphql`. See [lsp4mp#27](https://github.com/eclipse/lsp4mp/issues/27).
284 | * Properties support for `microprofile-reactive-messaging`. See [lsp4mp#26](https://github.com/eclipse/lsp4mp/issues/26).
285 | * Hover for Property Expressions. See [lsp4mp#24](https://github.com/eclipse/lsp4mp/issues/24).
286 | * Properties support for microprofile-jwt-auth. See [lsp4mp#23](https://github.com/eclipse/lsp4mp/issues/23).
287 | * Property expression validation. See [lsp4mp#21](https://github.com/eclipse/lsp4mp/pull/21).
288 | * Property expression definition. See [lsp4mp#19](https://github.com/eclipse/lsp4mp/pull/19).
289 | * Hardcoded support for boolean converter. See [lsp4mp#17](https://github.com/eclipse/lsp4mp/pull/17).
290 | * Properties support for `microprofile-health`. See [lsp4mp#16](https://github.com/eclipse/lsp4mp/issues/16).
291 | * Model and completion for property expressions. See [lsp4mp#13](https://github.com/eclipse/lsp4mp/pull/13).
292 |
293 | ### Bug Fixes
294 |
295 | * Ensure language server is stopped when extension is deactivated. See [#16](https://github.com/redhat-developer/vscode-microprofile/pull/16).
296 | * Ensure microprofile ls process is terminated on deactivate. See [#15](https://github.com/redhat-developer/vscode-microprofile/issues/15).
297 | * Detect lightweight java language server. See [#14](https://github.com/redhat-developer/vscode-microprofile/pull/14).
298 | * NPE during completion when Java language server is started in LightWeight mode. See [#12](https://github.com/redhat-developer/vscode-microprofile/issues/12).
299 | * Allow `[`, `]`, and `#` in property keys TextMate grammar. See [#11](https://github.com/redhat-developer/vscode-microprofile/pull/11).
300 | * NullPointerException with symbols. See [lsp4mp#66](https://github.com/eclipse/lsp4mp/issues/66).
301 | * Fix duplicate of `quarkus-properties` when registering `textDocument/rangeFormatting`. See [lsp4mp#52](https://github.com/eclipse/lsp4mp/pull/52).
302 | * Rename settings prefix to microprofile. See [lsp4mp#51](https://github.com/eclipse/lsp4mp/pull/51).
303 | * Fix missing unit in Gauge metrics snippet. See [lsp4mp#47](https://github.com/eclipse/lsp4mp/pull/47).
304 | * Escape special characters within LSP snippets. See [lsp4mp#29](https://github.com/eclipse/lsp4mp/pull/29).
305 | * Completion in properties file gives enum values before `=`. See [lsp4mp#14](https://github.com/eclipse/lsp4mp/issues/14).
306 |
307 | ### Build
308 |
309 | * Setup CI. See [#4](https://github.com/redhat-developer/vscode-microprofile/issues/4).
310 |
311 | ### Other
312 |
313 | * Add gitter link to readme. See [#20](https://github.com/redhat-developer/vscode-microprofile/pull/20).
314 | * Fix missing space in switch java mode prompt. See [#17](https://github.com/redhat-developer/vscode-microprofile/pull/17).
315 | * Document external lsp4mp extensions. See [#13](https://github.com/redhat-developer/vscode-microprofile/pull/13).
316 | * Update contributing guide. See [#10](https://github.com/redhat-developer/vscode-microprofile/pull/10).
317 | * Test collecting lsp4mp extensions. See [#7](https://github.com/redhat-developer/vscode-microprofile/pull/7).
318 | * Add badges. See [#6](https://github.com/redhat-developer/vscode-microprofile/pull/6).
319 | * Apache 2.0 License. See [#5](https://github.com/redhat-developer/vscode-microprofile/pull/5).
320 | * Remove quarkus-properties language. See [#3](https://github.com/redhat-developer/vscode-microprofile/issues/3).
321 | * Update contributing guide. See [#2](https://github.com/redhat-developer/vscode-microprofile/issues/2).
322 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guide
2 |
3 | Contributions are extremely welcome, no matter how big or small.
4 | If you have any questions or suggestions we are happy to hear them.
5 |
6 | # Table of Contents
7 | 1. [Project Structure](#project-structure)
8 | 2. [Implementing language features for `microprofile-config.properties`](#implementing-language-features-for-microprofile-configproperties)
9 | 3. [Implementing language features for Java files](#implementing-language-features-for-java-files)
10 | 4. [Development Setup](#development-setup)
11 | 1. [Installation Prerequisites](#installation-prerequisites)
12 | 2. [Setup](#setup)
13 | 3. [Running vscode-microprofile](#running-vscode-microprofile)
14 | 4. [Testing vscode-microprofile](#testing-vscode-microprofile)
15 | 5. [Debugging](#debugging)
16 | 1. [Debugging the MicroProfile language server](#debugging-the-microprofile-language-server)
17 | 2. [Debugging the MicroProfile jdt.ls extension](#debugging-the-microprofile-jdtls-extension)
18 |
19 | ## Project Structure
20 | For vscode-microprofile to work, it relies on the
21 | [MicroProfile language server](https://github.com/eclipse/lsp4mp/tree/master/microprofile.ls)
22 | and the
23 | [MicroProfile jdt.ls extension](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt).
24 | The MicroProfile language server is responsible for providing
25 | [LSP language features](https://microsoft.github.io/language-server-protocol/specification)
26 | to VSCode, while the MicroProfile jdt.ls extension is responsible
27 | for functionalities like listening
28 | to Java classpath changes and generating config setting metadata for
29 | the `microprofile-config.properties` file.
30 | The reason why
31 | [vscode-java](https://github.com/redhat-developer/vscode-java)
32 | is required for vscode-microprofile to work, is because vscode-java
33 | starts the [jdt.ls](https://github.com/eclipse/eclipse.jdt.ls)
34 | language server, which is required to run the MicroProfile jdt.ls extension.
35 |
36 | **Note**: The MicroProfile language server provides language features for both `microprofile-config.properties` and `*.java` files.
37 |
38 | 
39 | The image above represents communication between the three components.
40 | As the image implies, the MicroProfile language server cannot directly
41 | communicate with the MicroProfile jdt.ls extension and vice-versa. They must
42 | communicate via vscode-microprofile.
43 |
44 | Here is an example of how the components work together for
45 | `microprofile-config.properties` completion:
46 |
47 | **Step 1.** A MicroProfile project is opened in VSCode, and completion has been
48 | invoked inside the `microprofile-config.properties` file. VSCode sends a
49 | `textDocument/completion` request to the MicroProfile language server.
50 |
51 | **Step 2.** MicroProfile language server checks its cache if completion options
52 | exist.
53 | * If the cache holds completion options, the MicroProfile language server sends them to VSCode
54 | as the response to the `textDocument/completion` request.
55 | Communication is complete, and does not proceed to Step 3
56 | and onwards.
57 | * If completion options are not cached, the MicroProfile language server sends a
58 | custom request, `microprofile/projectInfo` to vscode-microprofile.
59 | Proceed to Step 3.
60 |
61 | **Step 3.** vscode-microprofile receives the `microprofile/projectInfo` request,
62 | and delegates it to the MicroProfile jdt.ls extension.
63 |
64 | **Step 4.** The MicroProfile jdt.ls extension receives the command, determines
65 | [project information](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/commons/MicroProfileProjectInfo.java)
66 | (project URI, configuration properties, hints etc.)
67 | about the currently opened MicroProfile project and returns
68 | the information to vscode-microprofile. The project information is then sent to
69 | the MicroProfile language server
70 |
71 | **Step 5.** vscode-microprofile receives the project information and sends it
72 | to the MicroProfile language server.
73 |
74 | **Step 6.** MicroProfile language server receives the information, adds it
75 | to its cache, and returns the completion options stored in the
76 | project information as the response to the `textDocument/completion`
77 | request.
78 |
79 | ## Implementing language features for `microprofile-config.properties`
80 | When a `microprofile-config.properties` file sends a request (e.g. textDocument/completion) to the
81 | MicroProfile language server, the requests are accepted in
82 | [ApplicationPropertiesTextDocumentService#completion](https://github.com/eclipse/lsp4mp/tree/master/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/ApplicationPropertiesTextDocumentService.java#L150).
83 | This class receives LSP requests for `microprofile-config.properties` files.
84 |
85 | Properties collected by the MicroProfile jdt.ls extension are cached to keep response times
86 | fast.
87 | Collecting properties will not be done unless absolutely necessary
88 | (ie, if cache doesn't exist, if project dependencies change).
89 |
90 | When the completion is triggered,
91 | the MicroProfile LS checks the properties cache for the given `microprofile-config.properties` file.
92 | If the cache does not exist, it calls the `microprofile/projectInfo` request to call the JDT LS Extension [projectInfo delegate command handler](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/core/ls/MicroProfileDelegateCommandHandler.java#L71) which
93 | uses the
94 | [properties manager](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/core/PropertiesManager.java)
95 | that collects MicroProfile properties for the given Java project.
96 |
97 | This manager is extensible by the
98 | `org.eclipse.lsp4mp.jdt.core.propertiesProviders`
99 | [extension point](https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/plugin.xml#L5):
100 |
101 | * [org.eclipse.lsp4mp.jdt.core](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/plugin.xml#L49-L52) defines properties provider for MicroProfile.
102 |
103 | Here are some providers for MicroProfile projects and the annotation(s) they scan for:
104 |
105 | | Class | Annotations |
106 | |-------|-------------|
107 | | [MicroProfileConfigPropertyProvider](https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/config/properties/MicroProfileConfigPropertyProvider.java) | org.eclipse.microprofile.config.inject.ConfigProperty |
108 | | [MicroProfileRegisterRestClientProvider](https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/restclient/properties/MicroProfileRegisterRestClientProvider.java) | org.eclipse.microprofile.rest.client.inject.RegisterRestClient |
109 |
110 | The microprofile.jdt can also be extended to provide additional property providers.
111 |
112 | * For example: [com.redhat.microprofile.jdt.quarkus](https://github.com/redhat-developer/quarkus-ls/tree/master/quarkus.jdt.ext/com.redhat.microprofile.jdt.quarkus/plugin.xml#L5-L10) defines properties providers that scan for additional annotations for Quarkus which is used by [vscode-quarkus](https://github.com/redhat-developer/vscode-quarkus) to extend vscode-microprofile.
113 |
114 |
115 | | Class | Annotations |
116 | |-------|-------------|
117 | | [QuarkusConfigPropertiesProvider](https://github.com/redhat-developer/quarkus-ls/tree/master/quarkus.jdt.ext/com.redhat.microprofile.jdt.quarkus/src/main/java/com/redhat/microprofile/jdt/internal/quarkus/providers/QuarkusConfigPropertiesProvider.java) | io.quarkus.arc.config.ConfigProperties |
118 | | [QuarkusConfigRootProvider](https://github.com/redhat-developer/quarkus-ls/tree/master/quarkus.jdt.ext/com.redhat.microprofile.jdt.quarkus/src/main/java/com/redhat/microprofile/jdt/internal/quarkus/providers/QuarkusConfigRootProvider.java) | io.quarkus.runtime.annotations.ConfigRoot |
119 | | [QuarkusKubernetesProvider](https://github.com/redhat-developer/quarkus-ls/tree/master/quarkus.jdt.ext/com.redhat.microprofile.jdt.quarkus/src/main/java/com/redhat/microprofile/jdt/internal/quarkus/providers/QuarkusKubernetesProvider.java) | io.dekorate.kubernetes.annotation.KubernetesApplication
io.dekorate.openshift.annotation.OpenshiftApplication
io.dekorate.s2i.annotation.S2iBuild
io.dekorate.docker.annotation.DockerBuild |
120 |
121 |
122 | ### Searching for properties in JARs not in the user's project's classpath
123 |
124 | It is also possible to search for properties in JARs not on the classpath. For an example of how the quarkus extension to microprofile.jdt does this you can look at the [vscode-quarkus CONTRIBUTING.md](https://github.com/redhat-developer/vscode-quarkus/blob/master/CONTRIBUTING.md#searching-for-properties-in-jars-not-in-the-users-quarkus-projects-classpath)
125 |
126 | ## Implementing language features for Java files
127 | When a Java file sends a request (e.g. `textDocument/codeLens`) to the
128 | MicroProfile language server, the requests are accepted in
129 | [JavaTextDocumentService#completion](https://github.com/eclipse/lsp4mp/blob/master/microprofile.ls/org.eclipse.lsp4mp.ls/src/main/java/org/eclipse/lsp4mp/ls/JavaTextDocumentService.java#L111).
130 | This class receives LSP requests for Java files.
131 |
132 | The `textDocument/codeLens`, `textDocument/publishDiagnostics`, `textDocument/hover` requests are delegated to
133 | [`MicroProfileDelegateCommandHandlerForJava`](https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/core/ls/MicroProfileDelegateCommandHandlerForJava.java) which creates the `lsp4j.Hover`,
134 | `lsp4j.CodeLens` and `lsp4j.PublishDiagnosticsParams` instances for hover, codelens and diagnostics respectively.
135 |
136 | Just like how `microprofile-config.properties` properties are extensible via extension point, Java codeLens, diagnostics and
137 | hover are also extensible via extension point.
138 |
139 | These Java features are extensible by the
140 | `org.eclipse.lsp4mp.jdt.core.javaFeatureParticipants`
141 | [extension point](https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/plugin.xml#L8):
142 |
143 | * [org.eclipse.lsp4mp.jdt.core](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/plugin.xml#L54-L57) defines Java feature participants for MicroProfile.
144 |
145 | Here are some examples of the leveraging the extension point to provide Java codeLens, diagnostics and hover:
146 | | Java Feature | Participant |
147 | |-----------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
148 | | MicroProfile Health diagnostics | [MicroProfileHealthDiagnosticsParticipant ](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/health/java/MicroProfileHealthDiagnosticsParticipant.java ) |
149 | | MicroProfile Rest Client diagnostics | [MicroProfileRestClientDiagnosticsParticipant ](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/restclient/java/MicroProfileRestClientDiagnosticsParticipant.java ) |
150 | | MicroProfile Rest Client codeLens | [MicroProfileRestClientCodeLensParticipant](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/restclient/java/MicroProfileRestClientCodeLensParticipant.java) |
151 | | JAX-RS codelens | [JaxRsCodeLensParticipant ](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/jaxrs/java/JaxRsCodeLensParticipant.java ) |
152 | | MicroProfile `@ConfigProperty` name hover | [MicroProfileConfigHoverParticipant ](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/config/java/MicroProfileConfigHoverParticipant.java ) |
153 |
154 |
155 | Similar to properties files, the microprofile.jdt Java feature participants can be extended to provide additionally functionality. For example [com.redhat.microprofile.jdt.quarkus](https://github.com/redhat-developer/quarkus-ls/blob/master/quarkus.jdt.ext/com.redhat.microprofile.jdt.quarkus/plugin.xml#L18-L21) defines Java feature participants for Quarkus.
156 |
157 | ## Development Setup
158 |
159 | ### Installation Prerequisites
160 |
161 | * [Visual Studio Code](https://code.visualstudio.com/)
162 | * [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java)
163 | * [Node.js](https://nodejs.org/en/)
164 | * [JDK 21+](https://adoptopenjdk.net/)
165 |
166 | ### Setup
167 | **Step 1.** Fork and clone this repository
168 |
169 | **Step 2.** Fork and clone the [lsp4mp repository](https://github.com/eclipse/lsp4mp), which
170 | contains the MicroProfile jdt.ls extension and MicroProfile language server
171 |
172 | **Note:** Ensure that the cloned repositories are under the same parent directory:
173 |
174 | ```
175 | YOUR_FOLDER/
176 | ├──── vscode-microprofile/
177 | ├──── lsp4mp/
178 | ```
179 |
180 | **Step 3.** Navigate into `vscode-microprofile/`
181 | ```bash
182 | $ cd vscode-microprofile/
183 | ```
184 | **Step 4.** Install npm dependencies
185 | ```bash
186 | $ npm install
187 | ```
188 |
189 | **Step 5.** Build the MicroProfile language server and MicroProfile jdt.ls extension
190 | ```bash
191 | $ npm run build
192 | ```
193 | This script does two things.
194 | 1. Builds the MicroProfile language server and places the jar in
195 | `vscode-microprofile/server/`.
196 | 2. Builds the MicroProfile jdt.ls extension and places the jar in
197 | `vscode-microprofile/jars/`.
198 |
199 | In addition to `npm run build`, there are two more build scripts:
200 | `npm run build-server` only builds the MicroProfile language server and places the jar in `vscode-microprofile/server/`.
201 | `npm run build-ext` only builds the MicroProfile jdt.ls extension and places the jar in `vscode-microprofile/jars/`.
202 |
203 | ### Running vscode-microprofile
204 | **Step 1.** Open `vscode-microprofile/` in VSCode.
205 |
206 | **Step 2.** Open the Run tab, select and run
207 | "Run Extension" at the top left.
208 | 
209 |
210 | ### Testing vscode-microprofile
211 |
212 | Run integration tests: `npm test`
213 |
214 | The tests are located in src/tests directory.
215 |
216 | ```
217 | vscode-microprofile/
218 | ├──── src/
219 | ├──── test/
220 | ```
221 |
222 | To debug the integration tests, open the VS Code Run tab and
223 | select the "Extension Tests" at the top left:
224 | 
225 |
226 | ## Debugging
227 | ### Debugging the MicroProfile language server:
228 | In an IDE of your choice, set the debugger configuration to connect
229 | to localhost, port 1064.
230 |
231 | If using VSCode, open `lsp4mp/microprofile.ls/` in VSCode. The proper
232 | debugger configurations are already defined in `.vscode/`.
233 | There should be a "Debug (Attach) - Remote" option
234 | at the top left of the Debugging tab.
235 | 
236 |
237 | The JVM arguments used to start the MicroProfile language
238 | server are specified
239 | [here](https://github.com/redhat-developer/vscode-microprofile/blob/master/src/languageServer/javaServerStarter.ts#L25).
240 |
241 | ### Debugging the MicroProfile jdt.ls extension:
242 | Only Eclipse can be used to debug the MicroProfile jdt.ls extension.
243 |
244 | **Step 1.** Open the jdt.ls source code in a new workspace in Eclipse by
245 | following the setup
246 | steps in the jdt.ls GitHub repository
247 | [here](https://github.com/eclipse/eclipse.jdt.ls#first-time-setup).
248 |
249 | **Step 2.** In the same workspace, import the projects from
250 | `lsp4mp/microprofile.jdt/`.
251 |
252 | **Step 3.** In the Debug dropdown menu, open "Debug Configurations...".
253 | 
254 |
255 | **Step 4.** Create a new "Remote Java Application" launch configuration.
256 | Set the following settings and click "Apply":
257 | ```
258 | Project: org.eclipse.lsp4mp.jdt.core
259 | Connection Type: Standard (Socket Attach)
260 | Host: localhost
261 | Port: 1044
262 | ```
263 | 
264 |
265 | ### Certificate of Origin
266 |
267 | By contributing to this project you agree to the Developer Certificate of
268 | Origin (DCO). This document was created by the Linux Kernel community and is a
269 | simple statement that you, as a contributor, have the legal right to make the
270 | contribution. See the [DCO](DCO) file for details.
271 |
--------------------------------------------------------------------------------
/DCO:
--------------------------------------------------------------------------------
1 | Developer Certificate of Origin
2 | Version 1.1
3 |
4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5 | 1 Letterman Drive
6 | Suite D4700
7 | San Francisco, CA, 94129
8 |
9 | Everyone is permitted to copy and distribute verbatim copies of this
10 | license document, but changing it is not allowed.
11 |
12 |
13 | Developer's Certificate of Origin 1.1
14 |
15 | By making a contribution to this project, I certify that:
16 |
17 | (a) The contribution was created in whole or in part by me and I
18 | have the right to submit it under the open source license
19 | indicated in the file; or
20 |
21 | (b) The contribution is based upon previous work that, to the best
22 | of my knowledge, is covered under an appropriate open source
23 | license and I have the right under that license to submit that
24 | work with modifications, whether created in whole or in part
25 | by me, under the same open source license (unless I am
26 | permitted to submit under a different license), as indicated
27 | in the file; or
28 |
29 | (c) The contribution was provided directly to me by some other
30 | person who certified (a), (b) or (c) and I have not modified
31 | it.
32 |
33 | (d) I understand and agree that this project and the contribution
34 | are public and that a record of the contribution (including all
35 | personal information I submit with it, including my sign-off) is
36 | maintained indefinitely and may be redistributed consistent with
37 | this project or the open source license(s) involved.
38 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env groovy
2 |
3 | node('rhel8'){
4 | stage('Checkout repos') {
5 | deleteDir()
6 | def hasLsp4mpDir = fileExists 'lsp4mp'
7 | if (!hasLsp4mpDir){
8 | sh 'mkdir lsp4mp'
9 | }
10 | dir ('lsp4mp') {
11 | echo "Checking out LSP4MP ${params.LSP4MP_TAG}"
12 | git url: 'https://github.com/eclipse/lsp4mp.git'
13 | sh "git checkout ${params.LSP4MP_TAG}"
14 | }
15 | def hasClientDir = fileExists 'vscode-microprofile'
16 | if (!hasClientDir) {
17 | sh 'mkdir vscode-microprofile'
18 | }
19 | dir ('vscode-microprofile') {
20 | git url: "https://github.com/${params.FORK}/vscode-microprofile.git"
21 | }
22 | }
23 |
24 | stage('Install requirements') {
25 | def nodeHome = tool 'nodejs-18.15.0'
26 | env.PATH="${env.PATH}:${nodeHome}/bin"
27 | sh 'npm install -g typescript'
28 | sh 'npm install -g -f "@vscode/vsce"'
29 | }
30 |
31 | stage('Build') {
32 | env.JAVA_HOME="${tool 'openjdk-17'}"
33 | env.PATH="${env.JAVA_HOME}/bin:${env.PATH}"
34 | dir ('vscode-microprofile') {
35 | sh "npm install --ignore-scripts"
36 | sh "npm install"
37 | sh "npm run build"
38 | sh "npm run vscode:prepublish"
39 | }
40 | }
41 |
42 | withEnv(['JUNIT_REPORT_PATH=report.xml']) {
43 | stage('Test') {
44 | wrap([$class: 'Xvnc']) {
45 | dir ('vscode-microprofile') {
46 | sh "npm test --silent"
47 | //junit 'report.xml'
48 | }
49 | }
50 | }
51 | }
52 |
53 | env.publishPreReleaseFlag = ""
54 | if(publishPreRelease.equals('true')){
55 | stage("Prepare for pre-release") {
56 | dir ('vscode-microprofile') {
57 | sh "npx gulp prepare_pre_release"
58 | env.publishPreReleaseFlag = "--pre-release"
59 | }
60 | }
61 | }
62 |
63 | stage('Package') {
64 | dir ('vscode-microprofile') {
65 | def packageJson = readJSON file: 'package.json'
66 | sh "vsce package ${env.publishPreReleaseFlag} -o ../vscode-microprofile-${packageJson.version}-${env.BUILD_NUMBER}.vsix"
67 | sh "npm pack && mv vscode-microprofile-${packageJson.version}.tgz ../vscode-microprofile-${packageJson.version}-${env.BUILD_NUMBER}.tgz"
68 | }
69 | }
70 |
71 | if(params.UPLOAD_LOCATION) {
72 | stage('Snapshot') {
73 | def filesToPush = findFiles(glob: '**.vsix')
74 | sh "sftp -C ${UPLOAD_LOCATION}/snapshots/vscode-microprofile/ <<< \$'put -p ${filesToPush[0].path}'"
75 | stash name:'vsix', includes:filesToPush[0].path
76 | def tgzFilesToPush = findFiles(glob: '**.tgz')
77 | stash name:'tgz', includes:tgzFilesToPush[0].path
78 | sh "sftp -C ${UPLOAD_LOCATION}/snapshots/vscode-microprofile/ <<< \$'put -p ${tgzFilesToPush[0].path}'"
79 | }
80 | }
81 |
82 | if('true'.equals(publishToMarketPlace) || 'true'.equals(publishToOVSX) || 'true'.equals(publishPreRelease)){
83 | if ('true'.equals(publishToMarketPlace) || 'true'.equals(publishToOVSX)) {
84 | timeout(time:5, unit:'DAYS') {
85 | input message:'Approve deployment?', submitter: 'fbricon,rgrunber,azerr,davthomp'
86 | }
87 | }
88 |
89 | stage("Publish to Marketplaces") {
90 | unstash 'vsix'
91 | unstash 'tgz'
92 | def vsix = findFiles(glob: '**.vsix')
93 |
94 | if ('true'.equals(publishToMarketPlace) || 'true'.equals(publishPreRelease)) {
95 | // VS Code Marketplace
96 | withCredentials([[$class: 'StringBinding', credentialsId: 'vscode_java_marketplace', variable: 'TOKEN']]) {
97 | sh 'vsce publish -p ${TOKEN} --packagePath' + " ${vsix[0].path}"
98 | }
99 | }
100 |
101 | if ('true'.equals(publishToOVSX)) {
102 | // open-vsx Marketplace
103 | sh 'npm install -g ovsx'
104 | withCredentials([[$class: 'StringBinding', credentialsId: 'open-vsx-access-token', variable: 'OVSX_TOKEN']]) {
105 | sh 'ovsx publish -p ${OVSX_TOKEN}' + " ${vsix[0].path}"
106 | }
107 | }
108 |
109 | archiveArtifacts artifacts:"**.vsix,**.tgz"
110 |
111 | if ('true'.equals(publishToMarketPlace)) {
112 | stage "Promote the build to stable"
113 | sh "sftp -C ${UPLOAD_LOCATION}/stable/vscode-microprofile/ <<< \$'put -p ${vsix[0].path}'"
114 | def tgz = findFiles(glob: '**.tgz')
115 | sh "sftp -C ${UPLOAD_LOCATION}/stable/vscode-microprofile/ <<< \$'put -p ${tgz[0].path}'"
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tools for MicroProfile
2 |
3 | [](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-microprofile)
4 | [](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-microprofile)
5 | [](https://gitter.im/redhat-developer/vscode-microprofile)
6 | [](https://github.com/redhat-developer/vscode-microprofile/actions?query=branch%3Amaster)
7 | [](https://github.com/redhat-developer/vscode-microprofile/blob/master/LICENSE)
8 |
9 | ## Description
10 |
11 | This Visual Studio Code extension provides support for the development of [MicroProfile®](https://microprofile.io/)-based applications, via the [LSP4MP project](https://github.com/eclipse/lsp4mp), which consists of:
12 |
13 | * a [language server for MicroProfile](https://github.com/eclipse/lsp4mp/tree/master/microprofile.ls).
14 | * a [jdt.ls extension for MicroProfile](https://github.com/eclipse/lsp4mp/tree/master/microprofile.jdt).
15 |
16 | 
17 |
18 | ## MicroProfile `properties` Features
19 |
20 | In `microprofile-config.properties` files, you will benefit with:
21 |
22 | * [Completion support for MicroProfile properties](./docs/PropertiesFeatures.md#completion-support)
23 | * [Hover support for MicroProfile properties](./docs/PropertiesFeatures.md#hover-support)
24 | * [Definition support for MicroProfile properties](./docs/PropertiesFeatures.md#definition-support)
25 | * [Format support for MicroProfile properties](./docs/PropertiesFeatures.md#format-support)
26 | * [Validation and Quick Fix support for MicroProfile properties](./docs/PropertiesFeatures.md#validation-and-quick-fix-support)
27 | * [Outline support (flat or tree view)](./docs/PropertiesFeatures.md#outline-support)
28 |
29 | ## MicroProfile `Java` Features
30 |
31 | In `Java` files, you will benefit with:
32 |
33 | * [Completion support for MicroProfile](./docs/JavaFeatures.md#completion-support)
34 | * [Hover support for MicroProfile](./docs/JavaFeatures.md#hover-support)
35 | * [Validation and Quick Fix support for MicroProfile](./docs/JavaFeatures.md#validation-and-quick-fix-support)
36 | * [Code Lens support for MicroProfile](./docs/JavaFeatures.md#codelens-support)
37 | * [Workspace symbols](./docs/JavaFeatures.md#workspace-symbols-support)
38 | * [Code snippets](./docs/JavaFeatures.md#snippets-support)
39 |
40 | ## Requirements
41 |
42 | * [Language Support for Java(TM) by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java)
43 | * Java JDK (or JRE) 21 or more recent is required **except** on the following platforms : `win32-x64`, `linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`. See [JDK Tooling](https://github.com/redhat-developer/vscode-java/#java-tooling-jdk) for details.
44 |
45 | ## Supported VS Code settings
46 |
47 | The following settings are supported:
48 |
49 | * `microprofile.tools.formatting.surroundEqualsWithSpaces` : Insert spaces around the equals sign when formatting the application.properties file. Default is `false`.
50 | * `microprofile.tools.trace.server` : Trace the communication between VS Code and the MicroProfile Language Server in the Output view.
51 | * `microprofile.tools.symbols.showAsTree` : Show MicroProfile properties as tree (Outline). Default is `true`.
52 | * `microprofile.tools.validation.enabled` : Enables MicroProfile validation. Default is `true`.
53 | * `microprofile.tools.validation.duplicate.severity` : Validation severity for duplicate properties for MicroProfile `*.properties` files.
54 | Default is `warning`.
55 | * `microprofile.tools.validation.syntax.severity` : Validation severity for property syntax checking for MicroProfile `*.properties` files.
56 | Default is `error`.
57 | * `microprofile.tools.validation.required.severity` : Validation severity for required properties for MicroProfile `*.properties` files.
58 | Default is `none`.
59 | * `microprofile.tools.validation.expression.severity` : Validation severity for property expressions for MicroProfile `*.properties` files.
60 | Default is `error`.
61 | * `microprofile.tools.validation.unknown.severity` : Validation severity for unknown properties for MicroProfile `*.properties` files. Default is `warning`.
62 | * `microprofile.tools.validation.unknown.excluded` : Array of properties to ignore for unknown properties validation. Patterns can be used ('\*' = any string, '?' = any character).
63 | Default is `["*/mp-rest/providers/*/priority", "mp.openapi.schema.*", "kafka-streams.*", "camel.*"]`.
64 | * `microprofile.tools.codeLens.urlCodeLensEnabled` : Enable/disable the URL code lenses for REST services. Default is`true`.
65 | * `microprofile.tools.validation.value.severity`: Validation severity for property values for MicroProfile `*.properties` files. Default is `error`.
66 | * `microprofile.tools.validation.unassigned.excluded`: Array of properties to ignore for unassigned properties validation in Java files. Patterns can be used ('\*' = any string, '?' = any character).
67 | * `microprofile.tools.inlayHint.enabled`: Enable/disable the inlay hint support. Default is `false`.
68 |
69 | ### **Note for MicroProfile Rest Client properties**:
70 |
71 | Due to [this issue](https://github.com/redhat-developer/quarkus-ls/issues/203), the MP Rest property: `/mp-rest/providers//priority` reports an unknown error.
72 |
73 | To avoid having this error, you must configure the following in `settings.json`:
74 |
75 | ```json
76 | "microprofile.tools.validation.unknown.excluded": [
77 | "*/mp-rest/providers/*/priority"
78 | ]
79 | ```
80 |
81 | This settings is set by default.
82 |
83 |
84 | ## Extending Tools for MicroProfile
85 |
86 | By default, Tools for MicroProfile provides:
87 |
88 | * Support for the `microprofile-config.properties` file (completion, validation, etc.) for the properties of MicroProfile specs (config, health, fault tolerance, etc.).
89 | * Support in java files (diagnostics, codelens, etc.) taking into account the API of each of the MicroProfile specs.
90 |
91 | The support for properties and java files can be extended with:
92 |
93 | * Additional language features (diagnostics, quick fixes, etc.) in Java files for modules other than MicroProfile specs.
94 | * Additional properties support for properties other than those defined by MicroProfile specs (Ex. Quarkus properties)
95 | * Additional language / document selectors to allow MicroProfile language features in files other than `microprofile-config.properties` (Ex. the `application.properties` file for Quarkus)
96 |
97 | To contribute these features, you must create a vscode-extension that declares the `microprofile` contributions in its package.json. These contributions will be picked up automatically by vscode-microprofile when it starts up the language server.
98 |
99 | ```json
100 | "contributes": {
101 | "microprofile": {
102 | "jarExtensions": [...],
103 | "documentSelector": [...],
104 | }
105 | }
106 | ```
107 |
108 | ### Contributing to properties and Java support
109 |
110 | LSP4MP can be [extended](https://github.com/eclipse/lsp4mp#extensions) to support custom completion, hover, validation, etc by using the [Java Service Provider Interface (SPI)](https://www.baeldung.com/java-spi). vscode-microprofile provides the ability to use your custom lsp4mp extension by contributing external JARs to the classpath of lsp4mp.
111 |
112 | To contribute an external JAR you must create a vscode extension which embeds your lsp4mp extension JAR and declares the path to your JAR in the extensions package.json
113 |
114 | ```json
115 | "contributes": {
116 | "microprofile": {
117 | "jarExtensions": [
118 | "./jar/com.demo.custom-lsp4mp-extension.jar"
119 | ]
120 | }
121 | }
122 | ```
123 |
124 | For an example of how this can be used you can look at [vscode-quarkus](https://github.com/redhat-developer/vscode-quarkus) and the [quarkus-ls](https://github.com/redhat-developer/quarkus-ls) lsp4mp extension. vscode-quarkus [contributes an external jar](https://github.com/redhat-developer/vscode-quarkus/blob/f38f4caaf218cf9c6ce91e64a0d9cd632314a483/package.json#L59) which provides additional language support for quarkus properties and java files.
125 |
126 | ### Contributing to MicroProfile Language / Document Selector support
127 |
128 | It is also possible to contribute additional document selectors which are used to register additional file types / languages with the lsp4mp language server
129 |
130 | ```json
131 | "contributes": {
132 | "microprofile": {
133 | "documentSelector": [
134 | {
135 | "scheme": "file",
136 | "language": "my-custom-properties"
137 | }
138 | ]
139 | }
140 | }
141 | ```
142 |
143 | For an example of how this can be used you can look at [vscode-quarkus](https://github.com/redhat-developer/vscode-quarkus) which [contributes a document selector](https://github.com/redhat-developer/vscode-quarkus/blob/f38f4caaf218cf9c6ce91e64a0d9cd632314a483/package.json#L62) for Quarkus's `application.properties` file in order to provide MicroProfile/Quarkus properties support in this file.
144 |
145 | ## Telemetry
146 |
147 | With your approval, vscode-microprofile extension collects anonymous [usage data](USAGE_DATA.md) and sends it to Red Hat servers to help improve our products and services.
148 | Read our [privacy statement](https://developers.redhat.com/article/tool-data-collection) to learn more.
149 | This extension respects the `redhat.telemetry.enabled` setting, which you can learn more about at https://github.com/redhat-developer/vscode-redhat-telemetry#how-to-disable-telemetry-reporting
150 | Note that this extension abides by Visual Studio Code's telemetry level: if `telemetry.telemetryLevel` is set to off, then no telemetry events will be sent to Red Hat, even if `redhat.telemetry.enabled` is set to true. If `telemetry.telemetryLevel` is set to `error` or `crash`, only events containing an error or errors property will be sent to Red Hat.
151 |
152 | ## Contributing
153 |
154 | This is an open source project open to anyone. Contributions are extremely welcome!
155 |
156 | For information on getting started, refer to the [CONTRIBUTING instructions](CONTRIBUTING.md).
157 |
158 | CI builds can be installed manually by following these instructions:
159 |
160 | 1) Download the latest development VSIX archive [from here](https://download.jboss.org/jbosstools/vscode/snapshots/vscode-microprofile/?C=M;O=D). `(vscode-microprofile-XXX.vsix)`
161 |
162 | 2) Click `View/Command Palette`
163 |
164 | 3) Type 'VSIX'
165 |
166 | 4) Select 'Install from VSIX...' and choose the `.vsix` file.
167 |
168 | ## Feedback
169 |
170 | Please report bugs, issues and feature requests by creating a [GitHub Issue](https://github.com/redhat-developer/vscode-microprofile/issues).
171 |
172 | ## License
173 |
174 | Apache License 2.0.
175 | See [LICENSE](LICENSE) file.
176 |
177 |
178 | MicroProfile® and the MicroProfile logo are trademarks of the Eclipse Foundation
179 |
--------------------------------------------------------------------------------
/USAGE_DATA.md:
--------------------------------------------------------------------------------
1 | # USAGE DATA
2 |
3 | vscode-microprofile has opt-in telemetry collection, provided by [vscode-redhat-telemetry](https://github.com/redhat-developer/vscode-redhat-telemetry).
4 |
5 | ## What's included in the vscode-microprofile telemetry data
6 |
7 | vscode-microprofile emits telemetry events when the extension starts and stops,
8 | which contain the common data mentioned on the [vscode-redhat-telemetry page](https://github.com/redhat-developer/vscode-redhat-telemetry/blob/HEAD/USAGE_DATA.md#common-data).
9 |
10 | vscode-microprofile emits telemetry events whenever you apply a quick fix or source action,
11 | and emits an event if applying the quick fix or source action fails.
12 |
13 | ## How to opt in or out
14 |
15 | Use the `redhat.telemetry.enabled` setting in order to enable or disable telemetry collection.
16 | Note that this extension abides by Visual Studio Code's telemetry level: if `telemetry.telemetryLevel` is set to off, then no telemetry events will be sent to Red Hat, even if `redhat.telemetry.enabled` is set to true. If `telemetry.telemetryLevel` is set to `error` or `crash`, only events containing an error or errors property will be sent to Red Hat.
17 |
--------------------------------------------------------------------------------
/docs/Features.md:
--------------------------------------------------------------------------------
1 | # Features
2 |
3 | [vscode-microprofile](https://github.com/redhat-developer/vscode-microprofile) has a number of notable features available for MicroProfile projects.
4 |
5 | - [MicroProfile Properties Features](PropertiesFeatures.md)
6 | - [MicroProfile Java Features](JavaFeatures.md)
7 |
--------------------------------------------------------------------------------
/docs/JavaFeatures.md:
--------------------------------------------------------------------------------
1 | # MicroProfile Java Features
2 |
3 | A MicroProfile project provides microservice architecture for Java applications. vscode-microprofile provides a variety of support for Java files.
4 |
5 | ## Completion support
6 |
7 | As a main component of development with MicroProfile, annotations are used to expose APIs. For MicroProfile annotation, completion support is available using `Ctrl + Space`. An example of this is the `fallbackMethod` completion for the MicroProfile Fault Tolerance `@Fallback` annotation.
8 |
9 | 
10 |
11 | ## Snippets support
12 |
13 | In Java files in a MicroProfile project, vscode-microprofile provides the following snippets:
14 |
15 | * `rest_class`: Create a new JAX-RS/Jakarta REST resource class
16 | * `rest_get`: Create a new JAX-RS/Jakarta REST GET resource method
17 | * `mpreadiness`: Create a readiness check class
18 | * `mpliveness`: Create a liveness check class
19 | * `mpnrc`: Create a new MicroProfile REST client
20 | * `mpirc`: Inject a MicroProfile REST client
21 | * Snippets to help fill out the parameters for annotations that are introduced by MicroProfile:
22 | * `@Timeout`
23 | * `@Retry`
24 | * `@Fallback`
25 | * `@CircuitBreaker`
26 | * `@Bulkhead`
27 | * `@Metric`
28 | * `@Counted`
29 | * `@Gauge`
30 | * `@ConcurrentGauge`
31 | * `@Metered`
32 | * `@Timed`
33 | * `@SimplyTimed`
34 | * `@RegistryType`
35 | * `@Operation`
36 | * `@Content`
37 | * `@Schema`
38 | * `@Parameters`
39 | * `@Parameter`
40 | * `@APIResponses`
41 | * `@APIResponse`
42 |
43 | Only snippets relevant to the context are shown.
44 | That means that if the cursor is in a place where it doesn't make sense to add the snippet content,
45 | or if the classes that the snippet references are on the classpath of the project,
46 | then the snippets won't be shown.
47 |
48 | ## Hover support
49 |
50 | Given any MicroProfile annotation, hover support is available for more info on usage, interface, etc..
51 |
52 | An example of this is the reference to the `@ConfigProperty` annotation value defined in the project properties file.
53 |
54 | 
55 |
56 | ## Navigation support
57 |
58 | For any reference to a local definition of an annotation value, `Ctrl + Click` will navigate to the value definition.
59 |
60 | 
61 |
62 | Similarly, there is navigation support for any `microprofile-config.properties` definition referenced in the Java project also using `Ctrl + Click`.
63 |
64 | 
65 |
66 | ## Validation and Quick Fix support
67 |
68 | Diagnostics are supported for MicroProfile annotations which targets errors and warnings that would thrown on runtime. Most of these diagnostics also have an associated quick fix to triage the diagnostic.
69 |
70 | 
71 |
72 | ## CodeLens support
73 |
74 | On debug, a Quarkus application run with MicroProfile sources supports a URL CodeLens that routes to the endpoint debug path.
75 |
76 | 
77 |
78 | ## Workspace Symbols support
79 |
80 | vscode-microprofile provides workspace symbols for:
81 |
82 | ### Jakarta/JAX-RS REST methods
83 |
84 | Workspace Symbols with the prefix `@` refer to Jakarta/JAX-RS REST methods.
85 | vscode-microprofile lists the URL and the HTTP method for each method.
86 |
87 | 
88 |
--------------------------------------------------------------------------------
/docs/PropertiesFeatures.md:
--------------------------------------------------------------------------------
1 | # MicroProfile Properties Features
2 |
3 | A MicroProfile project can be configured using a `microprofile-config.properties` file. vscode-microprofile provides a variety of support for `microprofile-config.properties` files.
4 |
5 | These features are made available given a "Microprofile properties" file has been detected.
6 |
7 | 
8 |
9 | These features are also supported for a user profile on the [config level](https://download.eclipse.org/microprofile/microprofile-config-2.0/microprofile-config-spec-2.0.html#_on_config_source_level) and the [property level](https://download.eclipse.org/microprofile/microprofile-config-2.0/microprofile-config-spec-2.0.html#_on_property_level). For example, a file such as `microprofile-config-prod.properties` will have feature support in relation to the `prod` profile.
10 |
11 | ## Completion support
12 |
13 | Depending on the extensions installed for the project, the property autocomplete feature lists suggested properties based on the text entered and extensions available.
14 |
15 | 
16 |
17 | Value completion is also supported for each property.
18 |
19 | ### Read more
20 |
21 | You can find out more on the available extensions and the completion supported for your MicroProfile project version at microprofile.io.
22 |
23 | ## Hover support
24 |
25 | For any given supported property defined in `microprofile-config.properties`, hovering the property will list details about the property, including type, associated extension and assigned value, if any.
26 |
27 | 
28 |
29 | ## Definition support
30 |
31 | ### Java file definition
32 |
33 | If a property value is configured in `microprofile-config.properties`, `Ctrl + Click` of the property will jump to the Java file declaration.
34 | 
35 |
36 | ### Properties definition
37 |
38 | If a property value is defined using a [property expression](https://download.eclipse.org/microprofile/microprofile-config-2.0/microprofile-config-spec-2.0.html#property-expressions) (i.e. `${}`) which references another property defined in `microprofile-config.properties`, `Ctrl + Click` of the property expression value will jump to the property definition.
39 |
40 | 
41 |
42 | ## Format support
43 |
44 | A "Microprofile properties" file sets the default formatter to "Tools for MicroProfile", so the formatting shortcut for a `microprofile-config.properties` file is `Ctrl + Shift + I`. The formatter can also be accessed from the command palette and right-click dropdown.
45 |
46 | 
47 |
48 | ## Validation and Quick Fix support
49 |
50 | For any supported property that can be defined in a "Microprofile properties" file, there is validation for the property name and a quick fix action to correct the diagnostic.
51 |
52 | 
53 |
54 | ## Outline support
55 |
56 | Given the following `microprofile-config.properties` file:
57 |
58 | ```properties
59 | mp.metrics.appName=foo
60 | mp.metrics.tags=bar
61 | ```
62 |
63 | With the `microprofile.tools.symbols.showAsTree` setting enabled:
64 |
65 | 
66 |
67 | The property hierarchy can be viewed from the "Outline" tab.
68 |
69 | 
70 |
--------------------------------------------------------------------------------
/docs/res/MPFormatter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPFormatter.gif
--------------------------------------------------------------------------------
/docs/res/MPJavaCodeLens.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaCodeLens.png
--------------------------------------------------------------------------------
/docs/res/MPJavaCompletion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaCompletion.gif
--------------------------------------------------------------------------------
/docs/res/MPJavaHover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaHover.gif
--------------------------------------------------------------------------------
/docs/res/MPJavaNavigation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaNavigation.gif
--------------------------------------------------------------------------------
/docs/res/MPJavaNavigationConfig.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaNavigationConfig.gif
--------------------------------------------------------------------------------
/docs/res/MPJavaValidationAndQuickFix.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJavaValidationAndQuickFix.gif
--------------------------------------------------------------------------------
/docs/res/MPJumpToJavaDefinition.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPJumpToJavaDefinition.gif
--------------------------------------------------------------------------------
/docs/res/MPPropertiesDetection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPPropertiesDetection.png
--------------------------------------------------------------------------------
/docs/res/MPPropertyCompletion.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPPropertyCompletion.gif
--------------------------------------------------------------------------------
/docs/res/MPPropertyHover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPPropertyHover.gif
--------------------------------------------------------------------------------
/docs/res/MPPropertyQuickFix.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPPropertyQuickFix.gif
--------------------------------------------------------------------------------
/docs/res/MPPropertyValueDefinition.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPPropertyValueDefinition.gif
--------------------------------------------------------------------------------
/docs/res/MPShowAsTreeOutline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPShowAsTreeOutline.png
--------------------------------------------------------------------------------
/docs/res/MPShowAsTreeSetting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/MPShowAsTreeSetting.png
--------------------------------------------------------------------------------
/docs/res/WorkspaceSymbolsJakartaREST.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/docs/res/WorkspaceSymbolsJakartaREST.gif
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import eslint from '@eslint/js';
4 | import tseslint from 'typescript-eslint';
5 |
6 | export default tseslint.config(
7 | eslint.configs.recommended,
8 | tseslint.configs.recommended,
9 | {
10 | files: [
11 | "*/**test.ts"
12 | ],
13 | rules: {
14 | "@typescript-eslint/no-unused-expressions": "off"
15 | }
16 | },
17 | );
18 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2019 Red Hat, Inc. and others.
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | * Unless required by applicable law or agreed to in writing, software
8 | * distributed under the License is distributed on an "AS IS" BASIS,
9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | * See the License for the specific language governing permissions and
11 | * limitations under the License.
12 | */
13 |
14 | const gulp = require('gulp');
15 | const rename = require('gulp-rename');
16 | const cp = require('child_process');
17 | const fse = require('fs-extra');
18 |
19 | const microprofileServerName = 'org.eclipse.lsp4mp.ls-uber.jar';
20 | const microprofileServerDir = '../lsp4mp/microprofile.ls/org.eclipse.lsp4mp.ls';
21 |
22 | const microprofileExtensionDir = '../lsp4mp/microprofile.jdt';
23 | const microprofileExtension = 'org.eclipse.lsp4mp.jdt.core';
24 | const microprofileSite = 'org.eclipse.lsp4mp.jdt.site';
25 |
26 | gulp.task('buildServer', (done) => {
27 | cp.execSync(mvnw() + ' clean install -B -DskipTests', { cwd: microprofileServerDir , stdio: 'inherit' });
28 | gulp.src(microprofileServerDir + '/target/' + microprofileServerName, { encoding: false })
29 | .pipe(gulp.dest('./server'));
30 | done();
31 | });
32 |
33 | gulp.task('buildExtension', (done) => {
34 | cp.execSync(mvnw() + ' clean verify -B -DskipTests', { cwd: microprofileExtensionDir, stdio: 'inherit' });
35 | gulp.src(microprofileExtensionDir + '/' + microprofileExtension + '/target/' + microprofileExtension + '-!(*sources).jar', { encoding: false })
36 | .pipe(rename(microprofileExtension + '.jar'))
37 | .pipe(gulp.dest('./jars'));
38 | gulp.src(microprofileExtensionDir + '/' + microprofileSite + '/target/repository/plugins/wrapped*.jar', { encoding: false })
39 | .pipe(rename(function (path, _file) {
40 | const patt = /wrapped\.([^_]+).*/;
41 | const result = path.basename.match(patt);
42 | path.basename = result[1];
43 | }))
44 | .pipe(gulp.dest('./jars'));
45 | gulp.src(microprofileExtensionDir + '/' + microprofileSite + '/target/repository/plugins/org.jboss.logging*.jar', { encoding: false })
46 | .pipe(rename(function (path, _file) {
47 | const patt = /([^_]+).*/;
48 | const result = path.basename.match(patt);
49 | path.basename = result[1];
50 | }))
51 | .pipe(gulp.dest('./jars'));
52 | done();
53 | });
54 |
55 | gulp.task('build', gulp.series('buildServer', 'buildExtension'));
56 |
57 | gulp.task('prepare_pre_release', function (done) {
58 | const json = JSON.parse(fse.readFileSync("./package.json").toString());
59 | const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/);
60 | const major = stableVersion[1];
61 | const minor = stableVersion[2];
62 | const date = new Date();
63 | const month = date.getMonth() + 1;
64 | const day = date.getDate();
65 | const hours = date.getHours();
66 | const patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`;
67 | const insiderPackageJson = Object.assign(json, {
68 | version: `${major}.${minor}.${patch}`,
69 | });
70 | fse.writeFileSync("./package.json", JSON.stringify(insiderPackageJson, null, 2));
71 | done();
72 | });
73 |
74 | function mvnw() {
75 | return isWin() ? 'mvnw.cmd' : './mvnw';
76 | }
77 |
78 | function isWin() {
79 | return /^win/.test(process.platform);
80 | }
81 |
82 | function prependZero(number) {
83 | if (number > 99) {
84 | throw "Unexpected value to prepend with zero";
85 | }
86 | return `${number < 10 ? "0" : ""}${number}`;
87 | }
88 |
--------------------------------------------------------------------------------
/icons/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/icons/logo.png
--------------------------------------------------------------------------------
/images/componentDiagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/componentDiagram.png
--------------------------------------------------------------------------------
/images/debugConfig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/debugConfig.png
--------------------------------------------------------------------------------
/images/debugConfigMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/debugConfigMenu.png
--------------------------------------------------------------------------------
/images/deployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/deployment.png
--------------------------------------------------------------------------------
/images/propertiesSupport.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/propertiesSupport.png
--------------------------------------------------------------------------------
/images/runDebugger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/runDebugger.png
--------------------------------------------------------------------------------
/images/runDebuggerVSCodeTests.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/runDebuggerVSCodeTests.png
--------------------------------------------------------------------------------
/images/runExtension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-microprofile/7e9d4d72fb6887cff89893052542671d1df61098/images/runExtension.png
--------------------------------------------------------------------------------
/language-support/properties-support/language-configuration.json:
--------------------------------------------------------------------------------
1 | // Referenced from:
2 | // https://github.com/spring-projects/sts4/blob/0714b6a69309789ac85441062698153b0ac4d9c6/vscode-extensions/vscode-spring-boot/properties-support/language-configuration.json
3 |
4 | {
5 | "comments": {
6 | "lineComment": "#"
7 | },
8 | "brackets": [
9 | ],
10 | "autoClosingPairs": [
11 | ["{", "}"],
12 | ["[", "]"],
13 | ["(", ")"],
14 | ["\"", "\""],
15 | ["'", "'"]
16 | ],
17 | "surroundingPairs": [
18 | ["{", "}"],
19 | ["[", "]"],
20 | ["(", ")"],
21 | ["\"", "\""],
22 | ["'", "'"]
23 | ]
24 | }
--------------------------------------------------------------------------------
/language-support/properties-support/microprofile-properties-injections.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "scopeName": "microprofile-value.injection",
3 | "injectionSelector": "L:string.unquoted.java-properties",
4 | "patterns": [
5 | {
6 | "include": "#numbers"
7 | },
8 | {
9 | "include": "#expression"
10 | }
11 | ],
12 | "repository": {
13 | "numbers": {
14 | "patterns": [
15 | {
16 | "match": "(?x)\n\\b(?,
38 | javaRequirement: Promise,
39 | serverMode: ServerMode,
40 | onDidServerModeChange(callback: (mode: string) => void);
41 | };
42 |
43 | export async function activate(context: ExtensionContext): Promise {
44 | if (await isJavaProject()) {
45 | await doActivate(context);
46 | }
47 | }
48 |
49 | async function doActivate(context: ExtensionContext) {
50 | const redHatService: RedHatService = await getRedHatService(context);
51 | const telemetryService: TelemetryService = await redHatService.getTelemetryService();
52 | await telemetryService.sendStartupEvent();
53 |
54 | const yamlSchemaCache = getYamlSchemaCache();
55 | let yamlRegistered = false;
56 |
57 | /**
58 | * Register Yaml Schema support to manage appropriate yaml files if currently open in workspace
59 | */
60 | if (hasOpenedYamlConfig()) {
61 | registerYamlSchemaSupport();
62 | yamlRegistered = true;
63 | }
64 |
65 | /**
66 | * Monitor opened files to register Yaml Schema support if appropriate yaml file is opened
67 | */
68 | workspace.onDidOpenTextDocument((e: TextDocument) => {
69 | yamlRegistered = registerYamlSchemaSupportIfNeeded(e.fileName, yamlSchemaCache, yamlRegistered);
70 | });
71 |
72 | /**
73 | * Monitor created files to register Yaml Schema support if appropriate yaml file is created
74 | */
75 | workspace.onDidCreateFiles((e: FileCreateEvent) => {
76 | yamlRegistered = registerYamlSchemaSupportIfNeeded(e.files[0].fsPath, yamlSchemaCache, yamlRegistered);
77 | });
78 |
79 | /**
80 | * Waits for the java language server to launch in standard mode
81 | * Before activating Tools for MicroProfile.
82 | * If java ls was started in lightweight mode, It will prompt user to switch
83 | */
84 | const api: JavaExtensionAPI = await getJavaExtensionAPI();
85 | await waitForStandardMode(api);
86 |
87 | const microprofileContributions: MicroProfileContribution[] = collectMicroProfileJavaExtensions(extensions.all);
88 | const documentSelector = getDocumentSelector(microprofileContributions);
89 | connectToLS(context, api, documentSelector, microprofileContributions).then(() => {
90 | yamlSchemaCache.then(cache => { if (cache) { cache.languageClient = languageClient; } });
91 |
92 | /**
93 | * Delegate requests from MicroProfile LS to the Java JDT LS
94 | */
95 | bindRequest(MicroProfileLS.PROJECT_INFO_REQUEST);
96 | bindRequest(MicroProfileLS.PROPERTY_DEFINITION_REQUEST);
97 | bindRequest(MicroProfileLS.PROPERTY_DOCUMENTATION_REQUEST);
98 | bindRequest(MicroProfileLS.JAVA_CODEACTION_REQUEST);
99 | bindRequest(MicroProfileLS.JAVA_CODEACTION_RESOLVE_REQUEST);
100 | bindRequest(MicroProfileLS.JAVA_CODELENS_REQUEST);
101 | bindRequest(MicroProfileLS.JAVA_COMPLETION_REQUEST);
102 | bindRequest(MicroProfileLS.JAVA_DEFINITION_REQUEST);
103 | bindRequest(MicroProfileLS.JAVA_DIAGNOSTICS_REQUEST);
104 | bindRequest(MicroProfileLS.JAVA_HOVER_REQUEST);
105 | bindRequest(MicroProfileLS.JAVA_WORKSPACE_SYMBOLS_REQUEST);
106 | bindRequest(MicroProfileLS.JAVA_FILE_INFO_REQUEST);
107 | bindRequest(MicroProfileLS.JAVA_PROJECT_LABELS_REQUEST);
108 | bindRequest(MicroProfileLS.JAVA_WORKSPACE_LABELS_REQUEST);
109 |
110 | /**
111 | * Delegate notifications from Java JDT LS to the MicroProfile LS
112 | */
113 | context.subscriptions.push(commands.registerCommand(MicroProfileLS.PROPERTIES_CHANGED_NOTIFICATION, (event: MicroProfilePropertiesChangeEvent) => {
114 | languageClient.sendNotification(MicroProfileLS.PROPERTIES_CHANGED_NOTIFICATION, event);
115 | yamlSchemaCache.then(cache => {
116 | if (cache)
117 | cache.evict(event);
118 | });
119 | }));
120 |
121 | /**
122 | * Registers a command that, given an LSP code action and a cancellation token:
123 | *
124 | * 1. Resolves the code action if necessary
125 | * 2. Runs command/applies workspace edit. If a code action provides
126 | * an edit and a command, first the edit is executed and then the command,
127 | * similar to how code actions are handled in the LSP specification.
128 | * 3. Sends telemetry if telemetry is enabled and the code action succeeds or fails
129 | */
130 | context.subscriptions.push(commands.registerCommand(APPLY_CODE_ACTION_WITH_TELEMETRY, async (lsCodeActionOrCommand: CodeAction | Command, resolvedEdit: boolean) => {
131 | let codeActionId: string | null = null;
132 | try {
133 | if (Command.is(lsCodeActionOrCommand)) {
134 | const command = lsCodeActionOrCommand as Command;
135 | codeActionId = command.command;
136 | await commands.executeCommand(command.command, ...command.arguments);
137 | } else {
138 | let lsCodeAction = lsCodeActionOrCommand as CodeAction;
139 | codeActionId = lsCodeAction.data?.id;
140 | if ((!resolvedEdit) && (!lsCodeAction.command)) {
141 | // resolve the code action
142 | lsCodeAction = await languageClient.sendRequest(CodeActionResolveRequest.type, lsCodeAction);
143 | }
144 |
145 | if (lsCodeAction.edit) {
146 | const vsCodeAction = await languageClient.protocol2CodeConverter.asCodeAction(lsCodeAction);
147 | await workspace.applyEdit(vsCodeAction.edit);
148 | }
149 | if (lsCodeAction.command) {
150 | if (!codeActionId) {
151 | codeActionId = lsCodeAction.command.command;
152 | }
153 | const vsCommand = languageClient.protocol2CodeConverter.asCommand(lsCodeAction.command);
154 | await commands.executeCommand(vsCommand.command, ...vsCommand.arguments);
155 | }
156 | }
157 | await sendCodeActionTelemetry(telemetryService, codeActionId || 'unknown', true);
158 | } catch (e) {
159 | await sendCodeActionTelemetry(telemetryService, codeActionId || 'unknown', false, e);
160 | }
161 | }));
162 |
163 | }).catch((error) => {
164 | window.showErrorMessage(error.message, error.label).then((selection) => {
165 | if (error.label && error.label === selection && error.openUrl) {
166 | commands.executeCommand('vscode.open', error.openUrl);
167 | }
168 | });
169 | });
170 |
171 | function bindRequest(request: string) {
172 | const requestType = new RequestType(request);
173 | languageClient.onRequest(requestType, async (params, token: CancellationToken) => {
174 | await api.serverReady();
175 | return commands.executeCommand(
176 | "java.execute.workspaceCommand",
177 | request,
178 | params,
179 | token
180 | );
181 | });
182 | }
183 |
184 | registerVSCodeCommands(context);
185 | }
186 |
187 | export async function deactivate(): Promise {
188 | // language client may not have been started
189 | // if java language server was never launched in standard mode.
190 | if (languageClient) {
191 | await languageClient.stop();
192 | }
193 | }
194 |
195 | function registerVSCodeCommands(context: ExtensionContext) {
196 | /**
197 | * Register standard LSP commands
198 | */
199 | context.subscriptions.push(registerConfigurationUpdateCommand());
200 | context.subscriptions.push(registerOpenURICommand());
201 | }
202 |
203 | const REPLACE_JDT_LINKS_PATTERN = /(\[(?:[^\]])+\]\()(jdt:\/\/(?:(?:(?:\\\))|([^)]))+))\)/g;
204 | const VSCODE_JAVA_OPEN_FILE_COMMAND_ID = "java.open.file";
205 |
206 | /**
207 | * Replace `jdt://` links in the documentation with links that execute the VS Code command required to open the referenced file.
208 | *
209 | * Adapted from vscode-java.
210 | *
211 | * @param oldDocumentation the documentation to fix the links in
212 | * @returns the documentation with fixed links
213 | */
214 | function fixJdtLinksInDocumentation(oldDocumentation: MarkdownString): MarkdownString {
215 | const newContent: string = oldDocumentation.value.replace(REPLACE_JDT_LINKS_PATTERN, (_substring, group1, group2) => {
216 | const uri = `command:${VSCODE_JAVA_OPEN_FILE_COMMAND_ID}?${encodeURI(JSON.stringify([encodeURIComponent(group2)]))}`;
217 | return `${group1}${uri})`;
218 | });
219 | const mdString = new MarkdownString(newContent);
220 | mdString.isTrusted = true;
221 | return mdString;
222 | }
223 |
224 | async function connectToLS(context: ExtensionContext, api: JavaExtensionAPI, documentSelector: DocumentSelector, microprofileContributions: MicroProfileContribution[]) {
225 | const requirements = await resolveRequirements(api);
226 | const clientOptions: LanguageClientOptions = {
227 | documentSelector: documentSelector,
228 | // wrap with key 'settings' so it can be handled same a DidChangeConfiguration
229 | initializationOptions: {
230 | settings: getVSCodeMicroProfileSettings(),
231 | extendedClientCapabilities: {
232 | commands: {
233 | commandsKind: {
234 | valueSet: [
235 | CommandKind.COMMAND_CONFIGURATION_UPDATE,
236 | CommandKind.COMMAND_OPEN_URI
237 | ]
238 | }
239 | },
240 | completion: {
241 | skipSendingJavaCompletionThroughLanguageServer: false
242 | },
243 | shouldLanguageServerExitOnShutdown: true
244 | }
245 | },
246 | synchronize: {
247 | // preferences starting with these will trigger didChangeConfiguration
248 | configurationSection: ['microprofile', '[microprofile]']
249 | },
250 | middleware: {
251 | workspace: {
252 | didChangeConfiguration: async () => {
253 | languageClient.sendNotification(DidChangeConfigurationNotification.type, { settings: getVSCodeMicroProfileSettings() });
254 | }
255 | },
256 | provideHover: async (document, position, token, next): Promise => {
257 | const hover = await next(document, position, token);
258 | if (hover === null || hover === undefined) {
259 | return hover;
260 | }
261 | const newContents: (MarkedString | MarkdownString)[] = [];
262 | for (const content of hover.contents) {
263 | if (content instanceof MarkdownString) {
264 | newContents.push(fixJdtLinksInDocumentation(content));
265 | } else {
266 | newContents.push(content);
267 | }
268 | }
269 | hover.contents = newContents;
270 | return hover;
271 | },
272 | resolveCompletionItem: async (item, token, next): Promise => {
273 | const completionItem = await next(item, token);
274 | if (completionItem !== undefined && completionItem !== null && completionItem.documentation instanceof MarkdownString) {
275 | completionItem.documentation = fixJdtLinksInDocumentation(completionItem.documentation);
276 | }
277 | return completionItem;
278 | },
279 | provideCodeActions: async (document, range, context, token, next): Promise => {
280 | // Collect the code actions from the language server,
281 | // then rewrite them to execute the command "microprofile.applyCodeAction"
282 | // instead of whatever action was specified by the language server.
283 | // "microprofile.applyCodeAction" is a command that accepts a code action,
284 | // then applies it, then sends a telemetry event indicating which
285 | // code action was applied.
286 | return (await next(document, range, context, token))
287 | .map((vsCodeActionOrCommand) => {
288 | let kind: CodeActionKind = undefined;
289 | let diagnostics: VSDiagnostic[] = undefined;
290 | let edit = undefined;
291 | // As command arguments are JSON object, code action / command from vscode
292 | // cannot be used as "microprofile.applyCodeAction" arguments because
293 | // it cannot be serialized as JSON correctly (some information are loosen like data, range, etc)
294 | // That's why "microprofile.applyCodeAction" arguments is filled with LSP code action /command.
295 | let lsCodeActionOrCommand: CodeAction | Command = undefined;
296 | if (Command.is(vsCodeActionOrCommand)) {
297 | // Get LSP command from the vscode command
298 | const vsCodeCommand: VSCommand = vsCodeActionOrCommand;
299 | lsCodeActionOrCommand = languageClient.code2ProtocolConverter.asCommand(vsCodeCommand);
300 | } else {
301 | // Get LSP code action from the vscode code action
302 | const vsCodeAction: VSCodeAction = vsCodeActionOrCommand;
303 | kind = vsCodeAction.kind;
304 | diagnostics = vsCodeAction.diagnostics;
305 | if (vsCodeAction.edit) {
306 | // When code action defines the edit, we return a code action with this vscode edit.
307 | // The apply workspace edit will be done by vscode himself and not by the command
308 | // "microprofile.applyCodeAction". In other words "microprofile.applyCodeAction" apply the
309 | // workspace edit only if edit must be resolved by the resolve code action.
310 | edit = vsCodeAction.edit;
311 | vsCodeAction.edit = undefined; // to avoid throwing error from https://github.com/microsoft/vscode-languageserver-node/blob/277e4564193c4ed258fe4d8d405d3379665bbab9/client/src/common/codeConverter.ts#L740
312 | }
313 | lsCodeActionOrCommand = languageClient.code2ProtocolConverter.asCodeActionSync(vsCodeAction);
314 | }
315 | const title = vsCodeActionOrCommand.title;
316 | return {
317 | title: title,
318 | command: {
319 | command: APPLY_CODE_ACTION_WITH_TELEMETRY,
320 | title: title,
321 | arguments: [lsCodeActionOrCommand, edit != undefined]
322 | },
323 | kind: kind,
324 | diagnostics: diagnostics,
325 | edit: edit
326 | }
327 | });
328 | }
329 | }
330 | };
331 |
332 | const serverOptions = prepareExecutable(requirements, getMicroProfileJarExtensions(microprofileContributions));
333 |
334 | languageClient = new LanguageClient('microprofile.tools', 'Tools for MicroProfile', serverOptions, clientOptions);
335 | await languageClient.start();
336 |
337 | if (extensions.onDidChange) {// Theia doesn't support this API yet
338 | context.subscriptions.push(extensions.onDidChange(() => {
339 | // if extensions that contribute mp java extensions change we need to reload the window
340 | handleExtensionChange(extensions.all);
341 | }));
342 | }
343 |
344 | /**
345 | * Returns a json object with key 'microprofile' and a json object value that
346 | * holds all microprofile settings.
347 | */
348 | function getVSCodeMicroProfileSettings(): { microprofile: unknown } {
349 | const defaultMicroProfileSettings = {};
350 | const configMicroProfile = workspace.getConfiguration().get('microprofile');
351 | const microprofileSettings = configMicroProfile ? configMicroProfile : defaultMicroProfileSettings;
352 |
353 | return {
354 | microprofile: microprofileSettings,
355 | };
356 | }
357 |
358 | /**
359 | * Returns an array of paths to MicroProfileLS extension jars within `microProfileContributions`
360 | *
361 | * @param microProfileContributions MicroProfile language server contributions from other VS Code extensions
362 | */
363 | function getMicroProfileJarExtensions(microProfileContributions: MicroProfileContribution[]): string[] {
364 | let jarPaths: string[] = [];
365 | microProfileContributions.forEach((contribution: MicroProfileContribution) => {
366 | if (contribution.jarExtensions && contribution.jarExtensions.length > 0) {
367 | jarPaths = jarPaths.concat(contribution.jarExtensions);
368 | }
369 | });
370 | return jarPaths;
371 | }
372 | }
373 |
374 | async function getJavaExtensionAPI(): Promise {
375 | const vscodeJava = extensions.getExtension(JAVA_EXTENSION_ID);
376 | if (!vscodeJava) {
377 | throw new Error("VSCode java is not installed");
378 | }
379 |
380 | const api = await vscodeJava.activate();
381 | if (!api) {
382 | throw new Error("VSCode java api not found");
383 | }
384 |
385 | return Promise.resolve(api);
386 | }
387 |
388 |
389 | /**
390 | * Returns the document selector.
391 | *
392 | * The returned document selector contains the microprofile-properties and java document selectors
393 | * and all document selectors contained in `microProfileContributions`.
394 | *
395 | * @param microProfileContributions MicroProfile language server contributions from other VS Code extensions
396 | */
397 | function getDocumentSelector(microProfileContributions: MicroProfileContribution[]): DocumentSelector {
398 | let documentSelector: DocumentSelector = [
399 | { scheme: 'file', language: 'java' },
400 | { scheme: 'file', language: 'microprofile-properties' }
401 | ];
402 | microProfileContributions.forEach((contribution: MicroProfileContribution) => {
403 | documentSelector = documentSelector.concat(contribution.documentSelector);
404 | });
405 | return documentSelector;
406 | }
407 |
408 | /**
409 | * Returns if any workspace folder contains a build.gradle, pom.xml, or .project.
410 | *
411 | * @returns true if any workspace folder contains a build.gradle, pom.xml, or .project
412 | */
413 | async function isJavaProject(): Promise {
414 | if (!workspace.workspaceFolders) {
415 | return false;
416 | }
417 | for (const ws of workspace.workspaceFolders) {
418 | const buildFileUris = await getFilePathsFromWorkspace(
419 | ws,
420 | "**/{pom.xml,build.gradle,.project}"
421 | );
422 | if (buildFileUris.length) {
423 | return true;
424 | }
425 | }
426 | return false;
427 | }
428 |
429 | /**
430 | * Returns if the given file name matches YAML config source file pattern.
431 | *
432 | * See https://download.eclipse.org/microprofile/microprofile-config-3.0/microprofile-config-spec-3.0.html#_on_config_source_level for an understanding of this pattern.
433 | *
434 | * @param fileName name of the file to be checked
435 | * @returns true if the file name is a match
436 | */
437 | function isYamlConfigSource(fileName: string): boolean {
438 | return /application(-.*)?\.(yml|yaml)/.test(fileName);
439 | }
440 |
441 | /**
442 | * Returns if any of the open files in the workspace are YAML config sources
443 | *
444 | * @returns true if the above is true
445 | */
446 | function hasOpenedYamlConfig(): boolean {
447 | return workspace.textDocuments.some(file => isYamlConfigSource(file.fileName));
448 | }
449 |
450 | /**
451 | * Registers YAML schema support if not already registered and if fileName is a config source.
452 | *
453 | * @param fileName the recently opened or created file to be checked
454 | * @param yamlSchemaCache
455 | * @param yamlRegistered indicates whether or not YAML support has already been registered
456 | * @returns true if YAML schema support was registered
457 | */
458 | function registerYamlSchemaSupportIfNeeded(fileName: string, yamlSchemaCache: Promise, yamlRegistered: boolean) {
459 | if (yamlRegistered == false && isYamlConfigSource(fileName)) {
460 | registerYamlSchemaSupport();
461 | return true;
462 | }
463 | return yamlRegistered;
464 | }
465 |
--------------------------------------------------------------------------------
/src/languageServer/javaServerStarter.ts:
--------------------------------------------------------------------------------
1 | import { globSync } from 'glob';
2 | import * as os from 'os';
3 | import * as path from 'path';
4 | import { workspace } from 'vscode';
5 | import { Executable, ExecutableOptions } from 'vscode-languageclient/node';
6 | import { RequirementsData } from './requirements';
7 |
8 | const DEBUG = startedInDebugMode();
9 | const DEBUG_PORT = 1064;
10 | const MICROPROFILE_SERVER_NAME = 'org.eclipse.lsp4mp.ls-uber.jar';
11 | const MICROPROFILE_SERVER_MAIN_CLASS = 'org.eclipse.lsp4mp.ls.MicroProfileServerLauncher';
12 |
13 | export function prepareExecutable(requirements: RequirementsData, microprofileJavaExtensions: string[]): Executable {
14 | const executable: Executable = Object.create(null);
15 | const options: ExecutableOptions = Object.create(null);
16 | options.env = process.env;
17 | executable.options = options;
18 | executable.command = path.resolve(requirements.tooling_jre + '/bin/java');
19 | executable.args = prepareParams(microprofileJavaExtensions);
20 | return executable;
21 | }
22 |
23 | function prepareParams(microprofileJavaExtensions: string[]): string[] {
24 | const params: string[] = [];
25 | if (DEBUG) {
26 | if (process.env.SUSPEND_SERVER === 'true') {
27 | params.push(`-agentlib:jdwp=transport=dt_socket,server=y,address=${DEBUG_PORT}`);
28 | } else {
29 | params.push(`-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${DEBUG_PORT},quiet=y`);
30 | }
31 | }
32 |
33 | const vmargs = workspace.getConfiguration("microprofile.tools").get("server.vmargs", '');
34 | if (os.platform() === 'win32') {
35 | const watchParentProcess = '-DwatchParentProcess=';
36 | if (vmargs.indexOf(watchParentProcess) < 0) {
37 | params.push(watchParentProcess + 'false');
38 | }
39 | }
40 | // Disable logging unless the user specifically sets it to a different value.
41 | // Logging can cause issues, since sometimes it writes to standard out.
42 | // See https://github.com/redhat-developer/vscode-java/issues/2577.
43 | if (vmargs.indexOf("-Xlog:") < 0) {
44 | params.push("-Xlog:disable");
45 | }
46 | parseVMargs(params, vmargs);
47 | const serverHome: string = path.resolve(__dirname, '../server');
48 | const microprofileServerFound: Array = globSync(`**/${MICROPROFILE_SERVER_NAME}`, { cwd: serverHome });
49 | if (microprofileServerFound.length) {
50 | let mpJavaExtensionsClasspath = '';
51 | if (microprofileJavaExtensions.length > 0) {
52 | const classpathSeperator = os.platform() === 'win32' ? ';' : ':';
53 | mpJavaExtensionsClasspath = classpathSeperator + microprofileJavaExtensions.join(classpathSeperator);
54 | }
55 |
56 | params.push('-cp');
57 | params.push(`${serverHome}/*` + mpJavaExtensionsClasspath);
58 | params.push(MICROPROFILE_SERVER_MAIN_CLASS);
59 | } else {
60 | throw new Error('Unable to find required Language Server JARs');
61 | }
62 | return params;
63 | }
64 |
65 | function hasDebugFlag(args: string[]): boolean {
66 | if (args) {
67 | // See https://nodejs.org/en/docs/guides/debugging-getting-started/
68 | return args.some(arg => /^--inspect/.test(arg) || /^--debug/.test(arg));
69 | }
70 | return false;
71 | }
72 |
73 | function startedInDebugMode(): boolean {
74 | const args: string[] = process.execArgv;
75 | return hasDebugFlag(args);
76 | }
77 |
78 | // exported for tests
79 | export function parseVMargs(params: string[], vmargsLine: string): void {
80 | if (!vmargsLine) {
81 | return;
82 | }
83 | const vmargs = vmargsLine.match(/(?:[^\s"]+|"[^"]*")+/g);
84 | if (vmargs === null) {
85 | return;
86 | }
87 | vmargs.forEach(arg => {
88 | // remove all standalone double quotes
89 | arg = arg.replace(/(\\)?"/g, ($0, $1) => { return ($1 ? $0 : ''); });
90 | // unescape all escaped double quotes
91 | arg = arg.replace(/(\\)"/g, '"');
92 | if (params.indexOf(arg) < 0) {
93 | params.push(arg);
94 | }
95 | });
96 | }
97 |
--------------------------------------------------------------------------------
/src/languageServer/plugin.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as path from 'path';
3 | import * as Commands from '../definitions/commands';
4 | import { DocumentFilter, DocumentSelector } from 'vscode-languageclient';
5 | import { isDeepStrictEqual } from 'util';
6 |
7 | let existingExtensions: MicroProfileContribution[];
8 |
9 | /**
10 | * MicroProfile language server contribution
11 | */
12 | export interface MicroProfileContribution {
13 | jarExtensions: string[];
14 | documentSelector: DocumentSelector;
15 | }
16 |
17 | /**
18 | * Returns all MicroProfile language server contributions from package.json
19 | *
20 | * @param extensions array of extensions to search contributions from
21 | */
22 | export function collectMicroProfileJavaExtensions(extensions: readonly vscode.Extension[]): MicroProfileContribution[] {
23 | const result: MicroProfileContribution[] = [];
24 | if (extensions && extensions.length) {
25 | for (const extension of extensions) {
26 | const contributesSection = extension.packageJSON.contributes;
27 | if (contributesSection && contributesSection.microprofile) {
28 | const microprofileSection = contributesSection.microprofile;
29 | const contributes: MicroProfileContribution = {jarExtensions: [], documentSelector: []};
30 |
31 | setJarExtensionsIfExists(contributes, microprofileSection, extension.extensionPath);
32 | setDocumentSelectorIfExists(contributes, microprofileSection);
33 |
34 | if (contributes.jarExtensions || contributes.documentSelector) {
35 | result.push(contributes);
36 | }
37 | }
38 | }
39 | }
40 | // Make a copy of extensions:
41 | existingExtensions = result.slice();
42 | return result;
43 | }
44 |
45 | export function handleExtensionChange(extensions: readonly vscode.Extension[]): void {
46 | if (!existingExtensions) {
47 | return;
48 | }
49 | const oldExtensions = new Set(existingExtensions.slice());
50 | const newExtensions = collectMicroProfileJavaExtensions(extensions);
51 | let hasChanged = (oldExtensions.size !== newExtensions.length);
52 | if (!hasChanged) {
53 | for (const newExtension of newExtensions) {
54 | let found = false;
55 | for (const oldExtension of oldExtensions) {
56 | if (isDeepStrictEqual(oldExtension, newExtension)) {
57 | found = true;
58 | break;
59 | }
60 | }
61 | if (found) {
62 | continue;
63 | } else {
64 | hasChanged = true;
65 | break;
66 | }
67 | }
68 | }
69 |
70 | if (hasChanged) {
71 | const msg = `Extensions to the MicroProfile Language Server changed, reloading ${vscode.env.appName} is required for the changes to take effect.`;
72 | const action = 'Reload';
73 | vscode.window.showWarningMessage(msg, action).then((selection) => {
74 | if (action === selection) {
75 | vscode.commands.executeCommand(Commands.RELOAD_WINDOW);
76 | }
77 | });
78 | }
79 | }
80 |
81 | function setJarExtensionsIfExists(obj: MicroProfileContribution, section: { jarExtensions: unknown }, extensionPath: string): void {
82 | if (Array.isArray(section.jarExtensions)) {
83 | for (const microprofileJavaExtensionPath of section.jarExtensions) {
84 | obj.jarExtensions.push(path.resolve(extensionPath, microprofileJavaExtensionPath));
85 | }
86 | }
87 | }
88 |
89 | function setDocumentSelectorIfExists(obj: MicroProfileContribution, section: { documentSelector: unknown }): void {
90 | if (!Array.isArray(section.documentSelector)) {
91 | return;
92 | }
93 | const documentSelector: DocumentSelector = [];
94 | section.documentSelector.forEach((selector) => {
95 | if (typeof selector === 'string') {
96 | documentSelector.push(selector);
97 | } else if (selector) {
98 | const documentFilter: {[key: string]: string} = {};
99 | if (typeof selector.language === 'string') {
100 | documentFilter.language = selector.language;
101 | }
102 | if (typeof selector.scheme === 'string') {
103 | documentFilter.scheme = selector.scheme;
104 | }
105 | if (typeof selector.pattern === 'string') {
106 | documentFilter.pattern = selector.pattern;
107 | }
108 | if (documentFilter.language || documentFilter.scheme || documentFilter.pattern) {
109 | documentSelector.push(documentFilter as DocumentFilter);
110 | }
111 | }
112 | });
113 | obj.documentSelector = obj.documentSelector.concat(documentSelector);
114 | }
115 |
--------------------------------------------------------------------------------
/src/languageServer/requirements.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import * as cp from 'child_process';
4 | import * as fs from 'fs';
5 | import * as path from 'path';
6 | import { Uri, workspace } from 'vscode';
7 |
8 | import * as expandHomeDir from 'expand-home-dir';
9 | import { findRuntimes, IJavaRuntime, getSources } from 'jdk-utils';
10 | import { JavaExtensionAPI } from '../extension';
11 | const isWindows = process.platform.indexOf('win') === 0;
12 | const JAVA_FILENAME = 'java' + (isWindows ? '.exe' : '');
13 |
14 | export interface RequirementsData {
15 | tooling_jre: string;
16 | tooling_jre_version: number;
17 | java_home: string;
18 | java_version: number;
19 | }
20 |
21 | /**
22 | * Resolves the requirements needed to run the extension.
23 | * Returns a promise that will resolve to a RequirementsData if
24 | * all requirements are resolved, it will reject with ErrorData if
25 | * if any of the requirements fails to resolve.
26 | *
27 | */
28 | export async function resolveRequirements(api: JavaExtensionAPI): Promise {
29 |
30 | // Use the embedded JRE from 'redhat.java' if it exists
31 | const requirementsData = api.javaRequirement;
32 | if (requirementsData) {
33 | return Promise.resolve(requirementsData);
34 | }
35 |
36 | const javaHome = await checkJavaRuntime();
37 | const javaVersion = await checkJavaVersion(javaHome);
38 | return Promise.resolve({ tooling_jre: javaHome, tooling_jre_version: javaVersion, java_home: javaHome, java_version: javaVersion });
39 | }
40 |
41 | async function checkJavaRuntime(): Promise {
42 | let source: string;
43 | let javaHome: string | undefined = readJavaHomeConfig();
44 |
45 | if (javaHome) {
46 | source = 'The java.home variable defined in VS Code settings';
47 | javaHome = expandHomeDir(javaHome);
48 | if (!fs.existsSync(javaHome)) {
49 | throw openJDKDownload(source + ' points to a missing folder');
50 | } else if (!fs.existsSync(path.resolve(javaHome as string, 'bin', JAVA_FILENAME))) {
51 | throw openJDKDownload(source + ' does not point to a Java runtime.');
52 | }
53 | return javaHome;
54 | }
55 | // No settings, let's try to detect as last resort.
56 | const javaRuntimes = await findRuntimes({ withVersion: true, withTags: true });
57 | if (javaRuntimes.length) {
58 | sortJdksBySource(javaRuntimes);
59 | javaHome = javaRuntimes[0].homedir;
60 | } else {
61 | throw openJDKDownload("Java runtime could not be located. Please download and install Java or use the binary server.");
62 | }
63 | return javaHome;
64 | }
65 |
66 | function sortJdksBySource(jdks: IJavaRuntime[]) {
67 | const rankedJdks = jdks as Array;
68 | const sources = ["JDK_HOME", "JAVA_HOME", "PATH"];
69 | for (const [index, source] of sources.entries()) {
70 | for (const jdk of rankedJdks) {
71 | if (jdk.rank === undefined && getSources(jdk).includes(source)) {
72 | jdk.rank = index;
73 | }
74 | }
75 | }
76 | rankedJdks.filter(jdk => jdk.rank === undefined).forEach(jdk => jdk.rank = sources.length);
77 | rankedJdks.sort((a, b) => a.rank - b.rank);
78 | }
79 |
80 | function readJavaHomeConfig(): string | undefined {
81 | const config = workspace.getConfiguration();
82 | return config.get('java.home');
83 | }
84 |
85 | function checkJavaVersion(javaHome: string): Promise {
86 | return new Promise((resolve, reject) => {
87 | cp.execFile(javaHome + '/bin/java', ['-version'], {}, (error, stdout, stderr) => {
88 | const javaVersion = parseMajorVersion(stderr);
89 | if (javaVersion < 21) {
90 | reject(openJDKDownload(`Java 21 or more recent is required to run 'Tools for MicroProfile'. Please download and install a recent JDK.`));
91 | } else {
92 | resolve(javaVersion);
93 | }
94 | });
95 | });
96 | }
97 |
98 | export function parseMajorVersion(content: string): number {
99 | let regexp = /version "(.*)"/g;
100 | let match = regexp.exec(content);
101 | if (!match) {
102 | return 0;
103 | }
104 | let version = match[1];
105 | // Ignore '1.' prefix for legacy Java versions
106 | if (version.startsWith('1.')) {
107 | version = version.substring(2);
108 | }
109 |
110 | // look into the interesting bits now
111 | regexp = /\d+/g;
112 | match = regexp.exec(version);
113 | let javaVersion = 0;
114 | if (match) {
115 | javaVersion = parseInt(match[0]);
116 | }
117 | return javaVersion;
118 | }
119 |
120 | function openJDKDownload(cause: string) {
121 | let jdkUrl = 'https://developers.redhat.com/products/openjdk/download/?sc_cid=701f2000000RWTnAAO';
122 | if (process.platform === 'darwin') {
123 | jdkUrl = 'http://www.oracle.com/technetwork/java/javase/downloads/index.html';
124 | }
125 | return {
126 | message: cause,
127 | label: 'Get the Java Development Kit',
128 | openUrl: Uri.parse(jdkUrl),
129 | replaceClose: false
130 | };
131 | }
132 |
--------------------------------------------------------------------------------
/src/lsp-commands.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2019 Red Hat, Inc. and others.
3 |
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 |
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import { commands, ConfigurationTarget, Disposable, Uri, workspace } from 'vscode';
18 | import * as CommandKind from './definitions/lspCommandKind';
19 |
20 | /**
21 | * Registers the `CommandKind.COMMAND_CONFIGURATION_UPDATE` command
22 | */
23 | export function registerConfigurationUpdateCommand(): Disposable {
24 | return commands.registerCommand(CommandKind.COMMAND_CONFIGURATION_UPDATE, resolveConfigurationItemEdit);
25 | }
26 |
27 | /**
28 | * Registers the `microprofile.command.open.uri` command.
29 | * This command gives the capability to open the given uri of the command.
30 | */
31 | export function registerOpenURICommand(): Disposable {
32 | return commands.registerCommand(CommandKind.COMMAND_OPEN_URI, (uri) => {
33 | commands.executeCommand('vscode.open', Uri.parse(uri));
34 | });
35 | }
36 |
37 | /**
38 | * Registers the `CommandKind.COMMAND_IMPLEMENTATIONS` command
39 | */
40 | export function registerImplementationsCommand(): Disposable {
41 | return commands.registerCommand(CommandKind.COMMAND_IMPLEMENTATIONS, () => {
42 | // not yet implemented
43 | });
44 | }
45 |
46 | /**
47 | * Registers the `CommandKind.COMMAND_REFERENCES` command
48 | */
49 | export function registerReferencesCommand(): Disposable {
50 | return commands.registerCommand(CommandKind.COMMAND_REFERENCES, () => {
51 | // not yet implemented
52 | });
53 | }
54 |
55 | function resolveConfigurationItemEdit(configItemEdit: ConfigurationItemEdit) {
56 | switch (configItemEdit.editType) {
57 | case ConfigurationItemEditType.Add:
58 | addToPreferenceArray(configItemEdit.section, configItemEdit.value);
59 | break;
60 | case ConfigurationItemEditType.Delete: {
61 | break;
62 | }
63 | case ConfigurationItemEditType.Update: {
64 | break;
65 | }
66 | }
67 | }
68 |
69 | function addToPreferenceArray(key: string, value: T): void {
70 | const configArray: T[] = workspace.getConfiguration().get(key, []);
71 | if (configArray.includes(value)) {
72 | return;
73 | }
74 | configArray.push(value);
75 | workspace.getConfiguration().update(key, configArray, ConfigurationTarget.Workspace);
76 | }
77 |
78 | interface ConfigurationItemEdit {
79 | section: string;
80 | value;
81 | editType: ConfigurationItemEditType;
82 | }
83 |
84 | enum ConfigurationItemEditType {
85 | Add = 0,
86 | Delete = 1,
87 | Update = 2
88 | }
89 |
--------------------------------------------------------------------------------
/src/test/resources/no-lsp4mp-extension-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fake-extension",
3 | "displayName": "Dummy extension",
4 | "version": "1.7.0",
5 | "icon": "icons/logo.png",
6 | "author": "fake author",
7 | "publisher": "fakepublisher",
8 | "preview": true,
9 | "license": "Apache-2.0",
10 | "engines": {
11 | "vscode": "^1.37.0"
12 | },
13 | "main": "./dist/extension",
14 | "extensionDependencies": [
15 | "redhat.vscode-microprofile",
16 | "redhat.java",
17 | "vscjava.vscode-java-debug"
18 | ],
19 | "contributes": {}
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/resources/quarkus-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fake-vscode-quarkus",
3 | "displayName": "Quarkus",
4 | "description": "Quarkus Tools for Visual Studio Code",
5 | "version": "1.7.0",
6 | "icon": "icons/logo.png",
7 | "author": "Red Hat",
8 | "publisher": "redhat",
9 | "preview": true,
10 | "license": "Apache-2.0",
11 | "engines": {
12 | "vscode": "^1.37.0"
13 | },
14 | "activationEvents": [
15 | "onCommand:quarkusTools.createProject",
16 | "onCommand:quarkusTools.welcome",
17 | "workspaceContains:**/src/main/resources/application.properties",
18 | "workspaceContains:**src/main/resources/META-INF/microprofile-config.properties",
19 | "workspaceContains:**/src/main/resources/application.yaml",
20 | "workspaceContains:**/src/main/resources/application.yml",
21 | "onLanguage:microprofile-properties",
22 | "onLanguage:quarkus-properties",
23 | "onLanguage:java",
24 | "onLanguage:qute-html",
25 | "onLanguage:qute-json",
26 | "onLanguage:qute-yaml",
27 | "onLanguage:qute-txt"
28 | ],
29 | "main": "./dist/extension",
30 | "extensionDependencies": [
31 | "redhat.vscode-microprofile",
32 | "redhat.java",
33 | "vscjava.vscode-java-debug"
34 | ],
35 | "contributes": {
36 | "javaExtensions": [
37 | "./jars/com.redhat.microprofile.jdt.quarkus.jar"
38 | ],
39 | "microprofile": {
40 | "jarExtensions": [
41 | "./server/com.redhat.quarkus.ls.jar"
42 | ],
43 | "documentSelector": [
44 | {
45 | "scheme": "file",
46 | "language": "quarkus-properties"
47 | }
48 | ]
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/runTest.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 |
3 | import { runTests } from '@vscode/test-electron';
4 |
5 | async function main() {
6 | try {
7 | // The folder containing the Extension Manifest package.json
8 | // Passed to `--extensionDevelopmentPath`
9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../../');
10 |
11 | // The path to test runner
12 | // Passed to --extensionTestsPath
13 | const extensionTestsPath = path.resolve(__dirname, './suite/index');
14 |
15 | // Download VS Code, unzip it and run the integration test
16 | await runTests({ extensionDevelopmentPath, extensionTestsPath, version: '1.83.1' });
17 | } catch {
18 | console.error('Failed to run tests');
19 | process.exit(1);
20 | }
21 | }
22 |
23 | main();
24 |
--------------------------------------------------------------------------------
/src/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { expect } from 'chai';
3 |
4 | describe('VS Code extension tests', () => {
5 |
6 | it('should be present', () => {
7 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions
8 | expect(vscode.extensions.getExtension('redhat.vscode-microprofile')).to.be.ok;
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/src/test/suite/index.ts:
--------------------------------------------------------------------------------
1 | import { glob } from "glob";
2 | import * as Mocha from "mocha";
3 | import * as path from "path";
4 |
5 | export async function run(): Promise {
6 | // Create the mocha test
7 | const mocha = new Mocha({
8 | ui: "bdd",
9 | color: true,
10 | });
11 |
12 | const testsRoot = path.resolve(__dirname, "..");
13 | const files = await glob("**/**.test.js", { cwd: testsRoot });
14 | files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
15 |
16 | return new Promise((resolve, reject) => {
17 | try {
18 | // Run the mocha test
19 | mocha.run((failures) => {
20 | if (failures > 0) {
21 | reject(new Error(`${failures} tests failed.`));
22 | } else {
23 | resolve();
24 | }
25 | });
26 | } catch (err) {
27 | reject(err);
28 | }
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/suite/languageServer/documentSelectorPlugin.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Red Hat, Inc. and others.
3 |
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 |
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import * as vscode from "vscode";
17 | import * as plugin from "../../../languageServer/plugin";
18 | import { expect } from "chai";
19 | import { MicroProfileContribution } from "../../../languageServer/plugin";
20 | import { TextDocumentFilter, DocumentSelector } from "vscode-languageclient";
21 |
22 | /**
23 | * This file ensures that DocumentSelectors contributed by other VS Code extensions
24 | * (using `contributes.microprofile.documentSelector` key within package.json) are being
25 | * collected correctly.
26 | */
27 | describe("Document selector collection from language server plugins", () => {
28 |
29 | it ('Should collect document selector when all keys exist', () => {
30 | const selector: DocumentSelector = collectDocumentSelectors([{ scheme: "file", language: "quarkus-properties", pattern: "**/*.properties" }]);
31 | expect(selector).to.have.length(1);
32 | expect(selector[0]).to.have.all.keys(["scheme", "language", "pattern"]);
33 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
34 | expect((selector[0] as TextDocumentFilter).language).to.equal("quarkus-properties");
35 | expect((selector[0] as TextDocumentFilter).pattern).to.equal("**/*.properties");
36 | });
37 |
38 | it ('Should collect all document selector when two keys exist', () => {
39 | let selector: DocumentSelector = collectDocumentSelectors([{ scheme: "file", language: "quarkus-properties" }]);
40 | expect(selector).to.have.length(1);
41 | expect(selector[0]).to.have.all.keys(["scheme", "language"]);
42 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
43 | expect((selector[0] as TextDocumentFilter).language).to.equal("quarkus-properties");
44 |
45 | selector = collectDocumentSelectors([{ language: "quarkus-properties", pattern: "**/*.properties" }]);
46 | expect(selector).to.have.length(1);
47 | expect(selector[0]).to.have.all.keys(["language", "pattern"]);
48 | expect((selector[0] as TextDocumentFilter).language).to.equal("quarkus-properties");
49 | expect((selector[0] as TextDocumentFilter).pattern).to.equal("**/*.properties");
50 |
51 | selector = collectDocumentSelectors([{ pattern: "**/*.properties", scheme: "file" }]);
52 | expect(selector).to.have.length(1);
53 | expect(selector[0]).to.have.all.keys(["pattern", "scheme"]);
54 | expect((selector[0] as TextDocumentFilter).pattern).to.equal("**/*.properties");
55 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
56 | });
57 |
58 | it ('Should collect document selector when one key exist', () => {
59 | let selector: DocumentSelector = collectDocumentSelectors([{ scheme: "file" }]);
60 | expect(selector).to.have.length(1);
61 | expect(selector[0]).to.have.all.keys(["scheme"]);
62 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
63 |
64 | selector = collectDocumentSelectors([{ language: "quarkus-properties" }]);
65 | expect(selector).to.have.length(1);
66 | expect(selector[0]).to.have.all.keys(["language"]);
67 | expect((selector[0] as TextDocumentFilter).language).to.equal("quarkus-properties");
68 |
69 | selector = collectDocumentSelectors([{ pattern: "**/*.properties" }]);
70 | expect(selector).to.have.length(1);
71 | expect(selector[0]).to.have.all.keys(["pattern"]);
72 | expect((selector[0] as TextDocumentFilter).pattern).to.equal("**/*.properties");
73 | });
74 |
75 | it ('Should collect document selector when a valid key and an invalid key exists', () => {
76 | // valid, but the "invalid" key is ignored
77 | let selector: DocumentSelector = collectDocumentSelectors([{ scheme: "file", invalid: "file" }]);
78 | expect(selector).to.have.length(1);
79 | expect(selector[0]).to.have.all.keys(["scheme"]);
80 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
81 |
82 | // valid, but the "language" key is ignored since the value has the wrong type
83 | selector = collectDocumentSelectors([{ scheme: "file", language: 12 }]);
84 | expect(selector).to.have.length(1);
85 | expect(selector[0]).to.have.all.keys(["scheme"]);
86 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
87 | });
88 |
89 | it ('Should collect document selector strings', () => {
90 | const selector: DocumentSelector = collectDocumentSelectors(["document-selector-string"]);
91 | expect(selector).to.have.length(1);
92 | expect(selector[0]).to.be.a('string');
93 | expect(selector[0]).to.equal("document-selector-string");
94 | });
95 |
96 | it ('Should not collect document selector when there are no correct keys', () => {
97 | let selector: DocumentSelector = collectDocumentSelectors([{ invalid: "file" }]);
98 | expect(selector).to.have.length(0);
99 |
100 | selector = collectDocumentSelectors([{}]);
101 | expect(selector).to.have.length(0);
102 |
103 | selector = collectDocumentSelectors([]);
104 | expect(selector).to.have.length(0);
105 | });
106 |
107 | it ('Should not collect document selector when containing invalid types', () => {
108 | let selector: DocumentSelector = collectDocumentSelectors([12]);
109 | expect(selector).to.have.length(0);
110 |
111 | selector = collectDocumentSelectors([/test/]);
112 | expect(selector).to.have.length(0);
113 |
114 | selector = collectDocumentSelectors([true]);
115 | expect(selector).to.have.length(0);
116 | });
117 |
118 | it ('Should not collect document selector when all keys have incorrect types', () => {
119 |
120 | let selector: DocumentSelector = collectDocumentSelectors([{ scheme: 12 }]);
121 | expect(selector).to.have.length(0);
122 |
123 | selector = collectDocumentSelectors([{ scheme: { key: "value" } }]);
124 | expect(selector).to.have.length(0);
125 |
126 | selector = collectDocumentSelectors([{ language: 12 }]);
127 | expect(selector).to.have.length(0);
128 |
129 | selector = collectDocumentSelectors([{ language: { key: "value" } }]);
130 | expect(selector).to.have.length(0);
131 |
132 | selector = collectDocumentSelectors([{ pattern: 12 }]);
133 | expect(selector).to.have.length(0);
134 |
135 | selector = collectDocumentSelectors([{ pattern: { key: "value" } }]);
136 | expect(selector).to.have.length(0);
137 | });
138 |
139 | it ('Should collect multiple document selectors', () => {
140 | const selector: DocumentSelector = collectDocumentSelectors([
141 | { scheme: "file", language: "quarkus-properties", pattern: "**/*.properties" }, // valid
142 | { language: "my-properties" }, // valid
143 | "document-selector-string", // valid
144 | { key: "value" }, // invalid
145 | 12 // invalid
146 | ]);
147 |
148 | expect(selector).to.have.length(3);
149 |
150 | expect(selector[0]).to.have.all.keys(["scheme", "language", "pattern"]);
151 | expect((selector[0] as TextDocumentFilter).scheme).to.equal("file");
152 | expect((selector[0] as TextDocumentFilter).language).to.equal("quarkus-properties");
153 | expect((selector[0] as TextDocumentFilter).pattern).to.equal("**/*.properties");
154 |
155 | expect(selector[1]).to.have.all.keys(["language"]);
156 | expect((selector[1] as TextDocumentFilter).language).to.equal("my-properties");
157 |
158 | expect(selector[2]).to.be.a('string');
159 | expect(selector[2]).to.equal("document-selector-string");
160 | });
161 |
162 | /**
163 | * Returns the DocumentSelector created from the provided `pluginDocumentSelector`.
164 | *
165 | * `pluginDocumentSelector` represents the DocumentSelector that other VS Code
166 | * extensions would contribute to vscode-microprofile.
167 | *
168 | * @param pluginDocumentSelector array of objects to create a DocumentSelector from.
169 | */
170 | function collectDocumentSelectors(pluginDocumentSelector: unknown[]): DocumentSelector {
171 | const fakePlugin: vscode.Extension = {
172 | id: "fake-no-plugin-extension",
173 | extensionUri: vscode.Uri.parse("https://example.org"),
174 | extensionPath: "",
175 | isActive: true,
176 | packageJSON: {
177 | contributes: {
178 | microprofile: {
179 | documentSelector: pluginDocumentSelector
180 | }
181 | }
182 | },
183 | exports: "",
184 | activate: null,
185 | extensionKind: vscode.ExtensionKind.Workspace,
186 | };
187 |
188 | const contribution: MicroProfileContribution[] = plugin.collectMicroProfileJavaExtensions([ fakePlugin ]);
189 | expect(contribution).to.have.length(1);
190 |
191 | return contribution[0].documentSelector;
192 | }
193 | });
194 |
--------------------------------------------------------------------------------
/src/test/suite/languageServer/plugin.test.ts:
--------------------------------------------------------------------------------
1 | import { expect } from "chai";
2 | import * as fs from "fs";
3 | import * as path from "path";
4 | import * as vscode from "vscode";
5 | import { TextDocumentFilter } from "vscode-languageclient";
6 | import * as plugin from "../../../languageServer/plugin";
7 | import { MicroProfileContribution } from "../../../languageServer/plugin";
8 |
9 | describe("Language server plugin", () => {
10 | it('Should collect lsp4mp extensions', () => {
11 | const quarkusPackageJSON = JSON.parse(
12 | fs.readFileSync(
13 | path.join(__dirname, "../../../../src/test/resources/quarkus-package.json"),
14 | "utf8"
15 | )
16 | );
17 |
18 | const fakeVscodeQuarkus: vscode.Extension = {
19 | id: "fake-vscode-quarkus",
20 | extensionPath: "",
21 | extensionUri: vscode.Uri.parse("https://example.org"),
22 | isActive: true,
23 | packageJSON: quarkusPackageJSON,
24 | exports: "",
25 | activate: null,
26 | extensionKind: vscode.ExtensionKind.Workspace,
27 | };
28 |
29 | const noPluginPackageJSON = JSON.parse(
30 | fs.readFileSync(
31 | path.join(__dirname, "../../../../src/test/resources/no-lsp4mp-extension-package.json"),
32 | "utf8"
33 | )
34 | );
35 |
36 | const fakeNoPluginExtension: vscode.Extension = {
37 | id: "fake-no-plugin-extension",
38 | extensionUri: vscode.Uri.parse("https://example.org"),
39 | extensionPath: "",
40 | isActive: true,
41 | packageJSON: noPluginPackageJSON,
42 | exports: "",
43 | activate: null,
44 | extensionKind: vscode.ExtensionKind.Workspace,
45 | };
46 |
47 | const extensions = [fakeVscodeQuarkus, fakeNoPluginExtension];
48 | const result: MicroProfileContribution[] = plugin.collectMicroProfileJavaExtensions(extensions);
49 | expect(result).to.have.length(1);
50 |
51 | expect(result[0].jarExtensions).to.have.length(1);
52 |
53 | const expectedPath: string = path.join('server', 'com.redhat.quarkus.ls.jar').replace("\\", "\\\\");
54 | expect(result[0].jarExtensions[0]).to.be.a("string").and.match(new RegExp(`${expectedPath}$`), `String should end with "${expectedPath}".`);
55 |
56 | expect(result[0].documentSelector).to.have.length(1);
57 | expect(result[0].documentSelector[0]).has.all.keys(["scheme", "language"]);
58 |
59 | const TextDocumentFilter: TextDocumentFilter = result[0].documentSelector[0] as TextDocumentFilter;
60 | expect(TextDocumentFilter.scheme).to.be.a("string").and.equal("file");
61 | expect(TextDocumentFilter.language).to.be.a("string").and.equal("quarkus-properties");
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/src/test/suite/languageServer/requirements.test.ts:
--------------------------------------------------------------------------------
1 | import { expect } from "chai";
2 | import { parseMajorVersion } from "../../../languageServer/requirements";
3 |
4 | describe("Language server java requirements", () => {
5 | it("Should parse the correct java version from OpenJDK 1.8", () => {
6 | const openJDK8 = `openjdk version "1.8.0_212"
7 | OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
8 | OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)`;
9 |
10 | expect(parseMajorVersion(openJDK8)).to.equal(8);
11 | });
12 |
13 | it("Should parse the correct java version from AdoptOpenJDK with OpenJ9", () => {
14 | const adoptOpenJ9 = `openjdk version "11.0.6" 2020-01-14
15 | OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
16 | Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.18.1, JRE 11 Mac OS X amd64-64-Bit Compressed References 20200122_450 (JIT enabled, AOT enabled)
17 | OpenJ9 - 51a5857d2
18 | OMR - 7a1b0239a
19 | JCL - da35e0c380 based on jdk-11.0.6+10)`;
20 |
21 | expect(parseMajorVersion(adoptOpenJ9)).to.equal(11);
22 | });
23 |
24 | it("Should parse the correct java version from Java SE 12", () => {
25 | const javaSE12 = `java version "12.0.1" 2019-04-16
26 | Java(TM) SE Runtime Environment (build 12.0.1+12)
27 | Java HotSpot(TM) 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing)`;
28 |
29 | expect(parseMajorVersion(javaSE12)).to.equal(12);
30 | });
31 |
32 | it("Should return 0 if it cannot find a java version", () => {
33 | const javaNotFound = "bash: java: command not found";
34 |
35 | expect(parseMajorVersion(javaNotFound)).to.equal(0);
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/src/util/javaServerMode.ts:
--------------------------------------------------------------------------------
1 | import { window, commands } from "vscode";
2 | import { JavaExtensionAPI } from "../extension";
3 |
4 | export const JAVA_EXTENSION_ID = "redhat.java";
5 |
6 | export enum ServerMode {
7 | STANDARD = "Standard",
8 | LIGHTWEIGHT = "LightWeight",
9 | HYBRID = "Hybrid",
10 | }
11 |
12 | /**
13 | * Waits for the java language server to launch in standard mode
14 | * Before activating Tools for MicroProfile.
15 | * If java ls was started in lightweight mode, It will prompt user to switch
16 | */
17 | export async function waitForStandardMode(api: JavaExtensionAPI): Promise {
18 | // If hybrid, standard mode is being launched. Wait for standard mode then resolve.
19 | if (api.serverMode === ServerMode.HYBRID) {
20 | return new Promise((resolve) => {
21 | api.onDidServerModeChange((mode: string) => {
22 | if (mode === ServerMode.STANDARD) {
23 | resolve();
24 | }
25 | });
26 | });
27 | // If Lightweight. Prompt to switch then wait for Standard mode.
28 | // Even if they do not select Yes on the prompt. This still waits for standard mode
29 | // since standard mode switch can be triggered other ways.
30 | } else if (api.serverMode === ServerMode.LIGHTWEIGHT) {
31 | window.showInformationMessage(
32 | "Tools for MicroProfile requires the Java language server to run in Standard mode. " +
33 | "Do you want to switch it to Standard mode now?",
34 | "Yes",
35 | "Later"
36 | )
37 | .then((answer) => {
38 | if (answer === "Yes") {
39 | commands.executeCommand("java.server.mode.switch", ServerMode.STANDARD, true);
40 | }
41 | });
42 | return new Promise((resolve) => {
43 | api.onDidServerModeChange((mode: string) => {
44 | if (mode === ServerMode.STANDARD) {
45 | resolve();
46 | }
47 | });
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/util/telemetry.ts:
--------------------------------------------------------------------------------
1 | import { TelemetryService } from "@redhat-developer/vscode-redhat-telemetry/lib";
2 |
3 | const CODE_ACTION_TELEMETRY_EVENT = 'codeAction';
4 | const SUCCEED_VALUE = "succeeded";
5 | const FAIL_VALUE = "failed";
6 |
7 | /**
8 | * Sends a telemetry event to indicate that the given code action was applied.
9 | *
10 | * @param telemetryService the telemetry service
11 | * @param codeActionId the id of the type of code action (not the name, since that might contain context such as variable names)
12 | * @param succeeded true if the code action was applied successfully, and false otherwise
13 | * @param error the error message if the code action has failed
14 | */
15 | export async function sendCodeActionTelemetry(telemetryService: TelemetryService, codeActionId: string, succeeded: boolean, error?) {
16 | telemetryService.send({
17 | name: CODE_ACTION_TELEMETRY_EVENT,
18 | properties: {
19 | codeActionId: codeActionId,
20 | status: succeeded ? SUCCEED_VALUE : FAIL_VALUE,
21 | error_message: error ? `${error}` : undefined
22 | }
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/src/util/workspaceUtils.ts:
--------------------------------------------------------------------------------
1 | import { RelativePattern, Uri, workspace, WorkspaceFolder } from "vscode";
2 |
3 | /**
4 | * Returns a list of all files that match the given glob in the given workspace.
5 | *
6 | * @param workspaceFolder the workspace to search
7 | * @param glob the glob of the files to match
8 | * @returns a list of all files that match the given glob in the given workspace
9 | */
10 | export async function getFilePathsFromWorkspace(
11 | workspaceFolder: WorkspaceFolder,
12 | glob: string
13 | ): Promise {
14 | return await getFilePathsFromFolder(workspaceFolder.uri.fsPath, glob);
15 | }
16 |
17 | /**
18 | * Returns a list of all files that match the given glob in the given folder.
19 | *
20 | * @param folderPath the folder to search
21 | * @param glob the glob of the files to match
22 | * @returns a list of all files that match the given glob in the given folder
23 | */
24 | export async function getFilePathsFromFolder(
25 | folderPath: string,
26 | glob: string
27 | ): Promise {
28 | return await workspace.findFiles(new RelativePattern(folderPath, glob), null);
29 | }
30 |
--------------------------------------------------------------------------------
/src/yaml/YamlConstants.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Red Hat, Inc. and others.
3 |
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 |
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import * as vscode from 'vscode';
17 |
18 | export const MICROPROFILE_SCHEMA = 'microprofile';
19 | export const MICROPROFILE_SCHEMA_PREFIX = MICROPROFILE_SCHEMA + '://schema/';
20 | export const VSCODE_YAML_EXTENSION_ID = 'redhat.vscode-yaml';
21 | export const VSCODE_YAML_DISPLAY_NAME = 'YAML Support by Red Hat';
22 | export const VSCODE_YAML_NOT_INSTALLED_MESSAGE = `For application.yaml support, please install '${VSCODE_YAML_DISPLAY_NAME}' and reload ${vscode.env.appName}.`;
23 | export const VSCODE_YAML_LOW_VERSION_MESSAGE = `The installed version of '${VSCODE_YAML_DISPLAY_NAME}' doesn't support multiple schemas. Please install the latest version and reload ${vscode.env.appName}.`;
24 | export const VSCODE_YAML_NO_REGISTRATION_MESSAGE = `The installed version of '${VSCODE_YAML_DISPLAY_NAME}' doesn't support MicroProfile Intellisense. Please install the latest version and reload ${vscode.env.appName}.`;
25 | export const VSCODE_YAML_INSTALL_SUCCESS = `Successfully installed '${VSCODE_YAML_DISPLAY_NAME}'. Please reload ${vscode.env.appName}.`;
--------------------------------------------------------------------------------
/src/yaml/YamlSchema.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020 Red Hat, Inc. and others.
3 |
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 |
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import * as vscode from 'vscode';
17 | import * as path from 'path';
18 | import * as semver from 'semver';
19 |
20 | import {
21 | VSCODE_YAML_EXTENSION_ID,
22 | VSCODE_YAML_DISPLAY_NAME,
23 | VSCODE_YAML_NOT_INSTALLED_MESSAGE,
24 | VSCODE_YAML_LOW_VERSION_MESSAGE,
25 | VSCODE_YAML_NO_REGISTRATION_MESSAGE,
26 | VSCODE_YAML_INSTALL_SUCCESS,
27 | MICROPROFILE_SCHEMA,
28 | MICROPROFILE_SCHEMA_PREFIX
29 | } from "./YamlConstants";
30 |
31 | import { Uri } from 'vscode';
32 | import { LanguageClient } from 'vscode-languageclient/node';
33 | import * as MicroProfileLS from '../definitions/microProfileLSRequestNames';
34 |
35 | // The function signature exposed by vscode-yaml:
36 | // 1. the requestSchema api will be called by vscode-yaml extension to decide whether the schema can be handled by this
37 | // contributor, if it returns undefined, means it doesn't support this yaml file, vscode-yaml will ask other contributors
38 | // 2. the requestSchemaContent api will give the parameter uri returned by the first api, and ask for the json content(after stringify) of
39 | // the schema
40 | declare type YamlSchemaContributor = (schema: string,
41 | requestSchema: (resource: string) => string | undefined,
42 | requestSchemaContent: (uri: string) => Promise) => void;
43 |
44 | interface JsonSchemaForProjectInfo {
45 | projectURI: string;
46 | jsonSchema: string;
47 | }
48 |
49 | export interface MicroProfilePropertiesChangeEvent {
50 | projectURIs: Array;
51 | type: Array;
52 | }
53 | export enum MicroProfilePropertiesScopeEnum {
54 | sources = 1,
55 | dependencies = 2
56 | }
57 |
58 | // Yaml Schema cache which caches YAML Schema (in JSON format) for application.yaml files
59 | // which belong to a MicroProfile project.
60 | export class YamlSchemaCache {
61 | private readonly cache = new Map();
62 | private _languageClient: LanguageClient;
63 | public set languageClient(languageClient: LanguageClient) {
64 | this._languageClient = languageClient;
65 | }
66 |
67 | /**
68 | * Returns the JSON Schema to use for the given application yaml file URI.
69 | *
70 | * @param applicationYamlUri the application yaml file URI
71 | */
72 | public async getSchema(applicationYamlUri: string): Promise {
73 | const yamlSchema = this.cache.get(applicationYamlUri);
74 | if (yamlSchema) {
75 | return yamlSchema.jsonSchema;
76 | }
77 | if (!this._languageClient) {
78 | return undefined;
79 | }
80 | const params = {
81 | uri: applicationYamlUri,
82 | scopes: [1, 2]
83 | };
84 | return this._languageClient.sendRequest(MicroProfileLS.JSON_SCHEMA_FOR_PROJECT_INFO_REQUEST, params)
85 | .then((result: JsonSchemaForProjectInfo) => {
86 | const jsonSchema = result.jsonSchema;
87 | this.cache.set(applicationYamlUri, result);
88 | return jsonSchema;
89 | }, (err) => {
90 | console.error(`Error while consumming '${MicroProfileLS.JSON_SCHEMA_FOR_PROJECT_INFO_REQUEST}' request: ${err.message}`);
91 | return null;
92 | });
93 | }
94 |
95 | /**
96 | * Evict the cache according to the classpath changed of the given project URIs
97 | *
98 | * @param event the properties change event
99 | */
100 | public evict(event: MicroProfilePropertiesChangeEvent): void {
101 | // collect all application.yaml uris which belong to the event project URIs
102 | // and evict them from the cache.
103 | this.cache.forEach((jsonSchema: JsonSchemaForProjectInfo, uri: string) => {
104 | if (event.projectURIs.includes(jsonSchema.projectURI)) {
105 | this.cache.delete(uri);
106 | }
107 | });
108 | }
109 | }
110 |
111 | const yamlSchemaCache = new YamlSchemaCache();
112 | let listener: vscode.Disposable|undefined = undefined;
113 |
114 | export async function registerYamlSchemaSupport(){
115 | const yamlPlugin = await activateYamlExtension();
116 | if (!yamlPlugin || !yamlPlugin.registerContributor) {
117 | // activateYamlExtension has already alerted users about errors.
118 | return undefined;
119 | }
120 | // register for microprofile schema provider
121 | yamlPlugin.registerContributor(MICROPROFILE_SCHEMA, requestYamlSchemaUriCallback, requestYamlSchemaContentCallback);
122 | }
123 |
124 | // find redhat.vscode-yaml extension and try to activate it to get the yaml contributor
125 | // this function should only be called once when vscode-microprofile activates
126 | async function activateYamlExtension(): Promise<{ registerContributor: YamlSchemaContributor } | undefined> {
127 | const ext = vscode.extensions.getExtension(VSCODE_YAML_EXTENSION_ID);
128 | const isApplicationYamlOpened: boolean = isEditorApplicationYaml(vscode.window.activeTextEditor);
129 |
130 | if (!ext) {
131 | if (isApplicationYamlOpened) {
132 | await askInstallVSCodeYaml(VSCODE_YAML_NOT_INSTALLED_MESSAGE);
133 | } else {
134 | listener = createInstallListener(VSCODE_YAML_NOT_INSTALLED_MESSAGE);
135 | }
136 | return undefined;
137 | }
138 |
139 | if (ext.packageJSON.version && !semver.gte(ext.packageJSON.version, '0.0.15')) {
140 | if (isApplicationYamlOpened) {
141 | await askInstallVSCodeYaml(VSCODE_YAML_LOW_VERSION_MESSAGE);
142 | } else {
143 | listener = createInstallListener(VSCODE_YAML_LOW_VERSION_MESSAGE);
144 | }
145 | return undefined;
146 | }
147 | const yamlPlugin = await ext.activate();
148 |
149 | if (!yamlPlugin || !yamlPlugin.registerContributor) {
150 | if (isApplicationYamlOpened) {
151 | await askInstallVSCodeYaml(VSCODE_YAML_NO_REGISTRATION_MESSAGE);
152 | } else {
153 | listener = createInstallListener(VSCODE_YAML_NO_REGISTRATION_MESSAGE);
154 | }
155 | return undefined;
156 | }
157 |
158 | return yamlPlugin;
159 | }
160 |
161 | // see docs from YamlSchemaContributor
162 | function requestYamlSchemaUriCallback(resource: string): string | undefined {
163 | const textEditor = vscode.window.visibleTextEditors.find((editor) => editor.document.uri.toString() === resource);
164 | if (textEditor) {
165 | if (resource.endsWith('application.yaml') || resource.endsWith('application.yml')) {
166 | return MICROPROFILE_SCHEMA_PREFIX + resource;
167 | }
168 | }
169 | return undefined;
170 | }
171 |
172 | // see docs from YamlSchemaContributor
173 | function requestYamlSchemaContentCallback(uri: string): Promise {
174 | const parsedUri = Uri.parse(uri);
175 | if (parsedUri.scheme !== MICROPROFILE_SCHEMA) {
176 | return undefined;
177 | }
178 | if (!parsedUri.path || !parsedUri.path.startsWith('/')) {
179 | return undefined;
180 | }
181 | const applicationYamlUri = uri.substring(MICROPROFILE_SCHEMA_PREFIX.length);
182 | return yamlSchemaCache.getSchema(applicationYamlUri);
183 | }
184 |
185 | function isEditorApplicationYaml(editor: vscode.TextEditor|undefined): boolean {
186 | if (!editor) {
187 | return false;
188 | }
189 | const currentFileName: string = editor.document.fileName;
190 | if (!currentFileName) return false;
191 | return currentFileName.endsWith(path.sep + 'application.yaml') || currentFileName.endsWith(path.sep + 'application.yml');
192 | }
193 |
194 | function createInstallListener(message: string): vscode.Disposable {
195 | return vscode.window.onDidChangeActiveTextEditor(async (change: vscode.TextEditor | undefined) => {
196 | if (!change) return;
197 |
198 | if (isEditorApplicationYaml(change)) {
199 | await askInstallVSCodeYaml(message);
200 | }
201 | });
202 | }
203 |
204 | async function askInstallVSCodeYaml(message: string): Promise {
205 | const INSTALL = 'Install';
206 | const RELOAD = 'Reload';
207 |
208 | const response: string|undefined = await vscode.window.showWarningMessage(message, INSTALL);
209 | if (response === INSTALL) {
210 | await installVSCodeYaml();
211 | if (listener) listener.dispose();
212 | const response: string|undefined = await vscode.window.showInformationMessage(VSCODE_YAML_INSTALL_SUCCESS, RELOAD);
213 | if (response === RELOAD) {
214 | await vscode.commands.executeCommand('workbench.action.reloadWindow');
215 | }
216 | }
217 | }
218 |
219 | async function installVSCodeYaml(): Promise {
220 | await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: `Installing '${VSCODE_YAML_DISPLAY_NAME}'...`}, () => {
221 | return vscode.commands.executeCommand('workbench.extensions.installExtension', VSCODE_YAML_EXTENSION_ID);
222 | });
223 | }
224 |
225 | export async function getYamlSchemaCache(): Promise {
226 | return yamlSchemaCache;
227 | }
228 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": [
5 | "es6"
6 | ],
7 | "module": "commonjs",
8 | "moduleResolution": "node",
9 | "outDir": "out",
10 | "sourceMap": true,
11 | "plugins": []
12 | },
13 | "exclude": [
14 | "node_modules",
15 | "server",
16 | "test-resources",
17 | ".vscode-test"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
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 |
6 | //@ts-check
7 |
8 | "use strict";
9 |
10 | const path = require("path");
11 | const ESLintWebpackPlugin = require('eslint-webpack-plugin');
12 |
13 | /**@type {import('webpack').Configuration}*/
14 | const config = {
15 | target: "node", // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
16 | node: {
17 | __dirname: false,
18 | __filename: false,
19 | },
20 | entry: "./src/extension.ts", // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
21 | output: {
22 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
23 | path: path.resolve(__dirname, "dist"),
24 | filename: "extension.js",
25 | libraryTarget: "commonjs2",
26 | devtoolModuleFilenameTemplate: "../[resource-path]",
27 | },
28 | devtool: "source-map",
29 | externals: {
30 | vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
31 | },
32 | resolve: {
33 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
34 | extensions: [".ts", ".js"],
35 | },
36 | module: {
37 | rules: [
38 | {
39 | test: /\.ts$/,
40 | exclude: /node_modules/,
41 | use: [
42 | {
43 | loader: "ts-loader",
44 | },
45 | ],
46 | },
47 | ],
48 | },
49 | infrastructureLogging: {
50 | level: "log",
51 | },
52 | plugins: [
53 | new ESLintWebpackPlugin({
54 | extensions: [".ts", ".js"],
55 | })
56 | ]
57 | };
58 |
59 | module.exports = config;
60 |
--------------------------------------------------------------------------------