├── .azure-pipelines ├── ci.yml ├── nightly.yml └── rc.yml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── Endgame.md │ ├── Feature_request.md │ └── Question.md ├── dependabot.yml ├── no-response.yml └── workflows │ ├── issueSnapshot.yml │ └── no-response.yml ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── Support.md ├── ThirdPartyNotices.txt ├── caption.dark.svg ├── caption.light.svg ├── logo.png ├── logo.svg ├── package-lock.json ├── package.json ├── package.nls.json ├── release-notes ├── v0.5.0.md ├── v0.5.0 │ ├── attachsource.gif │ ├── dependency-viewer.gif │ ├── intellicode.gif │ ├── java-overview.gif │ ├── junit5-displayname.png │ ├── junit5-parameterizedtest.png │ ├── launch-with-codelens.gif │ ├── logpoints.gif │ ├── renaming.gif │ └── testng.gif ├── v0.6.0.md ├── v0.6.0 │ ├── bulk.gen.getter.setter.gif │ ├── hide.temp.files.png │ ├── maven-plugin-goals.png │ ├── multiple.main.entry.gif │ ├── multiple.source.folder.gif │ ├── navigate.to.source.gif │ ├── pom-dependency-completion.gif │ └── standalone.file.support.gif ├── v0.7.0.md ├── v0.7.0 │ ├── debug.gtd.stack.trace.gif │ ├── java.convert.static.import.gif │ ├── java.debug.exception.view.gif │ ├── java.debug.logical.structure.gif │ ├── java.folding.range.gif │ ├── java.generate.tostring.gif │ ├── java.hashcode.equals.gif │ ├── java.implement.methods.gif │ ├── java.organize.imports.gif │ ├── jdk.acquisition.guide.gif │ ├── maven.add.dependency.gif │ └── maven.debug.goals.gif ├── v0.9.0.md └── v0.9.0 │ ├── call-hierarchy.gif │ ├── check-build-status.gif │ ├── create-class.gif │ ├── data-breakpoint.png │ ├── go-to-super-implementation.gif │ ├── reference-jar-files.gif │ ├── sonarlint.gif │ ├── syntax-mode-indicator.png │ ├── syntax-mode-switch.png │ └── syntax-server-startup.gif ├── resources ├── gutter-blue.svg └── gutter-red.svg ├── scripts ├── prepare-nightly-build.js └── update-third-party-notice.js ├── src ├── assets │ └── vscode.scss ├── beginner-tips │ ├── assets │ │ ├── BeginnerTips.tsx │ │ ├── index.tsx │ │ ├── style.scss │ │ └── tabs │ │ │ ├── CodeEditingPanel.tsx │ │ │ ├── DebuggingPanel.tsx │ │ │ ├── FaqPanel.tsx │ │ │ └── QuickStartPanel.tsx │ └── index.ts ├── commands │ ├── handler.ts │ └── index.ts ├── copilot │ ├── Copilot.ts │ ├── inspect │ │ ├── DocumentRenderer.ts │ │ ├── InspectActionCodeLensProvider.ts │ │ ├── Inspection.ts │ │ ├── InspectionCache.ts │ │ ├── InspectionCopilot.ts │ │ ├── SymbolNode.ts │ │ ├── commands.ts │ │ ├── index.ts │ │ └── render │ │ │ ├── CodeLensRenderer.ts │ │ │ ├── DiagnosticRenderer.ts │ │ │ ├── GutterIconRenderer.ts │ │ │ ├── InspectionRenderer.ts │ │ │ └── RulerHighlightRenderer.ts │ └── utils.ts ├── daemon │ ├── clientLog │ │ └── logWatcher.ts │ ├── daemon.ts │ ├── index.ts │ ├── processWatcher.ts │ └── serverLog │ │ ├── logUtils.ts │ │ ├── logWatcher.ts │ │ ├── utils.ts │ │ └── whitelist.ts ├── exp │ ├── TreatmentVariables.ts │ └── index.ts ├── ext-guide │ ├── assets │ │ └── index.ts │ └── index.ts ├── extension.ts ├── formatter-settings │ ├── FormatterConstants.ts │ ├── FormatterConverter.ts │ ├── RemoteProfileProvider.ts │ ├── assets │ │ ├── App.tsx │ │ ├── SpaceDiff.woff2 │ │ ├── app │ │ │ └── store.ts │ │ ├── features │ │ │ └── formatterSettings │ │ │ │ ├── FormatterSettingView.tsx │ │ │ │ ├── components │ │ │ │ ├── Highlight.tsx │ │ │ │ └── Setting.tsx │ │ │ │ └── formatterSettingViewSlice.ts │ │ ├── index.tsx │ │ ├── style.scss │ │ ├── utils.ts │ │ └── whitespace.ts │ ├── index.ts │ ├── types.ts │ └── utils.ts ├── install-jdk │ ├── assets │ │ ├── App.scss │ │ ├── App.tsx │ │ ├── app │ │ │ ├── hooks.ts │ │ │ └── store.ts │ │ ├── features │ │ │ ├── InstallJDKView.tsx │ │ │ ├── components │ │ │ │ ├── AdoptiumJDKPanel.tsx │ │ │ │ └── OtherJDKsPanel.tsx │ │ │ └── installJDKViewSlice.ts │ │ ├── index.tsx │ │ └── vscode.api.ts │ ├── constants.ts │ └── index.ts ├── java-runtime │ ├── assets │ │ ├── ProjectJDKPanel.tsx │ │ ├── ToolingJDKPanel.tsx │ │ ├── components │ │ │ ├── DefaultJDKSelector.tsx │ │ │ └── ProjectTypeHint.tsx │ │ ├── index.ts │ │ ├── style.scss │ │ └── vscode.api.ts │ ├── index.ts │ ├── types.ts │ └── utils │ │ ├── misc.ts │ │ └── upstreamApi.ts ├── misc │ └── index.ts ├── overview │ ├── assets │ │ └── index.ts │ └── index.ts ├── project-settings │ ├── assets │ │ ├── classpath │ │ │ ├── features │ │ │ │ ├── ClasspathConfigurationView.tsx │ │ │ │ ├── classpathConfigurationViewSlice.ts │ │ │ │ └── components │ │ │ │ │ ├── Hint.tsx │ │ │ │ │ ├── JdkRuntime.tsx │ │ │ │ │ ├── Libraries.tsx │ │ │ │ │ ├── Output.tsx │ │ │ │ │ ├── Sources.tsx │ │ │ │ │ └── UnmanagedFolderSources.tsx │ │ │ ├── style.scss │ │ │ └── utils.ts │ │ ├── compiler │ │ │ └── features │ │ │ │ ├── CompilerConfigurationView.tsx │ │ │ │ ├── compilerConfigurationViewSlice.tsx │ │ │ │ └── components │ │ │ │ └── Hint.tsx │ │ ├── index.tsx │ │ ├── mainpage │ │ │ ├── features │ │ │ │ ├── App.tsx │ │ │ │ ├── ProjectSettingView.tsx │ │ │ │ ├── commonSlice.ts │ │ │ │ └── component │ │ │ │ │ ├── Exception.tsx │ │ │ │ │ ├── Footer.tsx │ │ │ │ │ ├── ProjectSelector.tsx │ │ │ │ │ └── SideBar.tsx │ │ │ └── style.scss │ │ ├── maven │ │ │ └── features │ │ │ │ ├── MavenConfigurationView.tsx │ │ │ │ ├── components │ │ │ │ └── Profile.tsx │ │ │ │ └── mavenConfigurationViewSlice.tsx │ │ ├── store.ts │ │ ├── utils.scss │ │ └── vscode │ │ │ └── utils.ts │ ├── handlers │ │ ├── ClasspathRequestHandler.ts │ │ ├── CompilerRequestHandler.ts │ │ └── MavenRequestHandler.ts │ ├── projectSettingsView.ts │ └── types.ts ├── providers │ └── CodeActionProvider.ts ├── recommendation │ ├── handler.ts │ ├── index.ts │ └── xml.ts ├── utils │ ├── adoptiumApi.ts │ ├── extension.ts │ ├── globalState.ts │ ├── idle.ts │ ├── index.ts │ ├── jdt.ts │ ├── release-notes │ │ └── index.ts │ ├── scheduler.ts │ └── webview.ts └── welcome │ ├── assets │ ├── components │ │ ├── ControllerPanel.tsx │ │ ├── GetStartedPage.tsx │ │ ├── Header.tsx │ │ ├── NavigationPanel.tsx │ │ ├── QuickActionPanel.tsx │ │ ├── SocialMediaPanel.tsx │ │ └── TourPage.tsx │ ├── index.ts │ ├── resources │ │ ├── debugger.png │ │ ├── done.svg │ │ ├── open-project.png │ │ ├── project-manager.png │ │ └── testing.png │ ├── style.scss │ └── utils.ts │ └── index.ts ├── tsconfig.json ├── tslint.json ├── vscode.d.ts ├── walkthrough ├── codeAction.svg ├── debugAndTest.svg ├── extensions.svg ├── helpCenter.svg ├── helpCenterMac.svg ├── ok.svg ├── projects.svg └── runtime.md ├── webpack.config.js └── webview-resources ├── highlight.css └── java-formatter.xml /.azure-pipelines/ci.yml: -------------------------------------------------------------------------------- 1 | name: $(Date:yyyyMMdd).$(Rev:r) 2 | variables: 3 | - name: Codeql.Enabled 4 | value: true 5 | resources: 6 | repositories: 7 | - repository: self 8 | type: git 9 | ref: refs/heads/main 10 | - repository: 1esPipelines 11 | type: git 12 | name: 1ESPipelineTemplates/1ESPipelineTemplates 13 | ref: refs/tags/release 14 | trigger: 15 | branches: 16 | include: 17 | - main 18 | extends: 19 | template: v1/1ES.Unofficial.PipelineTemplate.yml@1esPipelines 20 | parameters: 21 | pool: 22 | os: linux 23 | name: 1ES_JavaTooling_Pool 24 | image: 1ES_JavaTooling_Ubuntu-2004 25 | sdl: 26 | sourceAnalysisPool: 27 | name: 1ES_JavaTooling_Pool 28 | image: 1ES_JavaTooling_Windows_2022 29 | os: windows 30 | customBuildTags: 31 | - MigrationTooling-mseng-VSJava-9247-Tool 32 | stages: 33 | - stage: Build 34 | jobs: 35 | - job: Job_1 36 | displayName: Agent job 1 37 | templateContext: 38 | outputs: 39 | - output: pipelineArtifact 40 | artifactName: drop 41 | targetPath: $(Build.ArtifactStagingDirectory) 42 | displayName: "Publish Artifact: drop" 43 | steps: 44 | - checkout: self 45 | fetchTags: true 46 | - task: NodeTool@0 47 | displayName: Use Node 20.x 48 | inputs: 49 | versionSpec: 20.x 50 | - task: Npm@1 51 | displayName: npm install 52 | inputs: 53 | verbose: false 54 | - task: CmdLine@2 55 | displayName: Command Line Script 56 | inputs: 57 | script: npx @vscode/vsce@latest package 58 | - task: CopyFiles@2 59 | displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)" 60 | inputs: 61 | Contents: "*.vsix" 62 | TargetFolder: $(Build.ArtifactStagingDirectory) 63 | -------------------------------------------------------------------------------- /.azure-pipelines/rc.yml: -------------------------------------------------------------------------------- 1 | name: $(Date:yyyyMMdd).$(Rev:r) 2 | variables: 3 | - name: Codeql.Enabled 4 | value: true 5 | resources: 6 | repositories: 7 | - repository: self 8 | type: git 9 | ref: refs/heads/main 10 | - repository: MicroBuildTemplate 11 | type: git 12 | name: 1ESPipelineTemplates/MicroBuildTemplate 13 | trigger: none 14 | extends: 15 | template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate 16 | parameters: 17 | pool: 18 | name: MSEngSS-MicroBuild2022-1ES 19 | stages: 20 | - stage: Build 21 | jobs: 22 | - job: Job_1 23 | displayName: Agent job 1 24 | templateContext: 25 | mb: 26 | signing: 27 | enabled: true 28 | signType: real 29 | zipSources: false 30 | feedSource: 'https://mseng.pkgs.visualstudio.com/DefaultCollection/_packaging/MicroBuildToolset/nuget/v3/index.json' 31 | outputs: 32 | - output: pipelineArtifact 33 | artifactName: vsix 34 | targetPath: $(Build.ArtifactStagingDirectory) 35 | displayName: "Publish Artifact: vsix" 36 | steps: 37 | - checkout: self 38 | clean: true 39 | fetchTags: false 40 | - task: NodeTool@0 41 | displayName: Use Node 20.x 42 | inputs: 43 | versionSpec: 20.x 44 | - task: Npm@1 45 | displayName: npm install 46 | inputs: 47 | verbose: false 48 | - task: CmdLine@2 49 | displayName: Replace AI Key 50 | inputs: 51 | script: npx json@9.0.6 -I -f package.json -e "this.aiKey=\"%AI_KEY%\"" 52 | - task: CmdLine@2 53 | displayName: VSCE package 54 | inputs: 55 | script: npx @vscode/vsce@latest package -o extension.vsix 56 | ### Copy files for APIScan 57 | - task: CopyFiles@2 58 | displayName: "Copy Files for APIScan" 59 | inputs: 60 | Contents: "*.vsix" 61 | TargetFolder: $(Agent.TempDirectory)/APIScanFiles 62 | condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) 63 | ### Run latest version of APIScan listed at https://www.1eswiki.com/wiki/APIScan_Build_Task 64 | - task: APIScan@2 65 | displayName: Run APIScan 66 | inputs: 67 | softwareFolder: $(Agent.TempDirectory)/APIScanFiles 68 | softwareName: "vscode-java-pack" 69 | softwareVersionNum: "$(Build.BuildId)" 70 | isLargeApp: false 71 | toolVersion: "Latest" 72 | condition: and(succeeded(), ne(variables['DisableAPIScan'], 'true')) 73 | env: 74 | AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret) 75 | - script: npx @vscode/vsce@latest generate-manifest -i extension.vsix -o extension.manifest 76 | displayName: 'Generate extension manifest' 77 | - script: copy extension.manifest extension.signature.p7s 78 | displayName: 'Prepare manifest for signing' 79 | - task: CmdLine@2 80 | displayName: Sign extension 81 | inputs: 82 | script: dotnet %MBSIGN_APPFOLDER%/ddsignfiles.dll /file:extension.signature.p7s /certs:4014052 83 | - task: CopyFiles@2 84 | displayName: "Copy Files to: $(Build.ArtifactStagingDirectory)" 85 | inputs: 86 | Contents: | 87 | extension.vsix 88 | extension.manifest 89 | extension.signature.p7s 90 | TargetFolder: $(Build.ArtifactStagingDirectory) 91 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jdneo @testforstephen 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: Bug 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 13 | 14 | **Environment:** 15 | 16 | - VS Code Version: 17 | - Extension Version: 18 | - JDK Type & Version: 19 | - OS Type & Version: 20 | 21 | **Step to Reproduce:** 22 | 23 | **Expected Behavior:** 24 | 25 | **Actual Behavior:** 26 | 27 | **Related Issues:** 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Endgame.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Endgame 3 | about: Monthly endgame issue template 4 | title: " 2023 Endgame" 5 | labels: endgame 6 | assignees: jdneo, testforstephen 7 | 8 | --- 9 | 10 | Legends of status: 11 | Mark | Description 12 | -- | -- 13 | ✅ | verified 14 | 🚢 | shipped/released 15 | ✋ | blocked 16 | 🏃 | work in progress 17 | 18 | 19 | ## Verification items 20 | #### Extension Pack 21 | verifier: 22 | 23 | #### Project Manager for Java 24 | verifier: 25 | 26 | #### Debugger for Java 27 | verifier: 28 | 29 | #### Maven for Java 30 | verifier: 31 | 32 | #### Gradle for Java 33 | verifier: 34 | 35 | #### Test Runner for Java 36 | verifier: 37 | 38 | #### Spring Boot Dashboard 39 | verifier: 40 | 41 | ## Verification follow-ups 42 | - [ ] Extension Pack 43 | - [ ] Project Manager for Java 44 | - [ ] Debugger for Java 45 | - [ ] Maven for Java 46 | - [ ] Gradle for Java 47 | - [ ] Test Runner for Java 48 | - [ ] Spring Boot Dashboard 49 | 50 | ## Release 51 | - [ ] Extension Pack 52 | - [ ] Project Manager for Java 53 | - [ ] Debugger for Java 54 | - [ ] Maven for Java 55 | - [ ] Gradle for Java 56 | - [ ] Test Runner for Java 57 | - [ ] Spring Boot Dashboard 58 | 59 | ## External Contributions 60 | 61 | ## Post-Release Tasks 62 | Please update dependencies for each project to avoid vulnerabilities. For any reason not to update, create and track corresponding issues in each repo. 63 | - [ ] Extension Pack @testforstephen 64 | - [ ] Project Manager for Java @jdneo 65 | - [ ] Debugger for Java @testforstephen 66 | - [ ] Maven for Java @testforstephen 67 | - [ ] Gradle for Java @jdneo 68 | - [ ] Test Runner for Java @jdneo 69 | - [ ] LSIF Java indexer @jdneo 70 | - [ ] Spring Extensions @testforstephen 71 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: Feature request 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Suggestion 11 | 12 | 13 | 14 | ## Use Cases 15 | 16 | 20 | 21 | ## Examples 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a quesion of how-tos. 4 | title: Question 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Before asking a question, search in existing issues for similar questions: https://github.com/Microsoft/vscode-java-pack/issues?q=is%3Aissue+ 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | daysUntilClose: 14 2 | responseRequiredLabel: needs more info 3 | closeComment: > 4 | This issue has been closed automatically because it needs more information and has not had recent activity. Please reach out if you have or find the answers we need so that we can investigate further. -------------------------------------------------------------------------------- /.github/workflows/issueSnapshot.yml: -------------------------------------------------------------------------------- 1 | name: Take snapshot of open issues 2 | on: 3 | schedule: 4 | - cron: '0 8 1 * *' 5 | workflow_dispatch: 6 | jobs: 7 | dump_issues: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Take issue snapshot 11 | run: | 12 | gh issue list -R $GITHUB_REPOSITORY --limit 1000 --search "is:issue is:open sort:reactions-+1-desc" --json number,url,reactionGroups,title,labels > $REPO.$(date +"%Y-%m-%d").json 13 | env: 14 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | REPO: ${{ github.event.repository.name }} 16 | - name: Save artifacts 17 | uses: actions/upload-artifact@v3 18 | with: 19 | path: ./*.json 20 | retention-days: 1 21 | - name: Log in to Azure 22 | uses: azure/login@v1 23 | with: 24 | creds: ${{ secrets.AZURE_CREDS }} 25 | - name: Upload to Azure 26 | uses: azure/CLI@v1 27 | with: 28 | inlineScript: | 29 | az storage blob upload-batch --account-name ${{ vars.AZURE_STORAGE_ACCOUNT_NAME }} --auth-mode login -d ${{ vars.AZURE_STORAGE_CONTAINER_NAME }} -s . 30 | -------------------------------------------------------------------------------- /.github/workflows/no-response.yml: -------------------------------------------------------------------------------- 1 | name: No Response 2 | 3 | # **What it does**: Closes issues where the original author doesn't respond to a request for information. 4 | # **Why we have it**: To remove the need for maintainers to remember to check back on issues periodically to see if contributors have responded. 5 | # **Who does it impact**: Everyone that works on docs or docs-internal. 6 | 7 | on: 8 | issue_comment: 9 | types: [created] 10 | schedule: 11 | # Schedule for five minutes after the hour, every hour 12 | - cron: '0 0 * * *' 13 | 14 | jobs: 15 | noResponse: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: lee-dohm/no-response@v0.5.0 19 | with: 20 | token: ${{ github.token }} 21 | daysUntilClose: 14 # Number of days of inactivity before an Issue is closed for lack of response 22 | responseRequiredLabel: "needs more info" # Label indicating that a response from the original author is required 23 | closeComment: > 24 | This issue has been closed automatically because it needs more information and has not had recent activity. Please reach out if you have or find the answers we need so that we can investigate further. 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | out/ 61 | 62 | .DS_Store 63 | 64 | .vscode-test 65 | 66 | *.vsix 67 | -------------------------------------------------------------------------------- /.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 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.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": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "npm: watch" 20 | }, 21 | { 22 | "name": "Extension Tests", 23 | "type": "extensionHost", 24 | "request": "launch", 25 | "runtimeExecutable": "${execPath}", 26 | "args": [ 27 | "--extensionDevelopmentPath=${workspaceFolder}", 28 | "--extensionTestsPath=${workspaceFolder}/out/test" 29 | ], 30 | "outFiles": [ 31 | "${workspaceFolder}/out/test/**/*.js" 32 | ], 33 | "preLaunchTask": "npm: watch" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /.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 | }, 9 | "cSpell.words": [ 10 | "SDKs", 11 | "classpaths", 12 | "codicon", 13 | "configurator", 14 | "iconify", 15 | "performant", 16 | "redhat", 17 | "reduxjs", 18 | "vscjava", 19 | "vscodeintellicode", 20 | "walkthrough", 21 | "walkthroughs" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.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 | "owner": "typescript", 11 | "pattern":[ 12 | { 13 | "regexp": "\\[tsl\\] ERROR", 14 | "file": 1, 15 | "location": 2, 16 | "message": 3 17 | } 18 | ], 19 | "background": { 20 | "activeOnStart": true, 21 | "beginsPattern": "\\w+", 22 | "endsPattern": "webpack .* compiled" 23 | } 24 | }, 25 | "isBackground": true, 26 | "presentation": { 27 | "reveal": "never" 28 | }, 29 | "group": { 30 | "kind": "build", 31 | "isDefault": true 32 | } 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | release-notes/**/*.gif 2 | release-notes/**/*.png 3 | release-notes/**/*.jpg 4 | node_modules 5 | src 6 | .vscode 7 | .github 8 | .gitignore 9 | package-lock.json 10 | tsconfig.json 11 | tslint.json 12 | webpack.config.ext.js 13 | webpack.config.js 14 | out/**/*.map 15 | *.vsix 16 | scripts 17 | .azure-pipelines/** 18 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------- START OF LICENSE ----------------------------------------- 2 | 3 | vscode-java-pack 4 | 5 | Copyright (c) Microsoft Corporation 6 | All rights reserved. 7 | 8 | MIT License 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | ----------------------------------------------- END OF LICENSE ------------------------------------------ -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | -------------------------------------------------------------------------------- /Support.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 7 | feature request as a new Issue. 8 | 9 | For help and questions about using this project, please see the [`java`+`visual-studio-code` labels on Stack Overflow](https://stackoverflow.com/questions/tagged/visual-studio-code+java) or the [product document](https://code.visualstudio.com/docs/languages/java). 10 | 11 | ## Microsoft Support Policy 12 | 13 | Support for this project is limited to the resources listed above. -------------------------------------------------------------------------------- /caption.dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /caption.light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/logo.png -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /package.nls.json: -------------------------------------------------------------------------------- 1 | { 2 | "walkthrough.title": "Get Started with Java Development", 3 | "walkthrough.description": "Your first steps to set up powerful Java tools in a lightweight, performant editor!", 4 | "walkthrough.java.runtime": "The Extension Pack for Java requires at least one Java runtime to be installed.\n[Install JDK](command:toSide:java.installJdk.fromWalkthrough)", 5 | 6 | "walkthrough.java.projects": "Java Project Explorer helps you to manage your projects and dependencies. It also helps you to create new Java project, classes and packages. \n[View Java Projects](command:javaProjectExplorer.focus)", 7 | 8 | "walkthrough.java.projects.inactive": "Java Project Explorer helps you to manage your projects and dependencies. Create a new project or open an existing folder to see the full features.\n[Open Command Palette](command:workbench.action.quickOpen?%22>java%22)\n__Try searching for 'Create Java Project' or 'Open Folder'__", 9 | 10 | "walkthrough.java.codeActions": "Find available actions for your code in the editor:\n - Open the right-click menu then select \"Refactor...\" or \"Source Action...\".\n - Click on the light bulb💡.", 11 | 12 | "walkthrough.java.debugAndTest":"Run and debug your application using the debugger. [Learn More...](https://aka.ms/java-walkthrough-debug)\nThe [Testing Explorer](command:workbench.view.testing.focus) allows you to view, run and manage all test cases in your project. [Learn More...](https://aka.ms/java-walkthrough-test)\n[Show Run and Debug View](command:workbench.view.debug)", 13 | 14 | "walkthrough.java.extensions": "Install extensions to support additional frameworks such as Spring Boot, Application Servers, key mappings and so on.\n[Browse Recommended Extensions](command:toSide:java.extGuide)", 15 | 16 | "walkthrough.java.more": "✨ Help Center provides tips, resources and links to help you get answers to the most common questions to learn Java on VS Code.\n[Open Help Center](command:java.welcome)" 17 | } 18 | -------------------------------------------------------------------------------- /release-notes/v0.5.0/attachsource.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/attachsource.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/dependency-viewer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/dependency-viewer.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/intellicode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/intellicode.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/java-overview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/java-overview.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/junit5-displayname.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/junit5-displayname.png -------------------------------------------------------------------------------- /release-notes/v0.5.0/junit5-parameterizedtest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/junit5-parameterizedtest.png -------------------------------------------------------------------------------- /release-notes/v0.5.0/launch-with-codelens.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/launch-with-codelens.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/logpoints.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/logpoints.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/renaming.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/renaming.gif -------------------------------------------------------------------------------- /release-notes/v0.5.0/testng.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.5.0/testng.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/bulk.gen.getter.setter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/bulk.gen.getter.setter.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/hide.temp.files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/hide.temp.files.png -------------------------------------------------------------------------------- /release-notes/v0.6.0/maven-plugin-goals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/maven-plugin-goals.png -------------------------------------------------------------------------------- /release-notes/v0.6.0/multiple.main.entry.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/multiple.main.entry.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/multiple.source.folder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/multiple.source.folder.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/navigate.to.source.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/navigate.to.source.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/pom-dependency-completion.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/pom-dependency-completion.gif -------------------------------------------------------------------------------- /release-notes/v0.6.0/standalone.file.support.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.6.0/standalone.file.support.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/debug.gtd.stack.trace.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/debug.gtd.stack.trace.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.convert.static.import.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.convert.static.import.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.debug.exception.view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.debug.exception.view.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.debug.logical.structure.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.debug.logical.structure.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.folding.range.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.folding.range.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.generate.tostring.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.generate.tostring.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.hashcode.equals.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.hashcode.equals.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.implement.methods.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.implement.methods.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/java.organize.imports.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/java.organize.imports.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/jdk.acquisition.guide.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/jdk.acquisition.guide.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/maven.add.dependency.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/maven.add.dependency.gif -------------------------------------------------------------------------------- /release-notes/v0.7.0/maven.debug.goals.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.7.0/maven.debug.goals.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/call-hierarchy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/call-hierarchy.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/check-build-status.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/check-build-status.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/create-class.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/create-class.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/data-breakpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/data-breakpoint.png -------------------------------------------------------------------------------- /release-notes/v0.9.0/go-to-super-implementation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/go-to-super-implementation.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/reference-jar-files.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/reference-jar-files.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/sonarlint.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/sonarlint.gif -------------------------------------------------------------------------------- /release-notes/v0.9.0/syntax-mode-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/syntax-mode-indicator.png -------------------------------------------------------------------------------- /release-notes/v0.9.0/syntax-mode-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/syntax-mode-switch.png -------------------------------------------------------------------------------- /release-notes/v0.9.0/syntax-server-startup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/release-notes/v0.9.0/syntax-server-startup.gif -------------------------------------------------------------------------------- /resources/gutter-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/gutter-red.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /scripts/prepare-nightly-build.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const json = JSON.parse(fs.readFileSync("./package.json").toString()); 4 | const stableVersion = json.version.match(/(\d+)\.(\d+)\.(\d+)/); 5 | const major = stableVersion[1]; 6 | const minor = stableVersion[2]; 7 | 8 | function prependZero(number) { 9 | if (number > 99) { 10 | throw "Unexpected value to prepend with zero"; 11 | } 12 | return `${number < 10 ? "0" : ""}${number}`; 13 | } 14 | 15 | const date = new Date(); 16 | const month = date.getMonth() + 1; 17 | const day = date.getDate(); 18 | const hours = date.getHours(); 19 | patch = `${date.getFullYear()}${prependZero(month)}${prependZero(day)}${prependZero(hours)}`; 20 | 21 | const insiderPackageJson = Object.assign(json, { 22 | version: `${major}.${minor}.${patch}`, 23 | }); 24 | 25 | fs.writeFileSync("./package.insiders.json", JSON.stringify(insiderPackageJson)); -------------------------------------------------------------------------------- /scripts/update-third-party-notice.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const formatRepositoryUrl = (url) => { 4 | if (!url) return url; 5 | url = url.replace(/\/$/, ""); 6 | url = url.replace(/\.git$/, ""); 7 | url = url.replace(/^git\+/, ""); 8 | url = url.replace(/^git:github\.com:/, "https://github.com/"); 9 | url = url.replace(/^git:\/\//, "https://"); 10 | url = url.replace(/^ssh:\/\/git@/, "https://"); 11 | return url; 12 | } 13 | 14 | const packageJSON = require(path.join(__dirname, "..", "package.json")); 15 | 16 | const header = `THIRD-PARTY SOFTWARE NOTICES AND INFORMATION 17 | For ${packageJSON.name} package 18 | 19 | This extension uses Open Source components. You can find the source code of their 20 | open source projects along with the license information below. We acknowledge and 21 | are grateful to these developers for their contribution to open source. 22 | 23 | `; 24 | 25 | const entries = Object.keys(packageJSON.dependencies).map((name, idx) => { 26 | console.log("===>>>"); 27 | console.log(name); 28 | // url 29 | const manifestFile = require(path.join(__dirname, "..", "node_modules", name, "package.json")); 30 | let url = manifestFile.repository?.url ?? manifestFile.repository; 31 | console.log(url, "\t", formatRepositoryUrl(url)); 32 | url = formatRepositoryUrl(url); 33 | 34 | // license 35 | const packageRoot = path.join(__dirname, "..", "node_modules", name); 36 | const files = fs.readdirSync(packageRoot); 37 | const licenseFile = files.find(f => f.match(/^license/i)); 38 | const license = licenseFile ? fs.readFileSync(path.join(packageRoot, licenseFile)) : undefined; 39 | console.log("<<<==="); 40 | return { 41 | name, 42 | url, 43 | license 44 | } 45 | 46 | }); 47 | 48 | const thirdPartyDeps = entries.filter(e => !e.url?.match(/microsoft/i)); 49 | const depsWithLicense = thirdPartyDeps.filter(e => e.name !== undefined && e.license !== undefined); 50 | 51 | const toc = depsWithLicense.map((dep, idx) => { 52 | return `${idx + 1}. ${dep.name} (${dep.url})`; 53 | }).join("\n") + "\n"; 54 | 55 | const licenses = depsWithLicense.map(dep => { 56 | return `${dep.name} NOTICES BEGIN HERE 57 | ============================= 58 | ${dep.license} 59 | ========================================= 60 | END OF ${dep.name} NOTICES AND INFORMATION 61 | `; 62 | }).join("\n"); 63 | 64 | const content = [header, toc, licenses].join("\n"); 65 | fs.writeFileSync(path.join(__dirname, "..", "ThirdPartyNotices.txt"), content); 66 | -------------------------------------------------------------------------------- /src/assets/vscode.scss: -------------------------------------------------------------------------------- 1 | $body-bg: var(--vscode-editor-background); 2 | $body-color: var(--vscode-editor-foreground); 3 | $link-color: var(--vscode-textLink-foreground) !default; 4 | $link-hover-color: $link-color; 5 | $link-hover-decoration: none !default; 6 | 7 | $list-group-bg: var(--vscode-notifications-background) !default; 8 | $list-group-active-color: var(--vscode-notifications-foreground) !default; 9 | $list-group-active-bg: var(--vscode-notifications-border) !default; 10 | $list-group-hover-bg: var(--vscode-list-hoverBackground) !default; 11 | $list-group-action-active-bg: $list-group-bg; 12 | $list-group-border-color: var(--vscode-notifications-background) !default; 13 | $list-group-action-color: var(--vscode-notifications-foreground) !default; 14 | $list-group-item-padding-y: .75rem !default; 15 | $list-group-item-padding-x: 1rem !default; 16 | 17 | $list-group-border-radius: 0 !default; 18 | 19 | $font-size-base: .8rem !default; 20 | 21 | $code-font-size: $font-size-base; 22 | $kbd-bg: var(--vscode-button-background) !default; 23 | $kbd-color: var(--vscode-button-foreground) !default; 24 | $pre-color: var(--vscode-textPreformat-foreground) !default; 25 | 26 | $text-muted: var(--vscode-editorCodeLens-foreground) !default; 27 | 28 | $nav-tabs-link-active-color: var(--vscode-sideBarTitle-foreground); 29 | $nav-tabs-link-active-bg: var(--vscode-sideBar-background); 30 | $nav-tabs-link-active-border-color: var(--vscode-sideBarTitle-foreground) var(--vscode-sideBarTitle-foreground) var(--vscode-sideBar-background) var(--vscode-sideBarTitle-foreground); 31 | $nav-tabs-link-hover-border-color: var(--vscode-sideBarTitle-foreground); 32 | $nav-tabs-border-color: var(--vscode-sideBarTitle-foreground); 33 | 34 | $card-bg: var(--vscode-sideBar-background); 35 | $card-color: var(--vscode-sideBarTitle-foreground); 36 | $card-border-color: var(--vscode-sideBar-border); 37 | 38 | $input-group-addon-bg: var(--vscode-sideBar-background); 39 | $input-group-addon-color: var(--vscode-sideBarTitle-foreground); 40 | 41 | $code-color: var(--vscode-textPreformat-foreground); 42 | 43 | $input-color:var(--vscode-sideBarTitle-foreground); 44 | $input-bg:var(--vscode-sideBar-background); 45 | @import "~bootstrap/scss/bootstrap"; 46 | 47 | -------------------------------------------------------------------------------- /src/beginner-tips/assets/BeginnerTips.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import "./style.scss"; 5 | import { VSCodePanelTab, VSCodePanels, VSCodePanelView } from "@vscode/webview-ui-toolkit/react"; 6 | import React from 'react'; 7 | import CodeEditingPanel from "./tabs/CodeEditingPanel"; 8 | import DebuggingPanel from "./tabs/DebuggingPanel"; 9 | import FaqPanel from "./tabs/FaqPanel"; 10 | import QuickStartPanel from "./tabs/QuickStartPanel"; 11 | 12 | export default function BeginnerTips() { 13 | 14 | return ( 15 |
16 |
17 |

Tips for Beginners

18 |
19 |
20 | 21 | Quick Start 22 | Code Editing 23 | Debugging 24 | FAQ 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 |
40 | ); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/beginner-tips/assets/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from 'react'; 5 | import * as ReactDOM from 'react-dom'; 6 | import BeginnerTips from "./BeginnerTips"; 7 | 8 | ReactDOM.render( 9 | , 10 | document.getElementById('root') as HTMLElement 11 | ); 12 | -------------------------------------------------------------------------------- /src/beginner-tips/assets/style.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | #root { 5 | display: flex; 6 | justify-content: center; 7 | 8 | div.container { 9 | display: flex; 10 | flex-direction: column; 11 | min-height: 100vh; 12 | max-width: 680px; 13 | } 14 | } 15 | 16 | blockquote.card-body { 17 | margin-top: 2rem; 18 | margin: 0 7px 0 5px; 19 | padding: 2px 10px 2px 10px; 20 | border-left: 5px solid; 21 | border-color: rgba(0, 122, 204, 0.5); 22 | background: rgba(127, 127, 127, 0.1); 23 | } 24 | 25 | .font-weight-bold { 26 | font-weight: bold; 27 | } 28 | 29 | .font-weight-light { 30 | font-weight: lighter; 31 | } 32 | 33 | a { 34 | text-decoration: none; 35 | } 36 | 37 | h5 { 38 | font-size: 1rem; 39 | margin-top: 5px; 40 | margin-bottom: 0; 41 | } 42 | 43 | code { 44 | font-family: var(--vscode-editor-font-family); 45 | } 46 | 47 | @import "../../../node_modules/@vscode/codicons/dist/codicon.css"; 48 | -------------------------------------------------------------------------------- /src/beginner-tips/assets/tabs/QuickStartPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from 'react'; 5 | 6 | const isMac: boolean = navigator.platform.toLowerCase().indexOf("darwin") === 0; 7 | 8 | export default function QuickStartPanel() { 9 | const codeSample = ( 10 | 11 | {"class QuickStart {"}
12 |     {"public static void main (String[] args) {"}
13 |         {"System.out.println(\"Hello, World.\");"}
14 |     {"}"}
15 | {"}"}
16 |
17 | ); 18 | const openFolderLink = isMac ? 19 | Open... 20 | : 21 | Open Folder... 22 | ; 23 | return ( 24 |
25 |

26 | In this 1-minute tutorial, we'll show you how to create a quick-start Java program in VS Code. 27 |

28 |

Setup the Workspace

29 |

30 | VS Code Java works directly with folders that have source code. To setup the workspace, simply open a folder using File {">"}  31 | {openFolderLink} 32 |

33 |

Create a Class

34 |

35 | A program needs an entry and a Java program needs a class to host its entry. To create a class for our quick-start program, Create a File and set its name to QuickStart.java.
36 | Now you can put the code in the new file: 37 |

38 |
39 | {codeSample} 40 |
41 |

Run the program

42 |

43 | To run the program, press F5. By default, the program is launched in the Integrated Terminal. You should already see the output there. 44 |

45 |
46 |
How to Debug?
47 |

48 | When you press F5, you are already debugging. Try setting some breakpoint by clicking on the line numbers before each code line and run the program again. You'll see the execution paused at the breakpoint.
49 | While debugging, switch to the Debug View to see the variables and call stacks. 50 |

51 |
52 |

Congratulations!

53 |

54 | Now the quick-start program is running and you are free to build more.
55 | What you saw is just a tiny part of VS Code Java. You can do much more with it. 56 |

57 |
58 | ); 59 | } -------------------------------------------------------------------------------- /src/commands/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { showInstallJdkWebview, showInstallJdkWebviewBeside } from "../install-jdk"; 5 | import * as vscode from "vscode"; 6 | import { instrumentOperation, instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper"; 7 | import { javaExtGuideCmdHandler } from "../ext-guide"; 8 | import { javaFormatterSettingsEditorProvider } from "../formatter-settings"; 9 | import { javaGettingStartedCmdHandler } from "../beginner-tips"; 10 | import { overviewCmdHandler } from "../overview"; 11 | import { webviewCmdLinkHandler } from "../utils"; 12 | import { showWelcomeWebview, showWelcomeWebviewBeside } from "../welcome"; 13 | import { createMavenProjectCmdHandler, createMicroProfileStarterProjectCmdHandler, createQuarkusProjectCmdHandler, createSpringBootProjectCmdHandler, installExtensionCmdHandler, openUrlCmdHandler, showExtensionCmdHandler, showReleaseNotesHandler, toggleAwtDevelopmentHandler } from "./handler"; 14 | import { projectSettingView } from "../project-settings/projectSettingsView"; 15 | 16 | export function initialize(context: vscode.ExtensionContext) { 17 | registerCommandHandler(context, "java.overview", overviewCmdHandler); 18 | registerCommandHandler(context, "java.helper.createMavenProject", createMavenProjectCmdHandler); 19 | registerCommandHandler(context, "java.helper.createSpringBootProject", createSpringBootProjectCmdHandler); 20 | registerCommandHandler(context, "java.helper.createQuarkusProject", createQuarkusProjectCmdHandler); 21 | registerCommandHandler(context, "java.helper.createMicroProfileStarterProject", createMicroProfileStarterProjectCmdHandler); 22 | registerCommandHandler(context, "java.helper.showExtension", showExtensionCmdHandler); 23 | registerCommandHandler(context, "java.helper.openUrl", openUrlCmdHandler); 24 | registerCommandHandler(context, "java.showReleaseNotes", showReleaseNotesHandler); 25 | registerCommandHandler(context, "java.helper.installExtension", installExtensionCmdHandler); 26 | registerCommandHandler(context, "java.gettingStarted", javaGettingStartedCmdHandler); 27 | registerCommandHandler(context, "java.extGuide", javaExtGuideCmdHandler); 28 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.webview.runCommand", webviewCmdLinkHandler)); 29 | registerCommandHandler(context, "java.welcome", showWelcomeWebviewBeside); 30 | registerCommandHandler(context, "java.welcome.fromWalkthrough", showWelcomeWebview); 31 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.formatterSettings", javaFormatterSettingsEditorProvider.showFormatterSettingsEditor, javaFormatterSettingsEditorProvider)); 32 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.formatterSettings.showTextEditor", javaFormatterSettingsEditorProvider.reopenWithTextEditor)); 33 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.projectSettings", projectSettingView.showProjectSettingsPage, projectSettingView)); 34 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.runtime", () => projectSettingView.showProjectSettingsPage("classpath/jdk"), projectSettingView)); 35 | context.subscriptions.push(instrumentOperationAsVsCodeCommand("java.classpathConfiguration", () => projectSettingView.showProjectSettingsPage("classpath"), projectSettingView)); 36 | registerCommandHandler(context, "java.installJdk", showInstallJdkWebviewBeside); 37 | registerCommandHandler(context, "java.installJdk.fromWalkthrough", showInstallJdkWebview); 38 | registerCommandHandler(context, "java.toggleAwtDevelopment", toggleAwtDevelopmentHandler); 39 | } 40 | 41 | type CommandHandler = (context: vscode.ExtensionContext, operationId: string, ...args: any[]) => any; 42 | 43 | /** 44 | * Register command handlers as vscode commands. 45 | * @param context 46 | * @param operationName 47 | * @param callback MUST be a CommandHandler 48 | */ 49 | function registerCommandHandler(context: vscode.ExtensionContext, operationName: string, callback: CommandHandler): void{ 50 | const stub = async (operationId: string, ...args: any[]) => { 51 | return await callback(context, operationId, ...args); 52 | }; 53 | 54 | context.subscriptions.push(vscode.commands.registerCommand(operationName, instrumentOperation(operationName, stub))); 55 | } -------------------------------------------------------------------------------- /src/copilot/Copilot.ts: -------------------------------------------------------------------------------- 1 | import { LanguageModelChatMessage, lm, Disposable, CancellationToken, LanguageModelChatRequestOptions, LanguageModelChatMessageRole, LanguageModelChatSelector } from "vscode"; 2 | import { fixedInstrumentSimpleOperation, logger } from "./utils"; 3 | import { sendInfo } from "vscode-extension-telemetry-wrapper"; 4 | 5 | export default class Copilot { 6 | public static readonly DEFAULT_END_MARK = '<|endofresponse|>'; 7 | public static readonly DEFAULT_MAX_ROUNDS = 10; 8 | public static readonly DEFAULT_MODEL = { family: 'gpt-4' }; 9 | public static readonly DEFAULT_MODEL_OPTIONS: LanguageModelChatRequestOptions = { modelOptions: {} }; 10 | public static readonly NOT_CANCELLABEL: CancellationToken = { isCancellationRequested: false, onCancellationRequested: () => Disposable.from() }; 11 | 12 | public constructor( 13 | private readonly systemMessagesOrSamples: LanguageModelChatMessage[], 14 | private readonly modelSelector: LanguageModelChatSelector = Copilot.DEFAULT_MODEL, 15 | private readonly modelOptions: LanguageModelChatRequestOptions = Copilot.DEFAULT_MODEL_OPTIONS, 16 | private readonly maxRounds: number = Copilot.DEFAULT_MAX_ROUNDS, 17 | private readonly endMark: string = Copilot.DEFAULT_END_MARK 18 | ) { 19 | } 20 | 21 | private async doSend( 22 | userMessage: string, 23 | modelOptions: LanguageModelChatRequestOptions = Copilot.DEFAULT_MODEL_OPTIONS, 24 | cancellationToken: CancellationToken = Copilot.NOT_CANCELLABEL 25 | ): Promise { 26 | let answer: string = ''; 27 | let rounds: number = 0; 28 | const messages = [...this.systemMessagesOrSamples]; 29 | const _send = async (message: string): Promise => { 30 | rounds++; 31 | logger.debug(`User: \n`, message); 32 | logger.info(`User: ${message.split('\n')[0]}...`); 33 | messages.push(new LanguageModelChatMessage(LanguageModelChatMessageRole.User, message)); 34 | logger.info('Copilot: thinking...'); 35 | 36 | let rawAnswer: string = ''; 37 | try { 38 | const model = (await lm.selectChatModels(this.modelSelector))?.[0]; 39 | if (!model) { 40 | const models = await lm.selectChatModels(); 41 | throw new Error(`No suitable model, available models: [${models.map(m => m.name).join(', ')}]. Please make sure you have installed the latest "GitHub Copilot Chat" (v0.16.0 or later).`); 42 | } 43 | const response = await model.sendRequest(messages, modelOptions ?? this.modelOptions, cancellationToken); 44 | for await (const item of response.text) { 45 | rawAnswer += item; 46 | } 47 | } catch (e) { 48 | //@ts-ignore 49 | const cause = e.cause || e; 50 | logger.error(`Failed to chat with copilot`, cause); 51 | throw cause; 52 | } 53 | messages.push(new LanguageModelChatMessage(LanguageModelChatMessageRole.Assistant, rawAnswer)); 54 | logger.debug(`Copilot: \n`, rawAnswer); 55 | logger.info(`Copilot: ${rawAnswer.split('\n')[0]}...`); 56 | answer += rawAnswer; 57 | return answer.trim().endsWith(this.endMark); 58 | }; 59 | let complete: boolean = await _send(userMessage); 60 | while (!complete && rounds < this.maxRounds) { 61 | complete = await _send('continue where you left off.'); 62 | } 63 | logger.debug('rounds', rounds); 64 | sendInfo('java.copilot.sendRequest.info', { rounds: rounds }); 65 | return answer.replace(this.endMark, ""); 66 | } 67 | 68 | public async send( 69 | userMessage: string, 70 | modelOptions: LanguageModelChatRequestOptions = Copilot.DEFAULT_MODEL_OPTIONS, 71 | cancellationToken: CancellationToken = Copilot.NOT_CANCELLABEL 72 | ): Promise { 73 | return fixedInstrumentSimpleOperation("java.copilot.sendRequest", this.doSend.bind(this))(userMessage, modelOptions, cancellationToken); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/copilot/inspect/InspectActionCodeLensProvider.ts: -------------------------------------------------------------------------------- 1 | import { CodeLens, CodeLensProvider, Event, EventEmitter, ExtensionContext, TextDocument, Uri, languages } from "vscode"; 2 | import { getTopLevelClassesOfDocument, logger } from "../utils"; 3 | import { COMMAND_IGNORE_INSPECTIONS, COMMAND_INSPECT_CLASS } from "./commands"; 4 | import InspectionCache from "./InspectionCache"; 5 | 6 | export class InspectActionCodeLensProvider implements CodeLensProvider { 7 | private inspectCodeLenses: Map = new Map(); 8 | private emitter: EventEmitter = new EventEmitter(); 9 | public readonly onDidChangeCodeLenses: Event = this.emitter.event; 10 | 11 | public install(context: ExtensionContext): InspectActionCodeLensProvider { 12 | logger.debug('[InspectCodeLensProvider] install...'); 13 | context.subscriptions.push( 14 | languages.registerCodeLensProvider({ language: 'java' }, this) 15 | ); 16 | return this; 17 | } 18 | 19 | public async rerender(document: TextDocument) { 20 | if (document.languageId !== 'java') return; 21 | logger.debug('[InspectCodeLensProvider] rerender inspect codelenses...'); 22 | const topLevelCodeLenses: CodeLens[] = []; 23 | const classes = await getTopLevelClassesOfDocument(document); 24 | classes.map(clazz => new CodeLens(clazz.range, { 25 | title: "✨ Rewrite with new Java syntax", 26 | command: COMMAND_INSPECT_CLASS, 27 | arguments: [document, clazz] 28 | })).forEach(codeLens => topLevelCodeLenses.push(codeLens)); 29 | 30 | const results = await Promise.all(classes.map(clazz => InspectionCache.hasCache(document, clazz))); 31 | classes.filter((_, i) => results[i]).map(clazz => new CodeLens(clazz.range, { 32 | title: "Ignore all", 33 | command: COMMAND_IGNORE_INSPECTIONS, 34 | arguments: [document, clazz] 35 | })).forEach(codeLens => topLevelCodeLenses.push(codeLens)); 36 | 37 | this.inspectCodeLenses.set(document.uri, topLevelCodeLenses); 38 | this.emitter.fire(); 39 | } 40 | 41 | public provideCodeLenses(document: TextDocument): CodeLens[] { 42 | return this.inspectCodeLenses.get(document.uri) ?? []; 43 | } 44 | } -------------------------------------------------------------------------------- /src/copilot/inspect/Inspection.ts: -------------------------------------------------------------------------------- 1 | import { TextDocument, workspace, window, Selection, Range, Position } from "vscode"; 2 | import { SymbolNode } from "./SymbolNode"; 3 | 4 | export interface InspectionProblem { 5 | /** 6 | * short description of the problem 7 | */ 8 | description: string; 9 | position: { 10 | /** 11 | * real line number to the start of the document, will change 12 | */ 13 | line: number; 14 | /** 15 | * relative line number to the start of the symbol(method/class), won't change 16 | */ 17 | relativeLine: number; 18 | /** 19 | * code of the first line of the problematic code block 20 | */ 21 | code: string; 22 | }; 23 | /** 24 | * indicator of the problematic code block, e.g. method name/class name, keywork, etc. 25 | */ 26 | indicator: string; 27 | } 28 | 29 | export interface Inspection { 30 | id: string; 31 | document?: TextDocument; 32 | symbol?: SymbolNode; 33 | problem: InspectionProblem; 34 | solution: string; 35 | severity: string; 36 | } 37 | 38 | export namespace Inspection { 39 | export function revealFirstLineOfInspection(inspection: Inspection) { 40 | inspection.document && void workspace.openTextDocument(inspection.document.uri).then(document => { 41 | void window.showTextDocument(document).then(editor => { 42 | const range = getIndicatorRangeOfInspection(inspection.problem); 43 | editor.selection = new Selection(range.start, range.end); 44 | editor.revealRange(range); 45 | }); 46 | }); 47 | } 48 | 49 | /** 50 | * get the range of the indicator of the inspection. 51 | * `indicator` will be used as the position of code lens/diagnostics and also used as initial selection for fix commands. 52 | */ 53 | export function getIndicatorRangeOfInspection(problem: InspectionProblem): Range { 54 | const position = problem.position; 55 | const startLine: number = position.line; 56 | let startColumn: number = position.code.indexOf(problem.indicator), endLine: number = -1, endColumn: number = -1; 57 | if (startColumn > -1) { 58 | // highlight only the symbol 59 | endLine = position.line; 60 | endColumn = startColumn + problem.indicator?.length; 61 | } else { 62 | // highlight entire first line 63 | startColumn = position.code.search(/\S/) ?? 0; // first non-whitespace character 64 | endLine = position.line; 65 | endColumn = position.code.length; // last character 66 | } 67 | return new Range(new Position(startLine, startColumn), new Position(endLine, endColumn)); 68 | } 69 | } -------------------------------------------------------------------------------- /src/copilot/inspect/SymbolNode.ts: -------------------------------------------------------------------------------- 1 | import { DocumentSymbol, SymbolKind, Range, TextDocument } from "vscode"; 2 | import * as crypto from "crypto"; 3 | 4 | /** 5 | * A wrapper class for DocumentSymbol to provide additional functionalities: 6 | * - parent: the parent symbol 7 | * - qualifiedName: the fully qualified name of the symbol 8 | */ 9 | export class SymbolNode { 10 | public readonly snapshotId: string; 11 | 12 | public constructor( 13 | public readonly document: TextDocument, 14 | public readonly symbol: DocumentSymbol, 15 | public readonly parent?: SymbolNode 16 | ) { 17 | // calculate the snapshot id of the symbol immediately because the symbol content may change. 18 | this.snapshotId = SymbolNode.calculateSymbolSnapshotId(document, symbol); 19 | } 20 | 21 | public get range(): Range { 22 | return this.symbol.range; 23 | } 24 | 25 | public get kind(): SymbolKind { 26 | return this.symbol.kind; 27 | } 28 | 29 | /** 30 | * The fully qualified name of the symbol. 31 | */ 32 | public get qualifiedName(): string { 33 | if (this.parent) { 34 | return this.parent.qualifiedName + "." + this.symbol.name; 35 | } else { 36 | return this.symbol.name; 37 | } 38 | } 39 | 40 | public get children(): SymbolNode[] { 41 | return this.symbol.children.map(symbol => new SymbolNode(this.document, symbol, this)); 42 | } 43 | 44 | /** 45 | * generate a unique id for the symbol based on its content, so that we can detect if the symbol has changed 46 | */ 47 | private static calculateSymbolSnapshotId(document: TextDocument, symbol: DocumentSymbol): string { 48 | const body = document.getText(symbol.range); 49 | return crypto.createHash('md5').update(body).digest("hex") 50 | } 51 | 52 | public toString(): string { 53 | return `${SymbolKind[this.kind].toLowerCase()} ${this.symbol.name}`; 54 | } 55 | } -------------------------------------------------------------------------------- /src/copilot/inspect/commands.ts: -------------------------------------------------------------------------------- 1 | import { TextDocument, Range, Selection, commands, window, Uri, env } from "vscode"; 2 | import { instrumentOperationAsVsCodeCommand, sendInfo } from "vscode-extension-telemetry-wrapper"; 3 | import InspectionCopilot from "./InspectionCopilot"; 4 | import { Inspection, InspectionProblem } from "./Inspection"; 5 | import { logger, uncapitalize } from "../utils"; 6 | import { SymbolNode } from "./SymbolNode"; 7 | import { DocumentRenderer } from "./DocumentRenderer"; 8 | import InspectionCache from "./InspectionCache"; 9 | import path from "path"; 10 | 11 | export const COMMAND_INSPECT_CLASS = 'java.copilot.inspect.class'; 12 | export const COMMAND_INSPECT_RANGE = 'java.copilot.inspect.range'; 13 | export const COMMAND_FIX_INSPECTION = 'java.copilot.inspection.fix'; 14 | export const COMMAND_IGNORE_INSPECTIONS = 'java.copilot.inspection.ignore'; 15 | 16 | const LEARN_MORE_RESPONSE_FILTERED = 'https://docs.github.com/en/copilot/configuring-github-copilot/configuring-github-copilot-settings-on-githubcom#enabling-or-disabling-duplication-detection'; 17 | 18 | export function registerCommands(copilot: InspectionCopilot, renderer: DocumentRenderer) { 19 | instrumentOperationAsVsCodeCommand(COMMAND_INSPECT_CLASS, async (document: TextDocument, clazz: SymbolNode) => { 20 | try { 21 | await copilot.inspectClass(document, clazz); 22 | } catch (e) { 23 | showErrorMessage(e, document, clazz); 24 | logger.error(`Failed to inspect class "${clazz.symbol.name}".`, e); 25 | throw e; 26 | } 27 | renderer.rerender(document); 28 | }); 29 | 30 | instrumentOperationAsVsCodeCommand(COMMAND_INSPECT_RANGE, async (document: TextDocument, range: Range | Selection) => { 31 | try { 32 | await copilot.inspectRange(document, range); 33 | } catch (e) { 34 | showErrorMessage(e, document, range); 35 | logger.error(`Failed to inspect range of "${path.basename(document.fileName)}".`, e); 36 | throw e; 37 | } 38 | renderer.rerender(document); 39 | }); 40 | 41 | instrumentOperationAsVsCodeCommand(COMMAND_FIX_INSPECTION, async (problem: InspectionProblem, solution: string, source: string) => { 42 | // source is where is this command triggered from, e.g. "gutter", "codelens", "diagnostic" 43 | const range = Inspection.getIndicatorRangeOfInspection(problem); 44 | sendInfo(`${COMMAND_FIX_INSPECTION}.info`, { problem: problem.description, solution, source }); 45 | void commands.executeCommand('vscode.editorChat.start', { 46 | autoSend: true, 47 | message: `/fix ${problem.description}, maybe ${uncapitalize(solution)}`, 48 | position: range?.start, 49 | initialSelection: new Selection(range!.start, range!.start), 50 | initialRange: new Range(range!.start, range!.start) 51 | }); 52 | }); 53 | 54 | instrumentOperationAsVsCodeCommand(COMMAND_IGNORE_INSPECTIONS, async (document: TextDocument, symbol?: SymbolNode, inspection?: Inspection) => { 55 | if (inspection) { 56 | sendInfo(`${COMMAND_IGNORE_INSPECTIONS}.info`, { problem: inspection.problem.description, solution: inspection.solution }); 57 | } 58 | InspectionCache.invalidateInspectionCache(document, symbol, inspection); 59 | renderer.rerender(document); 60 | }); 61 | } 62 | 63 | function showErrorMessage(e: unknown, document: TextDocument, target: SymbolNode | Range) { 64 | let message = target instanceof Range ? 65 | `Failed to inspect range of "${path.basename(document.fileName)}", ${e}` : 66 | `Failed to inspect class "${target.symbol.name}", ${e}`; 67 | 68 | const actions = new Map void>(); 69 | if (e instanceof Error && e.message.toLowerCase().includes('response got filtered')) { 70 | actions.set('Learn more', () => env.openExternal(Uri.parse(LEARN_MORE_RESPONSE_FILTERED))); 71 | message += ', possibly because it matches existing public code'; 72 | } 73 | window.showErrorMessage(`${message}.`, ...actions.keys()).then(choice => { 74 | if (choice) { 75 | actions.get(choice)!(); 76 | } 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /src/copilot/inspect/render/DiagnosticRenderer.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, Diagnostic, DiagnosticCollection, DiagnosticSeverity, ExtensionContext, Range, Selection, TextDocument, languages } from "vscode"; 3 | import { Inspection } from "../Inspection"; 4 | import { InspectionRenderer } from "./InspectionRenderer"; 5 | import { logger } from "../../../copilot/utils"; 6 | import { COMMAND_FIX_INSPECTION } from "../commands"; 7 | import _ from "lodash"; 8 | 9 | const DIAGNOSTICS_GROUP = 'java.copilot.inspection.diagnostics'; 10 | 11 | export class DiagnosticRenderer implements InspectionRenderer { 12 | private diagnostics: DiagnosticCollection | undefined; 13 | 14 | public install(context: ExtensionContext): InspectionRenderer { 15 | if (this.diagnostics) return this; 16 | logger.debug('[DiagnosticRenderer] install...'); 17 | this.diagnostics = languages.createDiagnosticCollection(DIAGNOSTICS_GROUP); 18 | context.subscriptions.push(this.diagnostics); 19 | return this; 20 | } 21 | 22 | public uninstall(): void { 23 | if (!this.diagnostics) return; 24 | logger.debug('[DiagnosticRenderer] uninstall...'); 25 | this.diagnostics.clear(); 26 | this.diagnostics.dispose(); 27 | this.diagnostics = undefined; 28 | } 29 | 30 | public clear(document?: TextDocument): void { 31 | if (document) { 32 | this.diagnostics?.set(document.uri, []); 33 | } else { 34 | this.diagnostics?.clear(); 35 | } 36 | } 37 | 38 | public renderInspections(document: TextDocument, inspections: Inspection[]): void { 39 | if (inspections.length < 1 || !this.diagnostics) { 40 | return; 41 | } 42 | const oldItems: readonly InspectionDiagnostic[] = (this.diagnostics.get(document.uri) ?? []) as InspectionDiagnostic[]; 43 | const oldIds: string[] = _.uniq(oldItems).map(c => c.inspection.id); 44 | const newIds: string[] = inspections.map(i => i.id); 45 | const toKeep: InspectionDiagnostic[] = _.intersection(oldIds, newIds).map(id => oldItems.find(c => c.inspection.id === id)!) ?? []; 46 | const toAdd: InspectionDiagnostic[] = _.difference(newIds, oldIds).map(id => inspections.find(i => i.id === id)!).map(i => new InspectionDiagnostic(i)); 47 | this.diagnostics.set(document.uri, [...toKeep, ...toAdd]); 48 | } 49 | } 50 | 51 | class InspectionDiagnostic extends Diagnostic { 52 | public constructor(public readonly inspection: Inspection) { 53 | const range = Inspection.getIndicatorRangeOfInspection(inspection.problem); 54 | const severiy = inspection.severity.toUpperCase() === 'HIGH' ? DiagnosticSeverity.Information : DiagnosticSeverity.Hint; 55 | super(range, inspection.problem.description, severiy); 56 | this.source = DIAGNOSTICS_GROUP; 57 | } 58 | } 59 | 60 | export async function fixDiagnostic(document: TextDocument, _range: Range | Selection, context: CodeActionContext, _token: CancellationToken): Promise { 61 | if (document?.languageId !== 'java') { 62 | return []; 63 | } 64 | const actions: CodeAction[] = []; 65 | for (const diagnostic of context.diagnostics) { 66 | if (diagnostic.source !== DIAGNOSTICS_GROUP) { 67 | continue; 68 | } 69 | const inspection: Inspection = (diagnostic as InspectionDiagnostic).inspection as Inspection; 70 | const fixAction: CodeAction = { 71 | title: inspection.solution, 72 | diagnostics: [diagnostic], 73 | kind: CodeActionKind.RefactorRewrite, 74 | isPreferred: true, 75 | command: { 76 | title: diagnostic.message, 77 | command: COMMAND_FIX_INSPECTION, 78 | arguments: [inspection.problem, inspection.solution, 'diagnostics'] 79 | } 80 | }; 81 | actions.push(fixAction); 82 | } 83 | return actions; 84 | } 85 | -------------------------------------------------------------------------------- /src/copilot/inspect/render/GutterIconRenderer.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | import { DecorationOptions, ExtensionContext, MarkdownString, TextDocument, TextEditorDecorationType, Uri, window } from "vscode"; 3 | import { Inspection } from "../Inspection"; 4 | import { InspectionRenderer } from "./InspectionRenderer"; 5 | import { logger } from "../../../copilot/utils"; 6 | import path = require("path"); 7 | import { COMMAND_FIX_INSPECTION } from "../commands"; 8 | import _ from "lodash"; 9 | 10 | export class GutterIconRenderer implements InspectionRenderer { 11 | private readonly gutterIcons: Map = new Map(); 12 | private gutterIconDecorationType: TextEditorDecorationType | undefined; 13 | 14 | public install(context: ExtensionContext): InspectionRenderer { 15 | if (this.gutterIconDecorationType) return this; 16 | logger.debug(`[GutterIconRenderer] install`); 17 | const icon = Uri.file(path.join(context.asAbsolutePath('resources'), `gutter-blue.svg`)); 18 | this.gutterIconDecorationType = window.createTextEditorDecorationType({ 19 | isWholeLine: true, 20 | gutterIconPath: icon, 21 | gutterIconSize: 'contain' 22 | }); 23 | return this; 24 | } 25 | 26 | public uninstall(): void { 27 | if (!this.gutterIconDecorationType) return; 28 | logger.debug(`[GutterIconRenderer] uninstall`); 29 | this.gutterIcons.clear(); 30 | window.visibleTextEditors.forEach(editor => this.gutterIconDecorationType && editor.setDecorations(this.gutterIconDecorationType, [])); 31 | this.gutterIconDecorationType.dispose(); 32 | this.gutterIconDecorationType = undefined; 33 | } 34 | 35 | public clear(document?: TextDocument): void { 36 | if (!this.gutterIconDecorationType) return; 37 | if (document) { 38 | this.gutterIcons?.set(document.uri, []); 39 | } else { 40 | this.gutterIcons?.clear(); 41 | } 42 | window.visibleTextEditors.forEach(editor => this.gutterIconDecorationType && editor.setDecorations(this.gutterIconDecorationType, [])); 43 | } 44 | 45 | public renderInspections(document: TextDocument, inspections: Inspection[]): void { 46 | const editor = window.visibleTextEditors.find(e => e.document.uri === document.uri); 47 | if (inspections.length < 1 || !editor || !this.gutterIconDecorationType) { 48 | return; 49 | } 50 | 51 | const oldItems: readonly InspectionGutterIcon[] = this.gutterIcons.get(document.uri) ?? []; 52 | const oldIds: string[] = _.uniq(oldItems).map(c => c.inspection.id); 53 | const newIds: string[] = inspections.map(i => i.id); 54 | const toKeep: InspectionGutterIcon[] = _.intersection(oldIds, newIds).map(id => oldItems.find(c => c.inspection.id === id)!) ?? []; 55 | const toAdd: InspectionGutterIcon[] = _.difference(newIds, oldIds).map(id => inspections.find(i => i.id === id)!).map(i => GutterIconRenderer.toGutterIcon(i)); 56 | const newGutterIcons: InspectionGutterIcon[] = [...toKeep, ...toAdd]; 57 | this.gutterIcons.set(document.uri, newGutterIcons); 58 | 59 | editor.setDecorations(this.gutterIconDecorationType, newGutterIcons); 60 | } 61 | 62 | private static toGutterIcon(inspection: Inspection): InspectionGutterIcon { 63 | const range = Inspection.getIndicatorRangeOfInspection(inspection.problem); 64 | const args = [inspection.problem, inspection.solution, 'guttericons']; 65 | const commandUri = Uri.parse(`command:${COMMAND_FIX_INSPECTION}?${encodeURIComponent(JSON.stringify(args))}`); 66 | const hoverMessage = new MarkdownString(`${inspection.problem.description}\n\n$(copilot) [${inspection.solution}](${commandUri})`, true); 67 | hoverMessage.isTrusted = true; 68 | return { range, hoverMessage, inspection }; 69 | } 70 | } 71 | 72 | interface InspectionGutterIcon extends DecorationOptions { 73 | inspection: Inspection; 74 | } 75 | -------------------------------------------------------------------------------- /src/copilot/inspect/render/InspectionRenderer.ts: -------------------------------------------------------------------------------- 1 | import { ExtensionContext, TextDocument } from "vscode"; 2 | import { Inspection } from "../Inspection"; 3 | 4 | export interface InspectionRenderer { 5 | install(context: ExtensionContext): InspectionRenderer; 6 | uninstall(): void; 7 | clear(document?: TextDocument): void; 8 | renderInspections(document: TextDocument, inspections: Inspection[]): void; 9 | } -------------------------------------------------------------------------------- /src/copilot/inspect/render/RulerHighlightRenderer.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | import { DecorationOptions, ExtensionContext, OverviewRulerLane, TextDocument, TextEditorDecorationType, ThemeColor, Uri, window } from "vscode"; 3 | import { Inspection } from "../Inspection"; 4 | import { InspectionRenderer } from "./InspectionRenderer"; 5 | import { logger } from "../../../copilot/utils"; 6 | import _ from "lodash"; 7 | 8 | export class RulerHighlightRenderer implements InspectionRenderer { 9 | private readonly rulerHighlights: Map = new Map(); 10 | private rulerDecorationType: TextEditorDecorationType | undefined; 11 | 12 | public install(_context: ExtensionContext): InspectionRenderer { 13 | if (this.rulerDecorationType) return this; 14 | logger.debug(`[RulerRenderer] install`); 15 | const color = new ThemeColor('textLink.foreground'); 16 | this.rulerDecorationType = window.createTextEditorDecorationType({ 17 | isWholeLine: true, 18 | overviewRulerLane: OverviewRulerLane.Right, 19 | overviewRulerColor: color 20 | }); 21 | return this; 22 | } 23 | 24 | public uninstall(): void { 25 | if (!this.rulerDecorationType) return; 26 | logger.debug(`[RulerRenderer] uninstall`); 27 | this.rulerHighlights.clear(); 28 | window.visibleTextEditors.forEach(editor => this.rulerDecorationType && editor.setDecorations(this.rulerDecorationType, [])); 29 | this.rulerDecorationType.dispose(); 30 | this.rulerDecorationType = undefined; 31 | } 32 | 33 | public clear(document?: TextDocument): void { 34 | if (!this.rulerDecorationType) return; 35 | if (document) { 36 | this.rulerHighlights?.set(document.uri, []); 37 | } else { 38 | this.rulerHighlights?.clear(); 39 | } 40 | window.visibleTextEditors.forEach(editor => this.rulerDecorationType && editor.setDecorations(this.rulerDecorationType, [])); 41 | } 42 | 43 | public renderInspections(document: TextDocument, inspections: Inspection[]): void { 44 | const editor = window.visibleTextEditors.find(e => e.document.uri === document.uri); 45 | if (inspections.length < 1 || !editor || !this.rulerDecorationType) { 46 | return; 47 | } 48 | const oldItems: readonly InspectionRulerHighlight[] = this.rulerHighlights.get(document.uri) ?? []; 49 | const oldIds: string[] = _.uniq(oldItems).map(c => c.inspection.id); 50 | const newIds: string[] = inspections.map(i => i.id); 51 | const toKeep: InspectionRulerHighlight[] = _.intersection(oldIds, newIds).map(id => oldItems.find(c => c.inspection.id === id)!) ?? []; 52 | const toAdd: InspectionRulerHighlight[] = _.difference(newIds, oldIds).map(id => inspections.find(i => i.id === id)!).map(i => RulerHighlightRenderer.toRulerHighlight(i)); 53 | const newRulerHightlights: InspectionRulerHighlight[] = [...toKeep, ...toAdd]; 54 | this.rulerHighlights.set(document.uri, newRulerHightlights); 55 | 56 | editor.setDecorations(this.rulerDecorationType, newRulerHightlights); 57 | } 58 | 59 | private static toRulerHighlight(inspection: Inspection): InspectionRulerHighlight { 60 | const range = Inspection.getIndicatorRangeOfInspection(inspection.problem); 61 | return { range, inspection }; 62 | } 63 | } 64 | 65 | interface InspectionRulerHighlight extends DecorationOptions { 66 | inspection: Inspection; 67 | } 68 | -------------------------------------------------------------------------------- /src/daemon/daemon.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { ClientLogWatcher } from "./clientLog/logWatcher"; 6 | import { ProcessWatcher } from "./processWatcher"; 7 | import { LogWatcher } from "./serverLog/logWatcher"; 8 | 9 | export class LSDaemon { 10 | 11 | public logWatcher: LogWatcher; 12 | public processWatcher: ProcessWatcher; 13 | public clientLogWatcher: ClientLogWatcher; 14 | 15 | constructor(public context: vscode.ExtensionContext) { 16 | this.processWatcher = new ProcessWatcher(this); 17 | this.logWatcher = new LogWatcher(this); 18 | this.clientLogWatcher = new ClientLogWatcher(this) 19 | } 20 | 21 | public async initialize() { 22 | await this.logWatcher.start(); 23 | setTimeout(() => { 24 | this.clientLogWatcher.collectInfoFromLog(); 25 | }, 10 * 1000); // wait a while when JDTLS has been launched 26 | } 27 | 28 | 29 | } -------------------------------------------------------------------------------- /src/daemon/serverLog/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export function toElapsed(start?: number, end?: number) { 5 | if (start && end) { 6 | return end - start; 7 | } else { 8 | return undefined; 9 | } 10 | } -------------------------------------------------------------------------------- /src/daemon/serverLog/whitelist.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | import { createHash } from "crypto"; 4 | 5 | const TAGS: string[] = [ 6 | "buildship", 7 | "m2e", 8 | "gradle", 9 | "maven", 10 | "bundle" 11 | ]; 12 | 13 | const MESSAGE_WHITELIST: string[] = [ 14 | "Application error", 15 | "BadLocationException", 16 | "Could not load Gradle version information", 17 | "Error computing hover", 18 | "Error in calling delegate command handler", 19 | "Error in JDT Core during AST creation", 20 | "Error occurred while deleting", 21 | "Error filtering index locations based on qualifier.", 22 | "Failed to configure project", 23 | "Failed to publish diagnostics for", 24 | "Failed to detect project changes", 25 | "Failed to update qualified index.", 26 | "Failed to launch debuggee in terminal. Reason: java.util.concurrent.TimeoutException: timeout", 27 | "Failed to save JDT index", 28 | "failed to send diagnostics", 29 | "FrameworkEvent ERROR", 30 | "Initialization failed", 31 | "Index out of bounds", 32 | "JavaBuilder handling CoreException", 33 | "Offset > length", 34 | "Problems occurred when invoking code from plug-in: \"org.eclipse.jdt.ls.core\".", 35 | "Problems occurred when invoking code from plug-in: \"org.eclipse.core.resources\".", 36 | "Problems occurred when invoking code from plug-in: \"org.eclipse.jdt.core.manipulation\".", 37 | "Problem resolving refactor code actions", 38 | "Problem with folding range", 39 | "Problem with codeComplete for", 40 | "Synchronize Gradle projects with workspace failed due to an error connecting to the Gradle build.", 41 | "Synchronize Gradle projects with workspace failed due to an error in the referenced Gradle build.", 42 | "Unable to read JavaModelManager nonChainingJarsCache file", 43 | "Workspace restored, but some problems occurred.", 44 | 45 | // While loading class "xxxx", thread "Thread[Worker-1: Loading available Gradle versions,5,main]" timed out waiting (300xxms) for thread "Thread[Worker-0: Synchronizing projects,5,main]" to finish starting bundle "org.eclipse.buildship.core_3.1.6.v20220511-1359 [16]". To avoid deadlock, thread "Thread[Worker-1: Loading available Gradle versions,5,main]" is proceeding but "xxxx" may not be fully initialized. 46 | // xxxx stands for below: 47 | // org.eclipse.buildship.core.internal.preferences.PersistentModelConverter 48 | // org.eclipse.buildship.core.internal.util.gradle.PublishedGradleVersions$LookupStrategy 49 | // ... 50 | "While loading class \"org.eclipse.buildship.core.internal." 51 | ]; 52 | 53 | export function redact(rawMessage: string, consentToCollectLogs: boolean): { 54 | message: string; 55 | tags: string[]; 56 | hash: string; 57 | } { 58 | const matchedMessage = MESSAGE_WHITELIST.find(msg => rawMessage.includes(msg)); 59 | const message = matchedMessage ?? (consentToCollectLogs ? rawMessage : ""); 60 | const hash = sha1(matchedMessage ?? rawMessage); 61 | const tags = TAGS.filter(tag => rawMessage.toLocaleLowerCase().includes(tag)); 62 | 63 | return { 64 | message, 65 | tags, 66 | hash 67 | } 68 | } 69 | 70 | function sha1(content: string): string { 71 | const hash = createHash("sha1"); 72 | hash.update(content); 73 | return hash.digest('hex'); 74 | } -------------------------------------------------------------------------------- /src/exp/TreatmentVariables.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export class TreatmentVariables { 5 | public static readonly VSCodeConfig = 'vscode'; 6 | public static readonly PresentWelcomePageByDefault = 'presentWelcomePageByDefault'; 7 | public static readonly JavaWalkthroughEnabled = "gettingStarted.overrideCategory.vscjava.vscode-java-pack.javaWelcome.when"; 8 | public static readonly JavaCompletionSampling = "javaCompletionSampling"; 9 | } 10 | -------------------------------------------------------------------------------- /src/exp/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { IExperimentationService, IExperimentationTelemetry, TargetPopulation, getExperimentationServiceAsync } from "vscode-tas-client"; 6 | import { addContextProperty, sendInfo } from "vscode-extension-telemetry-wrapper"; 7 | import { getExtensionName, getExtensionVersion, isInsiders } from "../utils"; 8 | 9 | class ExperimentationTelemetry implements IExperimentationTelemetry { 10 | 11 | public setSharedProperty(name: string, value: string): void { 12 | addContextProperty(name, value); 13 | } 14 | 15 | public postEvent(eventName: string, props: Map): void { 16 | const payload: any = { __event_name__: eventName }; 17 | for (const [key, value] of props) { 18 | payload[key] = value; 19 | } 20 | 21 | sendInfo("", payload); 22 | } 23 | 24 | } 25 | 26 | let expService: IExperimentationService; 27 | 28 | export function getExpService() { 29 | return expService; 30 | } 31 | 32 | function getTargetPopulation() { 33 | return isInsiders() ? TargetPopulation.Insiders : TargetPopulation.Public; 34 | } 35 | 36 | export async function initialize(context: vscode.ExtensionContext) { 37 | expService = await getExperimentationServiceAsync( 38 | getExtensionName(), 39 | getExtensionVersion(), 40 | getTargetPopulation(), 41 | new ExperimentationTelemetry(), 42 | context.globalState 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/ext-guide/assets/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import "../../assets/vscode.scss"; 5 | import "bootstrap/js/src/tab"; 6 | const $ = require("jquery"); 7 | 8 | $("#navigationPanel a").click((e: any) => { 9 | ($($(e.target).attr("href")||"") as any).tab("show"); 10 | }); 11 | 12 | let os = "win"; 13 | if (navigator.platform.toLowerCase().indexOf("mac") === 0) { 14 | os = "mac"; 15 | } 16 | 17 | const osToHide = os === "win" ? "mac" : "win"; 18 | $(`[data-os=${osToHide}]`).hide(); 19 | 20 | declare function acquireVsCodeApi(): any; 21 | const vscode = acquireVsCodeApi && acquireVsCodeApi(); 22 | 23 | $("a[data-toggle='tab']").on("shown.bs.tab", (e: any) => { 24 | vscode.postMessage({ 25 | command: "tabActivated", 26 | tabId: e.target.id 27 | }); 28 | 29 | bsHide($("p[ext]:visible")); 30 | bsHide($("#btn-learn-more")); 31 | updateSelection(); 32 | }); 33 | 34 | $("tr").hover((e: any) => { 35 | const $chkBox = $(e.target).closest("tr").find("input[type='checkbox']"); 36 | if ($chkBox.length === 0) { 37 | return; 38 | } 39 | 40 | const ext = $chkBox.val(); 41 | const $visibleDesc = $("p[ext]:visible"); 42 | if ($visibleDesc.length > 0 && $visibleDesc.val() !== ext) { 43 | bsHide($visibleDesc); 44 | } 45 | 46 | const $nextDesc = $(`p[ext='${ext}'].d-none`); 47 | bsShow($nextDesc); 48 | 49 | const $learnMore = $("#btn-learn-more"); 50 | $learnMore.attr("href", `command:java.helper.showExtension?%22${ext}%22`); 51 | bsShow($learnMore); 52 | }); 53 | 54 | function updateSelection() { 55 | const $checked = $("input:checked:visible:enabled"); 56 | const $btnSelected = $("#btn-install-selected"); 57 | if ($checked.length === 0) { 58 | bsHide($btnSelected); 59 | return; 60 | } 61 | 62 | $btnSelected.text(`Install Selected (${$checked.length})`); 63 | bsShow($btnSelected); 64 | } 65 | 66 | $("input[type='checkbox']").change(updateSelection); 67 | 68 | function bsHide($elem: any) { 69 | $elem.addClass("d-none"); 70 | } 71 | 72 | function bsShow($elem: any) { 73 | $elem.removeClass("d-none"); 74 | } 75 | 76 | window.addEventListener("message", event => { 77 | if (event.data.command === "syncExtensionStatus") { 78 | syncExtensionStatus(event.data.installedExtensions); 79 | } 80 | }); 81 | 82 | function syncExtensionStatus(extensions: string[]) { 83 | $("input[type='checkbox']").each((_i: any, elem: any) => { 84 | const isInstalled = extensions.includes($(elem).val()); 85 | $(elem).prop("disabled", isInstalled); 86 | $(elem).prop("checked", isInstalled); 87 | }); 88 | } 89 | 90 | function getSelectedExtension(isAll: boolean = false) { 91 | const $selected = isAll ? $("input:visible:enabled") : $("input:checked:visible:enabled"); 92 | const selectedExtensions: string[] = []; 93 | $selected.each((_i: any, elem: any) => { selectedExtensions.push($(elem).val()); }); 94 | return selectedExtensions; 95 | } 96 | 97 | $("#btn-install-selected").click(() => installExtensions(getSelectedExtension())); 98 | $("#btn-install-all").click(() => installExtensions(getSelectedExtension(true))); 99 | 100 | function installExtensions(extNames: string[]) { 101 | if (extNames.length <= 0) { 102 | return; 103 | } 104 | 105 | vscode.postMessage({ 106 | command: "installExtensions", 107 | extNames: extNames 108 | }); 109 | } 110 | -------------------------------------------------------------------------------- /src/formatter-settings/RemoteProfileProvider.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { downloadFile } from "./utils"; 6 | 7 | export class RemoteProfileProvider implements vscode.TextDocumentContentProvider { 8 | 9 | public static scheme = "java-formatter"; 10 | private contentStorage: Map = new Map(); 11 | 12 | public setContent(url: string, content: string): void { 13 | this.contentStorage.set(url, content); 14 | } 15 | 16 | async provideTextDocumentContent(uri: vscode.Uri): Promise { 17 | const originalUri: vscode.Uri = uri.with({ scheme: "https" }); 18 | return this.contentStorage.get(originalUri.toString()) || downloadFile(originalUri.toString()); 19 | } 20 | } 21 | 22 | export let remoteProfileProvider = new RemoteProfileProvider(); 23 | 24 | export function initRemoteProfileProvider(context: vscode.ExtensionContext) { 25 | context.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(RemoteProfileProvider.scheme, remoteProfileProvider)); 26 | } 27 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/App.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import FormatterSettingsView from "./features/formatterSettings/FormatterSettingView"; 6 | 7 | export class App extends React.Component { 8 | 9 | render() { 10 | return ( 11 | 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/SpaceDiff.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/src/formatter-settings/assets/SpaceDiff.woff2 -------------------------------------------------------------------------------- /src/formatter-settings/assets/app/store.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { configureStore } from "@reduxjs/toolkit"; 5 | import formatterSettingsViewReducer from "../features/formatterSettings/formatterSettingViewSlice"; 6 | 7 | export default configureStore({ 8 | reducer: { 9 | formatterSettings: formatterSettingsViewReducer 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/features/formatterSettings/components/Highlight.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import * as hljs from "highlight.js"; 6 | import "../../../../../../webview-resources/highlight.css"; 7 | 8 | export function highlight(content: string): JSX.Element { 9 | const highlighted = hljs.highlight("java", content); 10 | return ( 11 |
12 |       
13 |     
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/features/formatterSettings/formatterSettingViewSlice.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { createSlice } from "@reduxjs/toolkit"; 5 | import { SupportedSettings, VSCodeSettings } from "../../../FormatterConstants"; 6 | import { Category, JavaFormatterSetting } from "../../../types"; 7 | 8 | export const formatterSettingsViewSlice = createSlice({ 9 | name: "formatterSettings", 10 | initialState: { 11 | activeCategory: Category.Indentation, 12 | profileSettings: [] as JavaFormatterSetting[], 13 | vscodeSettings: [] as JavaFormatterSetting[], 14 | detectIndentation: false, 15 | formattedContent: "", 16 | readOnly: false, 17 | }, 18 | reducers: { 19 | changeActiveCategory: (state, action) => { 20 | state.activeCategory = action.payload; 21 | }, 22 | loadProfileSetting: (state, action) => { 23 | state.profileSettings = action.payload.setting; 24 | }, 25 | loadVSCodeSetting: (state, action) => { 26 | state.vscodeSettings = action.payload.setting; 27 | for (const setting of state.vscodeSettings) { 28 | if (setting.id === SupportedSettings.TABULATION_SIZE) { 29 | document.documentElement.style.setProperty("--vscode-tab-size", setting.value); 30 | } else if (setting.id === VSCodeSettings.DETECT_INDENTATION) { 31 | state.detectIndentation = (setting.value === "true"); 32 | } 33 | } 34 | }, 35 | applyFormatResult: (state, action) => { 36 | state.formattedContent = action.payload.content; 37 | }, 38 | changeReadOnlyState: (state, action) => { 39 | state.readOnly = Boolean(action.payload.value); 40 | }, 41 | }, 42 | }); 43 | 44 | export const { 45 | changeActiveCategory, 46 | loadProfileSetting, 47 | loadVSCodeSetting, 48 | applyFormatResult, 49 | changeReadOnlyState, 50 | } = formatterSettingsViewSlice.actions; 51 | 52 | export default formatterSettingsViewSlice.reducer; 53 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import * as ReactDOM from "react-dom"; 6 | import { Provider } from "react-redux"; 7 | import "./style.scss"; 8 | import { App } from "./App"; 9 | import store from "./app/store"; 10 | 11 | ReactDOM.render( 12 | 13 | 14 | 15 | 16 | , 17 | document.getElementById("formatterPanel") 18 | ); 19 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { ExampleKind } from "../types"; 5 | 6 | declare function acquireVsCodeApi(): any; 7 | const vscode = acquireVsCodeApi(); 8 | 9 | export function onWillInitialize() { 10 | vscode.postMessage({ 11 | command: "onWillInitialize" 12 | }); 13 | } 14 | 15 | export function onWillChangeExampleKind(exampleKind: ExampleKind) { 16 | vscode.postMessage({ 17 | command: "onWillChangeExampleKind", 18 | exampleKind: exampleKind, 19 | }); 20 | } 21 | 22 | export function onWillChangeSetting(id: string, value: any) { 23 | vscode.postMessage({ 24 | command: "onWillChangeSetting", 25 | id: id, 26 | value: value, 27 | }); 28 | } 29 | 30 | export function onWillDownloadAndUse() { 31 | vscode.postMessage({ 32 | command: "onWillDownloadAndUse" 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /src/formatter-settings/assets/whitespace.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | const SPACE_STYLE = "whitespace-style"; 5 | const TAB_STYLE = "tab-style"; 6 | const STYLE_ID = "whitespaceStyle"; 7 | 8 | export function renderWhitespace(): void { 9 | const style: HTMLElement | null = document.getElementById(STYLE_ID); 10 | if (!style) { 11 | const styleElement: HTMLStyleElement = document.createElement("style"); 12 | styleElement.id = STYLE_ID; 13 | styleElement.textContent = ``; 14 | document.head.appendChild(styleElement); 15 | } 16 | const elements = document.querySelectorAll("code"); 17 | for (let i = 0; i < elements.length; i++) { 18 | const treeWalker: TreeWalker = document.createTreeWalker(elements[i], NodeFilter.SHOW_TEXT); 19 | const nodes: Node[] = []; 20 | while (treeWalker.nextNode()) { 21 | nodes.push(treeWalker.currentNode); 22 | } 23 | for (const node of nodes) { 24 | replace(node); 25 | } 26 | } 27 | } 28 | 29 | function replace(node: Node): void { 30 | const textValue: string | null = node.nodeValue; 31 | if (!textValue) { 32 | return; 33 | } 34 | const parent: (Node & ParentNode) | null = node.parentNode; 35 | if (!parent) { 36 | return; 37 | } 38 | const tabs: string[] = textValue.split("\t"); 39 | const tabSpaces: string[][] = tabs.map(s => s.split(" ")); 40 | if (tabSpaces.length === 1 && tabSpaces[0].length === 1) { 41 | return; 42 | } 43 | for (let i = 0; i < tabSpaces.length; i++) { 44 | if (i > 0) { 45 | parent.insertBefore(createTabElement(), node); 46 | } 47 | let spaceCount = 0; 48 | for (let j = 0; j < tabSpaces[i].length; j++) { 49 | if (tabSpaces[i][j] === "" && j !== tabSpaces[i].length - 1) { 50 | spaceCount = spaceCount + 1; 51 | continue; 52 | } 53 | if (spaceCount > 0) { 54 | parent.insertBefore(createSpaceElement(spaceCount), node); 55 | } 56 | parent.insertBefore(document.createTextNode(tabSpaces[i][j]), node); 57 | spaceCount = 1; 58 | } 59 | } 60 | parent.removeChild(node); 61 | } 62 | 63 | function createSpaceElement(count: number): HTMLSpanElement { 64 | const node: HTMLSpanElement = document.createElement("span"); 65 | node.classList.add(SPACE_STYLE); 66 | node.textContent = " ".repeat(count); 67 | return node; 68 | } 69 | 70 | function createTabElement(): HTMLSpanElement { 71 | const node: HTMLSpanElement = document.createElement("span"); 72 | node.classList.add(TAB_STYLE); 73 | node.textContent = "\t"; 74 | return node; 75 | } 76 | -------------------------------------------------------------------------------- /src/formatter-settings/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | export interface JavaFormatterSetting { 6 | id: string; 7 | name: string; 8 | value: string; 9 | candidates?: string[]; 10 | category: Category; 11 | exampleKind: ExampleKind; 12 | valueKind: ValueKind; 13 | // the first profile version the setting becomes valid, default is 1. 14 | startVersion: number; 15 | // the first profile version the settings becomes deprecated, if undefined, the setting is valid in the current version. 16 | deprecatedVersion?: number; 17 | } 18 | 19 | export enum ValueKind { 20 | Boolean, 21 | Number, 22 | Enum, 23 | } 24 | 25 | export enum Category { 26 | Indentation, 27 | Whitespace, 28 | Comment, 29 | Wrapping, 30 | InsertLine, 31 | BlankLine, 32 | } 33 | 34 | export enum ExampleKind { 35 | INDENTATION_EXAMPLE = "Indentation", 36 | BLANKLINE_EXAMPLE = "Blank line", 37 | COMMENT_EXAMPLE = "Comment", 38 | INSERTLINE_EXAMPLE = "Insert Line", 39 | BRACED_CODE_TYPE_EXAMPLE = "Braced type", 40 | BRACED_CODE_RECORD_EXAMPLE = "Braced record", 41 | BRACED_CODE_ENUM_EXAMPLE = "Braced enum", 42 | ANNOTATION_AND_ANONYMOUS_EXAMPLE = "Annotation and anonymous", 43 | WHITESPACE_EXAMPLE = "Whitespace", 44 | WRAPPING_EXAMPLE = "Wrapping", 45 | } 46 | 47 | // two extra properties from @xmldom/xmldom package, see https://www.npmjs.com/package/@xmldom/xmldom 48 | export interface DOMElement extends Element { 49 | lineNumber: number; 50 | columnNumber: number; 51 | } 52 | 53 | export interface DOMAttr extends Attr { 54 | lineNumber: number; 55 | columnNumber: number; 56 | } 57 | 58 | export interface ProfileContent { 59 | isValid: boolean, 60 | settingsVersion: string, 61 | diagnostics: vscode.Diagnostic[], 62 | profileElements?: Map, 63 | profileSettings?: Map, 64 | lastElement?: DOMElement, 65 | supportedProfileSettings?: Map 66 | } 67 | -------------------------------------------------------------------------------- /src/install-jdk/assets/App.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | #root { 5 | display: flex; 6 | justify-content: center; 7 | 8 | div.install-jdk-view { 9 | display: flex; 10 | flex-direction: column; 11 | min-height: 100vh; 12 | width: 400px; 13 | } 14 | } 15 | 16 | ul.jdk-distros { 17 | list-style: none; 18 | padding: 0; 19 | margin-top: 0; 20 | } 21 | 22 | div.btn-download { 23 | font-size: large; 24 | div.asset-info { 25 | font-size: small; 26 | } 27 | } 28 | 29 | .footer .troubleshoot-link { 30 | margin: 0 0.5rem; 31 | } 32 | 33 | @import "../../../node_modules/@vscode/codicons/dist/codicon.css"; 34 | -------------------------------------------------------------------------------- /src/install-jdk/assets/App.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import InstallJDKView from "./features/InstallJDKView"; 6 | import './App.scss'; 7 | 8 | class App extends React.Component { 9 | render() { 10 | return ( 11 | 12 | ); 13 | } 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /src/install-jdk/assets/app/hooks.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 5 | import type { RootState, AppDispatch } from './store' 6 | 7 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 8 | export const useAppDispatch = () => useDispatch() 9 | export const useAppSelector: TypedUseSelectorHook = useSelector 10 | -------------------------------------------------------------------------------- /src/install-jdk/assets/app/store.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { configureStore } from '@reduxjs/toolkit' 5 | import jdksReducer from "../features/installJDKViewSlice"; 6 | 7 | const store = configureStore({ 8 | reducer: { 9 | jdks: jdksReducer 10 | }, 11 | }) 12 | 13 | // Infer the `RootState` and `AppDispatch` types from the store itself 14 | export type RootState = ReturnType 15 | // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} 16 | export type AppDispatch = typeof store.dispatch 17 | 18 | export default store; 19 | -------------------------------------------------------------------------------- /src/install-jdk/assets/features/InstallJDKView.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeLink, VSCodeButton, VSCodePanelView, VSCodePanels, VSCodePanelTab } from "@vscode/webview-ui-toolkit/react"; 5 | import React from 'react'; 6 | import { WEBVIEW_ID } from '../../constants'; 7 | import { encodeExternalLinkWithTelemetry } from '../../../utils/webview'; 8 | import { onWillReloadWindow } from '../vscode.api'; 9 | import AdoptiumJDKPanel from './components/AdoptiumJDKPanel'; 10 | import OtherJDKsPanel from './components/OtherJDKsPanel'; 11 | 12 | export default function InstallJDKView() { 13 | const helpLink = "https://github.com/redhat-developer/vscode-java#setting-the-jdk"; 14 | return ( 15 |
16 |
17 |

Install New JDK

18 |
19 |

{/*reserved for introduction*/}

20 | 21 | Adoptium's Temurin 22 | Others 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |

After you finish JDK installation, please reload Visual Studio Code to make it effective.

32 |
33 | Reload Window 34 | Having trouble? 35 |
36 | 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/install-jdk/assets/features/components/OtherJDKsPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"; 5 | import * as React from 'react'; 6 | import { encodeExternalLinkWithTelemetry } from '../../../../utils/webview'; 7 | import { WEBVIEW_ID } from '../../../constants'; 8 | 9 | class OtherJDKsPanel extends React.Component { 10 | public render() { 11 | const jdkList = [ 12 | { name: "Amazon Corretto", url: "https://aws.amazon.com/corretto" }, 13 | { name: "Azul Zulu", url: "https://www.azul.com/downloads/?package=jdk" }, 14 | { name: "Eclipse Adoptium's Temurin", url: "https://adoptium.net/" }, 15 | { name: "IBM Semeru Runtimes", url: "https://developer.ibm.com/languages/java/semeru-runtimes/"}, 16 | { name: "Microsoft Build of OpenJDK", url: "https://www.microsoft.com/openjdk" }, 17 | { name: "Oracle GraalVM", url: "https://www.graalvm.org/downloads/" }, 18 | { name: "Oracle Java SE", url: "https://www.oracle.com/java/technologies/javase-downloads.html" }, 19 | { name: "Red Hat build of OpenJDK", url: "https://developers.redhat.com/products/openjdk/download" }, 20 | { name: "SapMachine", url: "https://sapmachine.io" } 21 | ]; 22 | return ( 23 |
24 |
    25 | { 26 | jdkList.map((jdk, idx) =>
  • {jdk.name}
  • ) 27 | } 28 |
29 | 30 |
31 | ); 32 | } 33 | } 34 | 35 | export default OtherJDKsPanel; 36 | -------------------------------------------------------------------------------- /src/install-jdk/assets/features/installJDKViewSlice.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { createSlice, PayloadAction } from '@reduxjs/toolkit' 5 | import { AdoptiumAsset, AdoptiumReleaseInfo } from '../../../utils/adoptiumApi' 6 | 7 | // Define a type for the slice state 8 | interface State { 9 | availableReleases?: AdoptiumReleaseInfo; 10 | asset?: AdoptiumAsset; 11 | currentVersion?: number; 12 | } 13 | 14 | // Define the initial state using that type 15 | const initialState: State = { 16 | }; 17 | 18 | export const slice = createSlice({ 19 | name: 'jdks', 20 | initialState, 21 | reducers: { 22 | listReleases: (state, action: PayloadAction) => { 23 | state.availableReleases = action.payload; 24 | state.currentVersion = state.availableReleases.most_recent_lts; 25 | }, 26 | selectVersion: (state, action: PayloadAction) => { 27 | state.currentVersion = action.payload; 28 | }, 29 | showAsset: (state, action: PayloadAction) => { 30 | state.asset = action.payload; 31 | } 32 | }, 33 | }) 34 | 35 | export const { 36 | listReleases, 37 | selectVersion, 38 | showAsset 39 | } = slice.actions 40 | 41 | export default slice.reducer; 42 | -------------------------------------------------------------------------------- /src/install-jdk/assets/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from 'react'; 5 | import * as ReactDOM from 'react-dom'; 6 | import App from './App'; 7 | import { Provider } from 'react-redux' 8 | import store from './app/store'; 9 | 10 | ReactDOM.render( 11 | 12 | 13 | , 14 | document.getElementById('root') as HTMLElement 15 | ); 16 | -------------------------------------------------------------------------------- /src/install-jdk/assets/vscode.api.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | declare function acquireVsCodeApi(): any; 5 | const vscode = acquireVsCodeApi(); 6 | 7 | 8 | export function onWillFetchAvailableReleases() { 9 | vscode.postMessage({ 10 | command: "onWillFetchAvailableReleases" 11 | }); 12 | } 13 | 14 | export function onWillDownloadTemurinJDK(url: string) { 15 | vscode.postMessage({ 16 | command: "onWillDownloadTemurinJDK", 17 | payload: { 18 | url 19 | } 20 | }); 21 | } 22 | 23 | export function onWillFetchAsset(majorVersion?: number) { 24 | vscode.postMessage({ 25 | command: "onWillFetchAsset", 26 | payload: { 27 | majorVersion 28 | } 29 | }); 30 | } 31 | 32 | export function onWillReloadWindow() { 33 | vscode.postMessage({ 34 | command: "onWillReloadWindow", 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /src/install-jdk/constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export const WEBVIEW_ID = "java.installJdk"; 5 | -------------------------------------------------------------------------------- /src/java-runtime/assets/ToolingJDKPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; 5 | import * as React from "react"; 6 | import { JavaRuntimeEntry } from "../types"; 7 | import { onWillBrowseForJDK, onWillRunCommandFromWebview } from './vscode.api'; 8 | 9 | const REQUIRED_JDK_VERSION = 17; 10 | 11 | interface Props { 12 | jdkEntries?: JavaRuntimeEntry[]; 13 | javaDotHome?: string; 14 | javaHomeError?: any; 15 | } 16 | 17 | interface State { 18 | isDirty?: boolean; 19 | } 20 | 21 | export class ToolingJDKPanel extends React.Component { 22 | render = () => { 23 | const { javaHomeError } = this.props; 24 | 25 | return ( 26 |
27 |

Configure Runtime for Language Server

28 |
Java Language Server requires a JDK {REQUIRED_JDK_VERSION}+ to launch itself.
29 | 30 | {javaHomeError && (

{javaHomeError}

)} 31 | 32 |
33 | Locate an Existing JDK 34 | {this?.state?.isDirty && Reload } 35 |
36 |
37 | Install a New JDK 38 |
39 |
40 | ); 41 | } 42 | 43 | onClickBrowseJDKButton = () => { 44 | onWillBrowseForJDK(); 45 | this.setState({ isDirty: true }); 46 | } 47 | 48 | onClickInstallButton = () => { 49 | onWillRunCommandFromWebview("java.runtime", "download", "java.installJdk"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/java-runtime/assets/components/DefaultJDKSelector.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; 5 | import * as React from "react"; 6 | import { JavaRuntimeEntry, ProjectRuntimeEntry } from "../../types"; 7 | import { setDefaultRuntime } from "../vscode.api"; 8 | 9 | interface Props { 10 | jdkEntries: JavaRuntimeEntry[]; 11 | projectRuntime: ProjectRuntimeEntry; 12 | } 13 | 14 | interface State { 15 | isEditing: boolean; 16 | } 17 | 18 | export class DefaultJDKSelector extends React.Component { 19 | constructor(props: any) { 20 | super(props); 21 | this.state = { 22 | isEditing: false 23 | }; 24 | } 25 | 26 | render = () => { 27 | const { jdkEntries, projectRuntime: p } = this.props; 28 | const { isEditing } = this.state; 29 | return ( 30 |
31 | { isEditing ? 32 | 37 | : 38 | {p.sourceLevel} 39 | } 40 | this.onClickEdit()} title="Edit"> 41 |
42 | ); 43 | } 44 | 45 | onSelectionChange = (event: React.ChangeEvent) => { 46 | this.setIsEditing(false); 47 | const { value } = event.target; 48 | const targetJdk = this.props.jdkEntries.find(jdk => jdk.fspath === value); 49 | if (targetJdk) { 50 | setDefaultRuntime(targetJdk.fspath, targetJdk.majorVersion); 51 | } 52 | } 53 | 54 | onClickEdit = () => { 55 | this.setIsEditing(true); 56 | } 57 | 58 | setIsEditing = (isEditing: boolean) => { 59 | this.setState({ 60 | isEditing 61 | }) 62 | } 63 | } -------------------------------------------------------------------------------- /src/java-runtime/assets/components/ProjectTypeHint.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | 6 | interface Props { 7 | projectType: "Maven" | "Gradle" | "Others" | undefined; 8 | } 9 | 10 | export class ProjectTypeHint extends React.Component { 11 | 12 | render = () => { 13 | return ( 14 |
15 | {this.hintContent()} 16 |
17 | ); 18 | } 19 | 20 | hintContent = () => { 21 | const { projectType } = this.props; 22 | switch (projectType) { 23 | case "Maven": 24 | return ( 25 |
26 |

For projects managed by build tools, Java version is specified in build scripts. E.g. to use Java 8, add below lines in pom.xml:

27 |
28 | 29 | <properties>
30 |   <maven.compiler.source>1.8</maven.compiler.source>
31 |   <maven.compiler.target>1.8</maven.compiler.target>
32 | </properties> 33 |
34 |
35 |
36 | ); 37 | case "Gradle": 38 | return ( 39 |
40 |

For projects managed by build tools, Java version is specified in build scripts. E.g. to use Java 8, add below lines in build.gradle:

41 |
42 | 43 | sourceCompatibility = 1.8
44 | targetCompatibility = 1.8
45 |
46 |
47 |
48 | ); 49 | 50 | case "Others": 51 | return ( 52 |
53 |

For folders containing .java files, but not managed by build tools like Maven/Gradle, a default JDK is used.

54 |
55 | ); 56 | default: 57 | return undefined; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/java-runtime/assets/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import * as ReactDOM from "react-dom"; 6 | import "./style.scss"; 7 | import { ProjectJDKPanel } from "./ProjectJDKPanel"; 8 | import { onWillListRuntimes } from "./vscode.api"; 9 | import { ToolingJDKPanel } from "./ToolingJDKPanel"; 10 | 11 | const onInitialize = (event: any) => { 12 | const { data } = event; 13 | if (data.command === "showJavaRuntimeEntries") { 14 | showJavaRuntimeEntries(data.args); 15 | } 16 | }; 17 | 18 | window.addEventListener("message", onInitialize); 19 | onWillListRuntimes(); 20 | 21 | function showJavaRuntimeEntries(args: any) { 22 | if (args.javaHomeError) { 23 | // TODO: remove after tooling JDK is embedded 24 | const props = { 25 | jdkEntries: args.javaRuntimes, 26 | javaHomeError: args.javaHomeError, 27 | javaDotHome: args.javaDotHome 28 | }; 29 | ReactDOM.render(React.createElement(ToolingJDKPanel, props), document.getElementById("content")); 30 | } else { 31 | const props = { 32 | jdkEntries: args.javaRuntimes, 33 | projectRuntimes: args.projectRuntimes, 34 | } 35 | ReactDOM.render(React.createElement(ProjectJDKPanel, props), document.getElementById("content")); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/java-runtime/assets/style.scss: -------------------------------------------------------------------------------- 1 | div#content { 2 | min-width: 550px; 3 | padding: 0 24px 0 24px; 4 | } 5 | 6 | div.container { 7 | margin-top: 1.5rem; 8 | padding: 0 20px 0 20px; 9 | } 10 | 11 | vscode-data-grid-row.sticky-header vscode-data-grid-cell { 12 | font-weight: bold; 13 | } 14 | 15 | select#jdkDropdown { 16 | background-color: var(--dropdown-background); 17 | color: var(--dropdown-foreground); 18 | 19 | align-items: center; 20 | box-sizing: border-box; 21 | border: calc(var(--border-width) * 1px) solid var(--dropdown-border); 22 | border-radius: calc(var(--corner-radius) * 1px); 23 | cursor: pointer; 24 | display: flex; 25 | font-family: inherit; 26 | font-size: var(--type-ramp-base-font-size); 27 | line-height: var(--type-ramp-base-line-height); 28 | min-height: 100%; 29 | width: 100%; 30 | } 31 | 32 | @import "../../../node_modules/@vscode/codicons/dist/codicon.css"; 33 | 34 | div.warning-box { 35 | display: flex; 36 | border: solid 1px; 37 | border-color: var(--vscode-list-warningForeground); 38 | background: var(--vscode-inputValidation-warningBackground); 39 | padding: 0.5rem; 40 | 41 | .codicon { 42 | color: var(--vscode-list-warningForeground); 43 | margin-left: 0.2rem; 44 | margin-right: 0.2rem; 45 | } 46 | } 47 | 48 | div.jdk-action { 49 | display: flex; 50 | margin-top: 0.5rem; 51 | a { 52 | text-decoration: none; 53 | color: var(--button-primary-foreground); 54 | } 55 | vscode-button { 56 | width: 100%; 57 | margin-right: 0.5rem 58 | } 59 | } 60 | 61 | .java-home-error { 62 | color: var(--vscode-list-warningForeground); 63 | } 64 | 65 | div.inline-flex { 66 | display: inline-flex; 67 | } 68 | 69 | div.hintPanel { 70 | margin-top: 2rem; 71 | margin: 0 7px 0 5px; 72 | padding: 0 16px 0 10px; 73 | border-left: 5px solid; 74 | border-color: rgba(0, 122, 204, 0.5); 75 | background: rgba(127, 127, 127, 0.1); 76 | } -------------------------------------------------------------------------------- /src/java-runtime/assets/vscode.api.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | declare function acquireVsCodeApi(): any; 5 | const vscode = acquireVsCodeApi(); 6 | 7 | export function udpateJavaHome(javaHome: string) { 8 | vscode.postMessage({ 9 | command: "updateJavaHome", 10 | javaHome 11 | }); 12 | } 13 | 14 | export function updateRuntimePath(sourceLevel: string, runtimePath: string) { 15 | vscode.postMessage({ 16 | command: "updateRuntimePath", 17 | sourceLevel, 18 | runtimePath 19 | }); 20 | } 21 | 22 | export function setDefaultRuntime(runtimePath: string, majorVersion: number) { 23 | vscode.postMessage({ 24 | command: "setDefaultRuntime", 25 | runtimePath, 26 | majorVersion 27 | }); 28 | } 29 | 30 | export function openBuildScript(rootUri: string, scriptFile: string) { 31 | vscode.postMessage({ 32 | command: "openBuildScript", 33 | rootUri, 34 | scriptFile 35 | }); 36 | } 37 | 38 | export function onWillListRuntimes() { 39 | vscode.postMessage({ 40 | command: "onWillListRuntimes" 41 | }); 42 | } 43 | 44 | export function onWillBrowseForJDK() { 45 | vscode.postMessage({ 46 | command: "onWillBrowseForJDK" 47 | }); 48 | } 49 | 50 | export function onWillRunCommandFromWebview(webview: string, identifier: string, command: string, args?: any[]) { 51 | vscode.postMessage({ 52 | command: "onWillRunCommandFromWebview", 53 | wrappedArgs: { 54 | webview, 55 | identifier, 56 | command, 57 | args 58 | } 59 | }); 60 | } -------------------------------------------------------------------------------- /src/java-runtime/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { ProjectType } from "../utils/webview"; 5 | 6 | export interface JavaRuntimeEntry { 7 | name: string; 8 | fspath: string; 9 | type: string; 10 | majorVersion: number; 11 | } 12 | 13 | export interface JdkData { 14 | os: string; 15 | arch: string; 16 | name: string; 17 | size: string; 18 | downloadLink: string; 19 | } 20 | 21 | export interface ProjectRuntimeEntry { 22 | name: string; 23 | rootPath: string; 24 | runtimePath: string; 25 | sourceLevel: string; 26 | projectType: ProjectType; 27 | } 28 | -------------------------------------------------------------------------------- /src/java-runtime/utils/misc.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as path from "path"; 5 | 6 | export function sourceLevelDisplayName(ver: string | number) { 7 | if (!ver) { 8 | return ""; 9 | } 10 | 11 | if (ver === "1.5" || ver === 5) { 12 | return "J2SE-1.5"; 13 | } 14 | 15 | if (typeof ver === "number") { 16 | return ver <= 8 ? `JavaSE-1.${ver}` : `JavaSE-${ver}`; 17 | } else { 18 | return `JavaSE-${ver}`; 19 | } 20 | } 21 | 22 | export function sourceLevelMajorVersion(level: string): number { 23 | if (!level) { 24 | return 0; 25 | } 26 | 27 | let version = level.replace(/^.*-/, ""); // remove "JaveSE-" 28 | // Ignore "1." prefix for legacy Java versions 29 | if (version.startsWith("1.")) { 30 | version = version.substring(2); 31 | } 32 | 33 | // look into the interesting bits now 34 | const regexp = /\d+/g; 35 | const match = regexp.exec(version); 36 | let javaVersion = 0; 37 | if (match) { 38 | javaVersion = parseInt(match[0], 10); 39 | } 40 | return javaVersion; 41 | } 42 | 43 | export function isSamePath(a: string, b: string): boolean { 44 | return !!(a && b) && path.relative(a, b) === ""; 45 | } 46 | 47 | 48 | export function getMajorVersion(version: string) { 49 | if (!version) { 50 | return 0; 51 | } 52 | // Ignore "1." prefix for legacy Java versions 53 | if (version.startsWith("1.")) { 54 | version = version.substring(2); 55 | } 56 | 57 | // look into the interesting bits now 58 | const regexp = /\d+/g; 59 | const match = regexp.exec(version); 60 | let javaVersion = 0; 61 | if (match) { 62 | javaVersion = parseInt(match[0], 10); 63 | } 64 | return javaVersion; 65 | } 66 | -------------------------------------------------------------------------------- /src/misc/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { RELEASE_NOTE_PRESENTATION_HISTORY } from "../utils/globalState"; 5 | import * as vscode from "vscode"; 6 | import { getReleaseNotesEntries, findLatestReleaseNotes, timeToString, getExtensionVersion } from "../utils"; 7 | 8 | export enum HelpViewType { 9 | Auto = "auto", 10 | Overview = "overview", 11 | GettingStarted = "gettingStarted", 12 | None = "none", 13 | } 14 | 15 | type ReleaseNotesPresentationHistoryEntry = { version: string, timeStamp: string }; 16 | 17 | export async function showReleaseNotesOnStart(context: vscode.ExtensionContext) { 18 | const entries = await getReleaseNotesEntries(context); 19 | const latest = findLatestReleaseNotes(entries); 20 | if(latest.version !== getExtensionVersion()) { 21 | return; // in case we don't draft release note for a version. 22 | } 23 | 24 | const history: ReleaseNotesPresentationHistoryEntry[] = context.globalState.get(RELEASE_NOTE_PRESENTATION_HISTORY) || []; 25 | if (history.some(entry => entry.version === latest.version)) { 26 | return; 27 | } 28 | 29 | await vscode.commands.executeCommand("java.showReleaseNotes", "latest"); 30 | 31 | history.push({ 32 | version: latest.version, 33 | timeStamp: timeToString(new Date()) 34 | }); 35 | 36 | context.globalState.update(RELEASE_NOTE_PRESENTATION_HISTORY, history); 37 | } 38 | -------------------------------------------------------------------------------- /src/overview/assets/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | const $ = require("jquery"); 5 | import "../../assets/vscode.scss"; 6 | import "bootstrap/js/src/tab"; 7 | 8 | window.addEventListener("message", event => { 9 | if (event.data.command === "syncExtensionVisibility") { 10 | syncExtensionVisibility(event.data.installedExtensions); 11 | syncSectionVisibility(); 12 | } else if (event.data.command === "setOverviewVisibility") { 13 | $("#showWhenUsingJava").prop("checked", event.data.visibility); 14 | } 15 | }); 16 | 17 | function syncExtensionVisibility(extensions: any) { 18 | $("div[ext]").each((_index: any, elem: any) => { 19 | const anchor = $(elem); 20 | const ext = (anchor.attr("ext") || "").toLowerCase(); 21 | if (extensions.indexOf(ext) !== -1) { 22 | anchor.hide(); 23 | } else { 24 | anchor.show(); 25 | } 26 | }); 27 | } 28 | 29 | function syncSectionVisibility() { 30 | $("div h3").parent().each((_i: any, div: any) => { 31 | if (!$(div).children("h3 ~ div").is(":visible")) { 32 | $(div).hide(); 33 | } else { 34 | $(div).show(); 35 | } 36 | }); 37 | } 38 | 39 | declare function acquireVsCodeApi(): any; 40 | const vscode = acquireVsCodeApi(); 41 | 42 | $("#showWhenUsingJava").change(function () { 43 | vscode.postMessage({ 44 | command: "setOverviewVisibility", 45 | visibility: $(this).is(":checked") 46 | }); 47 | }); 48 | 49 | function installExtension(extName: string, displayName: string) { 50 | vscode.postMessage({ 51 | command: "java.helper.installExtension", 52 | args: [ extName, displayName ], 53 | }); 54 | } 55 | 56 | $("div[ext] > a").click(function () { 57 | if (this.parentElement) { 58 | installExtension($(this.parentElement).attr("ext") || "", $(this.parentElement).attr("displayName") || ""); 59 | } 60 | }); 61 | 62 | $("a[command]").click(function (event: any) { 63 | event.stopPropagation(); 64 | 65 | const command = $(this).attr("command") || ""; 66 | const args = $(this).attr("args") || undefined; 67 | execCommand(command, args); 68 | }); 69 | 70 | $("button[command]").click(function () { 71 | const command = $(this).attr("command") || ""; 72 | const args = $(this).attr("args") || undefined; 73 | execCommand(command, args); 74 | }); 75 | 76 | function execCommand(command: string, jsonArgs: string | undefined) { 77 | if (command) { 78 | let args = []; 79 | if (jsonArgs) { 80 | const data = JSON.parse(jsonArgs); 81 | if (Array.isArray(data)) { 82 | args = data; 83 | } else { 84 | args.push(data); 85 | } 86 | } 87 | vscode.postMessage({ 88 | command, 89 | args 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/project-settings/assets/classpath/features/ClasspathConfigurationView.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React, { useEffect } from "react"; 5 | import { useSelector, useDispatch } from "react-redux"; 6 | import { Dispatch } from "@reduxjs/toolkit"; 7 | import Output from "./components/Output"; 8 | import Sources from "./components/Sources"; 9 | import Libraries from "./components/Libraries"; 10 | import { listVmInstalls, updateActiveTab } from "./classpathConfigurationViewSlice"; 11 | import JdkRuntime from "./components/JdkRuntime"; 12 | import { VSCodePanelTab, VSCodePanelView, VSCodePanels } from "@vscode/webview-ui-toolkit/react"; 13 | import { ProjectType } from "../../../../utils/webview"; 14 | import UnmanagedFolderSources from "./components/UnmanagedFolderSources"; 15 | import Hint from "./components/Hint"; 16 | import "../style.scss"; 17 | 18 | const ClasspathConfigurationView = (): JSX.Element => { 19 | const activeTab: string = useSelector((state: any) => state.classpathConfig.ui.activeTab); 20 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 21 | const projectType: ProjectType = useSelector((state: any) => state.commonConfig.data.projectType[activeProjectIndex]); 22 | const dispatch: Dispatch = useDispatch(); 23 | 24 | const onClickTab = (tabId: string) => { 25 | dispatch(updateActiveTab(tabId)); 26 | }; 27 | 28 | const onMessage = (event: any) => { 29 | const { data } = event; 30 | if (data.command === "classpath.onDidListVmInstalls") { 31 | dispatch(listVmInstalls(data.vmInstalls)) 32 | } 33 | }; 34 | 35 | useEffect(() => { 36 | window.addEventListener("message", onMessage); 37 | return () => { 38 | window.removeEventListener("message", onMessage); 39 | } 40 | }, []); 41 | 42 | return ( 43 |
44 | 45 | onClickTab("source")}>Sources 46 | onClickTab("jdk")}>JDK Runtime 47 | onClickTab("libraries")}>Libraries 48 | 49 | {[ProjectType.Gradle, ProjectType.Maven].includes(projectType) && ()} 50 | {projectType !== ProjectType.Gradle && projectType !== ProjectType.Maven && ()} 51 | {projectType === ProjectType.UnmanagedFolder && ()} 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 | ); 63 | }; 64 | 65 | export default ClasspathConfigurationView; 66 | -------------------------------------------------------------------------------- /src/project-settings/assets/classpath/features/components/Hint.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeLink} from "@vscode/webview-ui-toolkit/react"; 5 | import React, { useEffect } from "react"; 6 | import { ClasspathEntry, ProjectInfo } from "../../../../types"; 7 | import { useSelector } from "react-redux"; 8 | import { ProjectType } from "../../../../../utils/webview"; 9 | import { updateMaxHeight } from "../../utils"; 10 | import { ClasspathRequest } from "../../../vscode/utils"; 11 | import _ from "lodash"; 12 | 13 | const Hint = (): JSX.Element | null => { 14 | 15 | const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects); 16 | const projectType: ProjectType[] = useSelector((state: any) => state.commonConfig.data.projectType); 17 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 18 | const sources: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.sources[activeProjectIndex]); 19 | const effectiveSources: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.effective.sources[activeProjectIndex]); 20 | const defaultOutput: string = useSelector((state: any) => state.classpathConfig.data.output[activeProjectIndex]); 21 | const effectiveOutput: string = useSelector((state: any) => state.classpathConfig.data.effective.output[activeProjectIndex]); 22 | const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.activeVmInstallPath[activeProjectIndex]); 23 | const effectiveVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.effective.activeVmInstallPath[activeProjectIndex]); 24 | const libraries: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.libraries[activeProjectIndex]); 25 | const effectiveLibraries: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.effective.libraries[activeProjectIndex]); 26 | const classpathModified: boolean = !_.isEqual(sources, effectiveSources) || 27 | defaultOutput !== effectiveOutput || 28 | activeVmInstallPath !== effectiveVmInstallPath || 29 | !_.isEqual(libraries, effectiveLibraries); 30 | 31 | useEffect(() => { 32 | updateMaxHeight(); 33 | }, [projectType, classpathModified]); 34 | 35 | useEffect(() => { 36 | window.addEventListener('resize', updateMaxHeight); 37 | return () => { 38 | window.removeEventListener("resize", updateMaxHeight); 39 | } 40 | }, []); 41 | 42 | if (!classpathModified) { 43 | return null; 44 | } 45 | 46 | let buildFile: string = ""; 47 | if (projectType[activeProjectIndex] === ProjectType.Maven) { 48 | buildFile = "pom.xml"; 49 | } else if (projectType[activeProjectIndex] === ProjectType.Gradle) { 50 | buildFile = "build.gradle"; 51 | } 52 | 53 | const handleOpenBuildFile = () => { 54 | ClasspathRequest.onClickGotoProjectConfiguration(projects[activeProjectIndex].rootPath, projectType[activeProjectIndex]); 55 | }; 56 | 57 | return ( 58 |
59 | {(projectType[activeProjectIndex] === ProjectType.Gradle || projectType[activeProjectIndex] === ProjectType.Maven) && 60 | 61 | '{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, changes made to the classpath might be lost after reloading. 62 | To make permanent changes, please edit the handleOpenBuildFile()}>{buildFile} file. 63 | 64 | } 65 |
66 | ); 67 | }; 68 | 69 | export default Hint; 70 | -------------------------------------------------------------------------------- /src/project-settings/assets/classpath/features/components/Output.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { Dispatch } from "@reduxjs/toolkit"; 5 | import React, { useEffect, useRef } from "react"; 6 | import { useSelector, useDispatch } from "react-redux"; 7 | import { ProjectType } from "../../../../../utils/webview"; 8 | import { ClasspathRequest } from "../../../vscode/utils"; 9 | import { setOutputPath } from "../classpathConfigurationViewSlice"; 10 | import { VSCodeButton, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"; 11 | 12 | const Output = (): JSX.Element | null => { 13 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 14 | const activeProjectIndexRef = useRef(activeProjectIndex); 15 | useEffect(() => { 16 | activeProjectIndexRef.current = activeProjectIndex; 17 | }, [activeProjectIndex]); 18 | 19 | const output: string = useSelector((state: any) => state.classpathConfig.data.output[activeProjectIndex]); 20 | const projectType: ProjectType = useSelector((state: any) => state.commonConfig.data.projectType[activeProjectIndex]); 21 | const dispatch: Dispatch = useDispatch(); 22 | const handleClick = () => { 23 | ClasspathRequest.onWillSelectOutputPath(); 24 | }; 25 | 26 | const onDidSelectOutputPath = (event: OnDidSelectOutputPathEvent) => { 27 | const { data } = event; 28 | if (data.command === "classpath.onDidSelectOutputPath") { 29 | dispatch(setOutputPath({ 30 | activeProjectIndex: activeProjectIndexRef.current, 31 | outputPath: data.output 32 | })); 33 | } 34 | }; 35 | 36 | useEffect(() => { 37 | window.addEventListener("message", onDidSelectOutputPath); 38 | return () => window.removeEventListener("message", onDidSelectOutputPath); 39 | }, []); 40 | 41 | if (projectType !== ProjectType.UnmanagedFolder) { 42 | return null; 43 | } 44 | 45 | return ( 46 |
47 |

Output Path

48 | 52 | handleClick()}> 53 | 54 | 55 | 56 |
57 | ); 58 | }; 59 | 60 | interface OnDidSelectOutputPathEvent { 61 | data: { 62 | command: string 63 | output: string 64 | }; 65 | } 66 | 67 | export default Output; 68 | -------------------------------------------------------------------------------- /src/project-settings/assets/classpath/style.scss: -------------------------------------------------------------------------------- 1 | .setting-header { 2 | color: var(--vscode-settings-headerForeground); 3 | } 4 | 5 | .setting-section { 6 | width: 100%; 7 | } 8 | 9 | .setting-panels { 10 | overflow-x: visible; 11 | 12 | .setting-panels-view { 13 | max-width: 80vw; 14 | flex-direction: column; 15 | } 16 | } 17 | 18 | .setting-section-header { 19 | color: var(--vscode-settings-headerForeground); 20 | display: flex; 21 | align-items: baseline; 22 | 23 | .setting-section-title { 24 | margin: 0; 25 | } 26 | 27 | span { 28 | color: var(--vscode-descriptionForeground); 29 | } 30 | } 31 | 32 | .setting-section-description { 33 | color: var(--vscode-descriptionForeground); 34 | } 35 | 36 | .setting-section-dropdown { 37 | width: 320px; 38 | z-index: 10; 39 | 40 | .dropdown-description { 41 | position: sticky; 42 | top: 0; 43 | background: var(--dropdown-background); 44 | } 45 | &[open][position='below'] .dropdown-above-description { 46 | display: none; 47 | } 48 | 49 | &[open][position='above'] .dropdown-below-description { 50 | display: none; 51 | } 52 | 53 | &[open][position='above'] #add-new-jdk { 54 | margin: calc(var(--design-unit) * 1px) 0; 55 | } 56 | 57 | p { 58 | word-break: break-all; 59 | margin: 0; 60 | padding: 4px; 61 | } 62 | 63 | .setting-section-option { 64 | padding: 0 4px; 65 | .setting-section-option-action { 66 | display: flex; 67 | align-items: flex-end; 68 | .codicon { 69 | margin-right: calc(var(--design-unit) * 1px); 70 | } 71 | } 72 | } 73 | } 74 | 75 | .setting-section-warning { 76 | color: var(--vscode-editorWarning-foreground); 77 | } 78 | 79 | .setting-section-grid-row { 80 | padding-left: 4px; 81 | .setting-section-grid-row-header { 82 | font-weight: 700; 83 | } 84 | .setting-section-grid-cell { 85 | padding: 0; 86 | display: flex; 87 | align-items: center; 88 | } 89 | .setting-section-grid-cell-left { 90 | padding-right: calc(var(--design-unit) * 4px); 91 | } 92 | .setting-section-grid-cell-readonly { 93 | justify-content: space-between; 94 | } 95 | .setting-section-grid-cell-editable { 96 | justify-content: end; 97 | } 98 | .setting-section-grid-text { 99 | flex-grow: 1; 100 | } 101 | 102 | span { 103 | font-size: 12.8px; 104 | line-height: 22px; 105 | word-break: break-all; 106 | } 107 | } 108 | 109 | .setting-section-subtitle { 110 | display: flex; 111 | align-items: baseline; 112 | } 113 | 114 | .setting-section-text { 115 | width: 100%; 116 | max-width: 420px; 117 | word-break: break-all; 118 | } 119 | 120 | .setting-list-actions { 121 | height: calc(var(--design-unit) * 8px); 122 | } 123 | 124 | .setting-overflow-area { 125 | overflow: auto; 126 | max-height: 50vh; 127 | } 128 | 129 | .inactive { 130 | opacity: 0.67; 131 | } 132 | -------------------------------------------------------------------------------- /src/project-settings/assets/classpath/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export const WEBVIEW_ID = "java.classpathConfiguration"; 5 | 6 | // TODO: better way to handle the max height calculation? 7 | export const updateMaxHeight = () => { 8 | let maxHeight = window.innerHeight; 9 | const projectSelector = document.getElementById("project-selector"); 10 | if (projectSelector) { 11 | maxHeight -= projectSelector.getBoundingClientRect().height; 12 | } 13 | const hinter = document.getElementById("hint"); 14 | if (hinter) { 15 | maxHeight -= hinter.getBoundingClientRect().height; 16 | } 17 | const footer = document.getElementById("footer"); 18 | if (footer) { 19 | maxHeight -= footer.getBoundingClientRect().height; 20 | } 21 | maxHeight -= 120; 22 | const areas = Array.from(document.getElementsByClassName("setting-overflow-area") as HTMLCollectionOf); 23 | for (let i = 0; i < areas.length; i++) { 24 | areas[i].style!.maxHeight = (maxHeight <= 10 ? 10 : maxHeight) + "px"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/project-settings/assets/compiler/features/components/Hint.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeLink} from "@vscode/webview-ui-toolkit/react"; 5 | import React from "react"; 6 | import { useSelector } from "react-redux"; 7 | import { ProjectType } from "../../../../../utils/webview"; 8 | import { ClasspathRequest } from "../../../vscode/utils"; 9 | import { ProjectInfo } from "../../../../types"; 10 | import _ from "lodash"; 11 | 12 | const Hint = (): JSX.Element | null => { 13 | 14 | const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects); 15 | const projectType: ProjectType[] = useSelector((state: any) => state.commonConfig.data.projectType); 16 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 17 | const complianceLevel: string = useSelector((state: any) => state.compilerConfig.data.complianceLevel[activeProjectIndex]); 18 | const effectiveComplianceLevel: string = useSelector((state: any) => state.compilerConfig.data.effective.complianceLevel[activeProjectIndex]); 19 | const sourceLevel: string = useSelector((state: any) => state.compilerConfig.data.sourceLevel[activeProjectIndex]); 20 | const effectiveSourceLevel: string = useSelector((state: any) => state.compilerConfig.data.effective.sourceLevel[activeProjectIndex]); 21 | const targetLevel: string = useSelector((state: any) => state.compilerConfig.data.targetLevel[activeProjectIndex]); 22 | const effectiveTargetLevel: string = useSelector((state: any) => state.compilerConfig.data.effective.targetLevel[activeProjectIndex]); 23 | const compilerModified: boolean = complianceLevel !== effectiveComplianceLevel || 24 | sourceLevel !== effectiveSourceLevel || 25 | targetLevel !== effectiveTargetLevel; 26 | 27 | if (!compilerModified) { 28 | return null; 29 | } 30 | 31 | let buildFile: string = ""; 32 | if (projectType[activeProjectIndex] === ProjectType.Maven) { 33 | buildFile = "pom.xml"; 34 | } else if (projectType[activeProjectIndex] === ProjectType.Gradle) { 35 | buildFile = "build.gradle"; 36 | } 37 | 38 | const handleOpenBuildFile = () => { 39 | ClasspathRequest.onClickGotoProjectConfiguration(projects[activeProjectIndex].rootPath, projectType[activeProjectIndex]); 40 | }; 41 | 42 | return ( 43 |
44 | {(projectType[activeProjectIndex] === ProjectType.Gradle || projectType[activeProjectIndex] === ProjectType.Maven) && 45 |
46 | 47 | '{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, some changes made to the compiler settings might be lost after reloading. 48 | To make permanent changes, please edit the handleOpenBuildFile()}>{buildFile} file. 49 | 50 |
51 | } 52 |
53 | ); 54 | }; 55 | 56 | export default Hint; 57 | -------------------------------------------------------------------------------- /src/project-settings/assets/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import * as ReactDOM from "react-dom"; 6 | import App from "./mainpage/features/App"; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | , 12 | document.getElementById("content") 13 | ); 14 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/features/App.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import { Provider } from "react-redux"; 6 | import store from "../../store"; 7 | import ProjectSettingView from "./ProjectSettingView"; 8 | 9 | const App = (): JSX.Element => { 10 | return ( 11 | 12 | 13 | 14 | ); 15 | }; 16 | 17 | export default App; 18 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/features/commonSlice.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { createSlice } from "@reduxjs/toolkit"; 5 | import { ProjectType } from "../../../../utils/webview"; 6 | import { SectionId } from "../../../types"; 7 | import _ from "lodash"; 8 | 9 | export const commonSlice = createSlice({ 10 | name: "commonConfiguration", 11 | initialState: { 12 | ui: { 13 | activeSection: SectionId.Classpath, 14 | activeProjectIndex: 0, 15 | exception: undefined, 16 | loadingState: false, 17 | }, 18 | data: { 19 | projects: [], 20 | projectType: [] as ProjectType[], 21 | } 22 | }, 23 | reducers: { 24 | updateActiveSection: (state, action) => { 25 | state.ui.activeSection = action.payload; 26 | }, 27 | catchException: (state, action) => { 28 | state.ui.exception = action.payload; 29 | }, 30 | updateLoadingState: (state, action) => { 31 | state.ui.loadingState = action.payload; 32 | }, 33 | listProjects: (state, action) => { 34 | state.data.projects = action.payload; 35 | const projectNum = state.data.projects.length; 36 | state.data.projectType = Array(projectNum).fill(""); 37 | }, 38 | activeProjectChange: (state, action) => { 39 | state.ui.activeProjectIndex = action.payload; 40 | // If the active project is not a Maven project, the Maven section is invisible, 41 | // switch to the Classpath section. 42 | if (state.data.projectType[state.ui.activeProjectIndex] !== ProjectType.Maven 43 | && state.ui.activeSection === SectionId.Maven) { 44 | state.ui.activeSection = SectionId.Classpath; 45 | } 46 | }, 47 | setProjectType: (state, action) => { 48 | state.data.projectType[state.ui.activeProjectIndex] = action.payload.projectType; 49 | }, 50 | }, 51 | }); 52 | 53 | export const { 54 | updateActiveSection, 55 | catchException, 56 | updateLoadingState, 57 | listProjects, 58 | activeProjectChange, 59 | setProjectType, 60 | } = commonSlice.actions; 61 | 62 | export default commonSlice.reducer; 63 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/features/component/Exception.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import { useSelector } from "react-redux"; 6 | import { encodeCommandUriWithTelemetry, supportedByNavigator } from "../../../../../utils/webview"; 7 | import { ProjectSettingsException } from "../../../../types"; 8 | import { WEBVIEW_ID } from "../../../classpath/utils"; 9 | 10 | const Exception = (): JSX.Element | null => { 11 | const exception: ProjectSettingsException | undefined = useSelector((state: any) => state.commonConfig.ui.exception); 12 | 13 | let content: JSX.Element; 14 | switch (exception) { 15 | case ProjectSettingsException.NoJavaProjects: 16 | let command: string = "workbench.action.files.openFolder"; 17 | if (supportedByNavigator("mac")) { 18 | command = "workbench.action.files.openFileFolder"; 19 | } 20 | content = ( 21 | There are no Java projects opened in the current workspace. Please try to reload the page or open a Java project. 22 | ); 23 | break; 24 | case ProjectSettingsException.JavaExtensionNotInstalled: 25 | content = ( 26 | The required extension Language Support for Java™ by Red Hat is not installed or it's disabled. Please install it in Visual Studio Code and reload the page after installation. 27 | ); 28 | break; 29 | case ProjectSettingsException.StaleJavaExtension: 30 | content = ( 31 | The version of required extension Language Support for Java™ by Red Hat is too stale. Please update it and reload the page. 32 | ); 33 | break; 34 | default: 35 | return null; 36 | } 37 | 38 | return (
39 | {content} 40 |
41 | ); 42 | }; 43 | 44 | export default Exception; 45 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/features/component/ProjectSelector.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React, { useEffect } from "react"; 5 | import { useSelector, useDispatch } from "react-redux"; 6 | import { ProjectInfo } from "../../../../types"; 7 | import { Dispatch } from "@reduxjs/toolkit"; 8 | import { VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"; 9 | import { activeProjectChange } from "../../../mainpage/features/commonSlice"; 10 | import { ClasspathRequest, CompilerRequest, MavenRequest } from "../../../vscode/utils"; 11 | 12 | const ProjectSelector = (): JSX.Element | null => { 13 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 14 | const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects); 15 | 16 | const dispatch: Dispatch = useDispatch(); 17 | 18 | const handleActiveProjectChange = (index: number) => { 19 | dispatch(activeProjectChange(index)); 20 | }; 21 | 22 | useEffect(() => { 23 | if (projects.length === 0) { 24 | return; 25 | } 26 | 27 | ClasspathRequest.onWillLoadProjectClasspath(projects[activeProjectIndex].rootPath); 28 | CompilerRequest.onWillGetCompilerSettings(projects[activeProjectIndex].rootPath); 29 | MavenRequest.onWillGetSelectedProfiles(projects[activeProjectIndex].rootPath); 30 | }, [activeProjectIndex, projects]); 31 | 32 | const projectSelections = projects.map((project, index) => { 33 | if (projects.length === 0) { 34 | return null; 35 | } 36 | 37 | return ( 38 | handleActiveProjectChange(index)}> 39 | {project.name} 40 | 41 | ); 42 | }); 43 | 44 | return ( 45 |
46 |
47 | Project: 48 | 49 | {projectSelections} 50 | 51 |
52 |
53 | ); 54 | }; 55 | 56 | export default ProjectSelector; 57 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/features/component/SideBar.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import { useSelector, useDispatch } from "react-redux"; 6 | import { Dispatch } from "@reduxjs/toolkit"; 7 | import { updateActiveSection } from "../commonSlice"; 8 | import { CommonRequest } from "../../../vscode/utils"; 9 | import { ProjectType } from "../../../../../utils/webview"; 10 | import { SectionId } from "../../../../types"; 11 | 12 | const SideBar = (): JSX.Element => { 13 | 14 | const activeSection: string = useSelector((state: any) => state.commonConfig.ui.activeSection); 15 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 16 | const projectType: ProjectType = useSelector((state: any) => state.commonConfig.data.projectType[activeProjectIndex]); 17 | 18 | const dispatch: Dispatch = useDispatch(); 19 | 20 | const onClickNavBarItem = (panelId: string) => { 21 | if (panelId === SectionId.Formatter) { 22 | CommonRequest.onWillExecuteCommand("java.formatterSettings"); 23 | return; 24 | } 25 | dispatch(updateActiveSection(panelId)); 26 | }; 27 | 28 | return ( 29 |
30 |
31 |
32 |
onClickNavBarItem(SectionId.Classpath)}> 33 | Classpath 34 |
35 |
onClickNavBarItem(SectionId.Compiler)}> 36 | Compiler 37 |
38 | { 39 | projectType === ProjectType.Maven && ( 40 |
onClickNavBarItem(SectionId.Maven)}> 41 | Maven 42 |
43 | ) 44 | } 45 |
onClickNavBarItem(SectionId.Formatter)}> 46 | Formatter 47 |
48 |
49 |
50 |
51 |
52 | ); 53 | }; 54 | 55 | export default SideBar; 56 | -------------------------------------------------------------------------------- /src/project-settings/assets/mainpage/style.scss: -------------------------------------------------------------------------------- 1 | .app-container { 2 | min-height: calc(100vh - 108px); 3 | display: flex; 4 | flex-direction: row; 5 | height: calc(100vh - 108px); 6 | } 7 | 8 | .app-sidebar { 9 | width: 90px; 10 | flex-grow: 0; 11 | flex-shrink: 0; 12 | display: flex; 13 | flex-direction: row; 14 | z-index: 2; 15 | 16 | .app-sidebar-content { 17 | flex: 1; 18 | 19 | .section-link { 20 | color: var(--vscode-foreground); 21 | line-height: 22px; 22 | 23 | &:hover { 24 | cursor: pointer; 25 | } 26 | 27 | .codicon { 28 | font-size: 12px; 29 | } 30 | } 31 | 32 | .section-link-active { 33 | font-weight: 700; 34 | color: var(--vscode-settings-headerForeground); 35 | } 36 | } 37 | 38 | .app-sidebar-resizer { 39 | flex-grow: 0; 40 | flex-shrink: 0; 41 | flex-basis: 1px; 42 | justify-self: flex-end; 43 | resize: horizontal; 44 | background: var(--vscode-editorWidget-border); 45 | } 46 | } 47 | 48 | .app-frame { 49 | flex: 1; 50 | display: flex; 51 | flex-direction: column; 52 | height: 100vh; 53 | max-height: 100%; 54 | z-index: 1; 55 | min-width: 560px; 56 | margin: 0 18px; 57 | } 58 | 59 | .app-footer { 60 | position: absolute; 61 | bottom: 0; 62 | width: 80%; 63 | background: var(--background); 64 | } 65 | 66 | @import "../utils.scss"; -------------------------------------------------------------------------------- /src/project-settings/assets/maven/features/MavenConfigurationView.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import { useSelector } from "react-redux"; 6 | import { ProjectType } from "../../../../utils/webview"; 7 | import Profile from "./components/Profile"; 8 | 9 | const MavenConfigurationView = (): JSX.Element | null => { 10 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 11 | const projectTypes: ProjectType = useSelector((state: any) => state.commonConfig.data.projectType); 12 | if (projectTypes.length === 0) { 13 | return null; 14 | } 15 | 16 | if (projectTypes[activeProjectIndex] !== ProjectType.Maven) { 17 | return Not a Maven project; 18 | } else { 19 | return ; 20 | } 21 | } 22 | 23 | export default MavenConfigurationView; 24 | -------------------------------------------------------------------------------- /src/project-settings/assets/maven/features/components/Profile.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"; 5 | import React, { Dispatch } from "react"; 6 | import { useDispatch, useSelector } from "react-redux"; 7 | import { updateActiveProfiles } from "../mavenConfigurationViewSlice"; 8 | 9 | const Profile = (): JSX.Element => { 10 | const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); 11 | const activeProfiles: string | undefined = useSelector((state: any) => state.mavenConfig.data.activeProfiles[activeProjectIndex]); 12 | 13 | const dispatch: Dispatch = useDispatch(); 14 | 15 | const handleInput = (e: any) => { 16 | dispatch(updateActiveProfiles({ 17 | activeProjectIndex, 18 | activeProfiles: e.target.value, 19 | })); 20 | } 21 | 22 | return ( 23 |
24 |
25 |

Active Maven Profiles

26 | (comma separated) 27 |
28 | 29 | 32 | 33 |
34 | ); 35 | }; 36 | 37 | export default Profile; 38 | -------------------------------------------------------------------------------- /src/project-settings/assets/maven/features/mavenConfigurationViewSlice.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { createSlice } from "@reduxjs/toolkit"; 5 | import _ from "lodash"; 6 | 7 | export const mavenConfigurationViewSlice = createSlice({ 8 | name: "mavenConfig", 9 | initialState: { 10 | data: { 11 | effective: { 12 | activeProfiles: [] as string[], 13 | }, 14 | activeProfiles: [] as string[], 15 | }, 16 | }, 17 | reducers: { 18 | updateActiveProfiles: (state, action) => { 19 | const activeProjectIndex = action.payload.activeProjectIndex; 20 | state.data.activeProfiles[activeProjectIndex] = action.payload.activeProfiles; 21 | }, 22 | initializeMavenData: (state, action) => { 23 | const projectNum = action.payload.projectsNum; 24 | state.data.activeProfiles = Array(projectNum).fill(undefined); 25 | state.data.effective.activeProfiles = Array(projectNum).fill(undefined); 26 | }, 27 | flushMavenSettingsToEffective: (state, action) => { 28 | const activeProjectIndex = action.payload.activeProjectIndex; 29 | state.data.effective.activeProfiles[activeProjectIndex] = state.data.activeProfiles[activeProjectIndex]; 30 | } 31 | }, 32 | }); 33 | 34 | export const { 35 | updateActiveProfiles, 36 | initializeMavenData, 37 | flushMavenSettingsToEffective, 38 | } = mavenConfigurationViewSlice.actions; 39 | 40 | export default mavenConfigurationViewSlice.reducer; 41 | -------------------------------------------------------------------------------- /src/project-settings/assets/store.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { configureStore } from "@reduxjs/toolkit"; 5 | import classpathConfigurationViewReducer from "./classpath/features/classpathConfigurationViewSlice"; 6 | import compilerConfigurationViewReducer from "./compiler/features/compilerConfigurationViewSlice"; 7 | import commonReducer from "./mainpage/features/commonSlice"; 8 | import mavenConfigurationViewReducer from "./maven/features/mavenConfigurationViewSlice"; 9 | 10 | export default configureStore({ 11 | reducer: { 12 | commonConfig: commonReducer, 13 | classpathConfig: classpathConfigurationViewReducer, 14 | compilerConfig: compilerConfigurationViewReducer, 15 | mavenConfig: mavenConfigurationViewReducer, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /src/project-settings/assets/utils.scss: -------------------------------------------------------------------------------- 1 | @for $i from 0 through 12 { 2 | .pl-#{$i} { 3 | padding-left: calc(var(--design-unit) * #{$i}px); 4 | } 5 | 6 | .pr-#{$i} { 7 | padding-right: calc(var(--design-unit) * #{$i}px); 8 | } 9 | 10 | .pt-#{$i} { 11 | padding-top: calc(var(--design-unit) * #{$i}px); 12 | } 13 | 14 | .pb-#{$i} { 15 | padding-bottom: calc(var(--design-unit) * #{$i}px); 16 | } 17 | } 18 | 19 | @for $i from 0 through 12 { 20 | .ml-#{$i} { 21 | margin-left: calc(var(--design-unit) * #{$i}px); 22 | } 23 | 24 | .mr-#{$i} { 25 | margin-right: calc(var(--design-unit) * #{$i}px); 26 | } 27 | 28 | .mt-#{$i} { 29 | margin-top: calc(var(--design-unit) * #{$i}px); 30 | } 31 | 32 | .mb-#{$i} { 33 | margin-bottom: calc(var(--design-unit) * #{$i}px); 34 | } 35 | } 36 | 37 | .flex-center { 38 | display: flex; 39 | align-items: center; 40 | } 41 | 42 | .invisible { 43 | display: none; 44 | } 45 | 46 | .hidden { 47 | visibility: hidden; 48 | } 49 | 50 | .root { 51 | display: flex; 52 | flex-direction: column; 53 | justify-content: space-between; 54 | flex: 1; 55 | } 56 | 57 | @import "~@vscode/codicons/dist/codicon.css"; -------------------------------------------------------------------------------- /src/project-settings/handlers/MavenRequestHandler.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { instrumentOperation } from "vscode-extension-telemetry-wrapper"; 6 | 7 | const M2E_SELECTED_PROFILES = "org.eclipse.m2e.core.selectedProfiles"; 8 | 9 | export class MavenRequestHandler implements vscode.Disposable { 10 | private webview: vscode.Webview; 11 | private disposables: vscode.Disposable[] = []; 12 | 13 | constructor(webview: vscode.Webview) { 14 | this.webview = webview; 15 | this.disposables.push(this.webview.onDidReceiveMessage(async (message) => { 16 | switch (message.command) { 17 | case "maven.onWillGetSelectedProfiles": 18 | this.onWillGetSelectedProfiles(message.uri); 19 | break; 20 | case "maven.onWillUpdateSelectProfiles": 21 | this.onWillUpdateSelectProfiles(message.uri, message.selectedProfiles); 22 | break; 23 | default: 24 | break; 25 | } 26 | })); 27 | } 28 | 29 | private onWillGetSelectedProfiles = instrumentOperation("projectSettings.maven.onWillGetSelectedProfiles", async (_operationId: string, uri: any): Promise => { 30 | const response: any = await vscode.commands.executeCommand("java.execute.workspaceCommand", 31 | "java.project.getSettings", uri, [M2E_SELECTED_PROFILES]); 32 | const selectedProfiles: string = response?.[M2E_SELECTED_PROFILES]; 33 | if (selectedProfiles) { 34 | this.webview.postMessage({ 35 | command: "maven.onDidGetSelectedProfiles", 36 | uri, 37 | selectedProfiles, 38 | }); 39 | } 40 | }); 41 | 42 | private onWillUpdateSelectProfiles = instrumentOperation("projectSettings.maven.onWillUpdateSelectProfiles", async (_operationId: string, uri: any, selectedProfiles: string[]): Promise => { 43 | await vscode.commands.executeCommand("java.execute.workspaceCommand", 44 | "java.project.updateSettings", uri, { [M2E_SELECTED_PROFILES]: selectedProfiles }); 45 | }); 46 | 47 | public dispose() { 48 | this.disposables.forEach(d => d.dispose()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/project-settings/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import { ProjectType } from "../utils/webview"; 5 | 6 | export interface ProjectInfo { 7 | name: string; 8 | rootPath: string; 9 | } 10 | 11 | export interface VmInstall { 12 | typeName: string; 13 | name: string; 14 | path: string; 15 | version: string; 16 | } 17 | 18 | export interface ClasspathComponent { 19 | projectType: ProjectType; 20 | sourcePaths: ClasspathEntry[]; 21 | defaultOutputPath: string; 22 | jdkPath: string; 23 | libraries: ClasspathEntry[]; 24 | } 25 | 26 | export interface ClasspathEntry { 27 | kind: ClasspathEntryKind; 28 | path: string; 29 | output?: string; 30 | attributes?: { [key: string]: string } 31 | } 32 | 33 | export enum ClasspathEntryKind { 34 | Library = 1, 35 | Project = 2, 36 | Source = 3, 37 | Variable = 4, 38 | Container = 5, 39 | } 40 | 41 | export enum ProjectSettingsException { 42 | JavaExtensionNotInstalled = "javaExtensionNotInstalled", 43 | StaleJavaExtension = "staleJavaExtension", 44 | NoJavaProjects = "noJavaProjects", 45 | } 46 | 47 | export enum SectionId { 48 | Classpath = "classpath", 49 | Compiler = "compiler", 50 | Maven = "maven", 51 | Formatter = "formatter", 52 | } -------------------------------------------------------------------------------- /src/providers/CodeActionProvider.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | 6 | // See: https://github.com/eclipse/eclipse.jdt.ls/blob/f0b68a8251b4971cac58eddc731227b66493ffc9/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDiagnosticsHandler.java#L48 7 | const NOT_ON_CLASSPATH: string = "32"; 8 | export class CodeActionProvider implements vscode.CodeActionProvider { 9 | provideCodeActions(_document: vscode.TextDocument, _range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext): vscode.CodeAction[] { 10 | const classPathDiagnostics: vscode.Diagnostic[] = []; 11 | for (const diagnostic of context.diagnostics) { 12 | if (diagnostic.source === "Java" && diagnostic.code === NOT_ON_CLASSPATH) { 13 | classPathDiagnostics.push(diagnostic); 14 | } 15 | } 16 | 17 | if (classPathDiagnostics.length === 0) { 18 | return []; 19 | } 20 | 21 | const codeAction: vscode.CodeAction = new vscode.CodeAction("Configure classpath"); 22 | codeAction.diagnostics = classPathDiagnostics; 23 | codeAction.command = { 24 | title: "Configure classpath", 25 | command: "java.classpathConfiguration" 26 | }; 27 | codeAction.kind = vscode.CodeActionKind.QuickFix; 28 | return [codeAction]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/recommendation/handler.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper"; 6 | import { isExtensionInstalled, recommendExtension } from "../utils"; 7 | import { KEY_RECOMMENDATION_TIMESTAMP_MAP } from "../utils/globalState"; 8 | 9 | let handler: (...args: any[]) => any; 10 | 11 | export function initialize() { 12 | handler = instrumentOperation("recommendExtension", async (operationId: string, extName: string, message: string) => { 13 | sendInfo(operationId, { 14 | extName: extName 15 | }, {}); 16 | 17 | return recommendExtension(extName, message); 18 | }); 19 | } 20 | 21 | export function extensionRecommendationHandler(context: vscode.ExtensionContext, extName: string, message: string, isForce: boolean = false) { 22 | if (isExtensionInstalled(extName)) { 23 | return; 24 | } 25 | 26 | const timeStampMap: { [key: string]: string; } = context.globalState.get(KEY_RECOMMENDATION_TIMESTAMP_MAP, {}); 27 | if (!isForce && timeStampMap && timeStampMap[extName] !== undefined) { 28 | return; 29 | } 30 | 31 | handler(extName, message); 32 | 33 | timeStampMap[extName] = Date.now().toString(); 34 | 35 | context.globalState.update(KEY_RECOMMENDATION_TIMESTAMP_MAP, timeStampMap); 36 | } 37 | -------------------------------------------------------------------------------- /src/recommendation/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { initialize as initHandler, extensionRecommendationHandler } from "./handler"; 6 | import { isExtensionInstalled, getExtensionContext } from "../utils"; 7 | 8 | export function initialize(_context: vscode.ExtensionContext) { 9 | initHandler(); 10 | } 11 | 12 | export async function validateAndRecommendExtension(extName: string, message: string, isForce: boolean = false) { 13 | if (isExtensionInstalled(extName)) { 14 | return true; 15 | } 16 | 17 | await extensionRecommendationHandler(getExtensionContext(), extName, message, isForce); 18 | 19 | return false; 20 | } 21 | -------------------------------------------------------------------------------- /src/recommendation/xml.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { extensionRecommendationHandler } from "./handler"; 6 | 7 | const EXTENSION_NAME = "redhat.vscode-xml"; 8 | const RECOMMENDATION_MESSAGE = "XML extension is recommended to check the syntax when editing pom.xml."; 9 | 10 | function isPomDotXml(uri: vscode.Uri) { 11 | return !!uri.path && uri.path.toLowerCase().endsWith("pom.xml"); 12 | } 13 | 14 | export function initialize (context: vscode.ExtensionContext) { 15 | context.subscriptions.push(vscode.workspace.onDidOpenTextDocument(e => { 16 | if (isPomDotXml(e.uri)) { 17 | extensionRecommendationHandler(context, EXTENSION_NAME, RECOMMENDATION_MESSAGE); 18 | } 19 | })); 20 | 21 | let isPomDotXmlOpened = vscode.workspace.textDocuments.findIndex(doc => isPomDotXml(doc.uri)) !== -1; 22 | if (isPomDotXmlOpened) { 23 | extensionRecommendationHandler(context, EXTENSION_NAME, RECOMMENDATION_MESSAGE); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/extension.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export function getExtensionName() { 5 | const packageInfo = getPackageInfo(); 6 | return `${packageInfo["publisher"]}.${packageInfo["name"]}`; 7 | } 8 | 9 | export function getExtensionVersion() { 10 | return getPackageInfo()["version"]; 11 | } 12 | 13 | function getPackageInfo() { 14 | return {} = require("../../package.json"); 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/globalState.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export const KEY_RECOMMENDATION_TIMESTAMP_MAP = "recommendationTimeStampMap"; 5 | 6 | // first view (shared) 7 | export const KEY_SHOW_WHEN_USING_JAVA = "showWhenUsingJava"; 8 | // overview 9 | export const KEY_OVERVIEW_LAST_SHOW_TIME = "overviewLastShowTime"; 10 | // welcome 11 | export const KEY_IS_WELCOME_PAGE_VIEWED = "isWelcomePageViewed"; 12 | 13 | // release note (inactive) 14 | export const RELEASE_NOTE_PRESENTATION_HISTORY = "releaseNotesPresentationHistory"; -------------------------------------------------------------------------------- /src/utils/idle.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | 6 | // in milliseconds 7 | let timeElapsed: number = 0; 8 | const INTERVAL = 1000; 9 | // reference - https://medium.com/@slhenty/ui-response-times-acec744f3157 10 | // 5s is when users start to lose focus 11 | const IDLE_THRESHOLD = 5000; 12 | 13 | export function initialize(context: vscode.ExtensionContext) { 14 | context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(vscodeEventHandler)); // switching editor 15 | context.subscriptions.push(vscode.window.onDidChangeTextEditorSelection(vscodeEventHandler)); // change cursor position 16 | context.subscriptions.push(vscode.window.onDidChangeTextEditorVisibleRanges(vscodeEventHandler)); // scrolling 17 | 18 | setInterval(timerEventHandler, INTERVAL); 19 | } 20 | 21 | function vscodeEventHandler() { 22 | timeElapsed = 0; 23 | } 24 | 25 | function timerEventHandler() { 26 | timeElapsed += INTERVAL; 27 | if (timeElapsed >= IDLE_THRESHOLD) { 28 | timeElapsed = 0; 29 | _onIdle.fire(); 30 | } 31 | } 32 | 33 | const _onIdle: vscode.EventEmitter = new vscode.EventEmitter; 34 | export const onIdle: vscode.Event = _onIdle.event; 35 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as crypto from "crypto"; 5 | import * as vscode from "vscode"; 6 | import { readFile as fsReadFile } from "fs"; 7 | import * as util from "util"; 8 | import { initialize as initializeIdle } from "./idle"; 9 | import { initialize as initializeScheduler } from "./scheduler"; 10 | import { sendInfo } from "vscode-extension-telemetry-wrapper"; 11 | 12 | const readFile = util.promisify(fsReadFile); 13 | 14 | let extensionContext: vscode.ExtensionContext; 15 | 16 | export function initialize(context: vscode.ExtensionContext) { 17 | extensionContext = context; 18 | initializeIdle(context); 19 | initializeScheduler(context); 20 | } 21 | 22 | export function getExtensionContext() { 23 | return extensionContext; 24 | } 25 | 26 | export function isExtensionInstalled(extName: string) { 27 | return !!vscode.extensions.getExtension(extName); 28 | } 29 | 30 | export async function recommendExtension(extName: string, message: string): Promise { 31 | const action = "Install"; 32 | const answer = await vscode.window.showInformationMessage(message, action); 33 | if (answer === action) { 34 | await vscode.commands.executeCommand("java.helper.installExtension", extName, extName); 35 | } 36 | } 37 | 38 | export function timeToString(time: Date) { 39 | return time.toString(); 40 | } 41 | 42 | export function stringToTime(str: string) { 43 | return Date.parse(str); 44 | } 45 | 46 | export async function loadTextFromFile(resourceUri: string) { 47 | let buffer = await readFile(resourceUri); 48 | return buffer.toString(); 49 | } 50 | 51 | export * from "./release-notes"; 52 | export * from "./extension"; 53 | 54 | export async function webviewCmdLinkHandler(obj: { webview: string, identifier: string, command: string, args?: string[] }) { 55 | const { webview, identifier, command, args } = obj; 56 | sendInfo("", { 57 | name: "openWebviewUrl", 58 | webview, 59 | identifier 60 | }); 61 | 62 | if (args !== undefined) { 63 | await vscode.commands.executeCommand(command, ...args); 64 | } else { 65 | await vscode.commands.executeCommand(command); 66 | } 67 | } 68 | 69 | export async function openExternalLinkFromWebview(webview: string, identifier: string, url: string) { 70 | await webviewCmdLinkHandler({ 71 | webview, 72 | identifier, 73 | command: "java.helper.openUrl", 74 | args: [url] 75 | }); 76 | } 77 | 78 | export function isInsiders() { 79 | return vscode.env.appName.indexOf('Insider') > 0 || vscode.env.appName.indexOf('OSS') > 0; 80 | } 81 | 82 | export function getNonce() { 83 | let array = new Uint32Array(16); 84 | array = crypto.getRandomValues(array); 85 | const buffer = Buffer.from(array); 86 | return buffer.toString('base64'); 87 | } 88 | -------------------------------------------------------------------------------- /src/utils/jdt.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as path from "path"; 5 | import { NatureId, ProjectType } from "./webview"; 6 | import * as vscode from "vscode"; 7 | 8 | export function getProjectType(fsPath: string, natureIds: string[]): ProjectType { 9 | if (isDefaultProject(fsPath)) { 10 | return ProjectType.Default; 11 | } 12 | 13 | if (natureIds.includes(NatureId.Gradle) || natureIds.includes(NatureId.GradleBs)) { 14 | return ProjectType.Gradle; 15 | } 16 | if (natureIds.includes(NatureId.Maven)){ 17 | return ProjectType.Maven; 18 | } 19 | if (natureIds.includes(NatureId.UnmanagedFolder)) { 20 | return ProjectType.UnmanagedFolder; 21 | } 22 | return ProjectType.Others; 23 | } 24 | 25 | export function isDefaultProject(path: string): boolean { 26 | return path.indexOf("jdt.ls-java-project") > -1; 27 | } 28 | 29 | export function getProjectNameFromUri(uri: string): string { 30 | return path.basename(vscode.Uri.parse(uri).fsPath); 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/release-notes/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import * as fs from "fs"; 6 | import { gt } from "semver"; 7 | import { sendError } from "vscode-extension-telemetry-wrapper"; 8 | 9 | type ReleaseNotesEntry = { fileName: string, version: string }; 10 | 11 | export async function getReleaseNotesEntries(context: vscode.ExtensionContext): Promise { 12 | const dir = context.asAbsolutePath("release-notes"); 13 | const regex = /v((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*))\.md/g; 14 | 15 | return new Promise((resolve, reject) => { 16 | fs.readdir(dir, (err, files) => { 17 | if (err) { 18 | sendError(err); 19 | reject(err); 20 | return; 21 | } 22 | 23 | const entries: any[] = []; 24 | 25 | files.forEach(fileName => { 26 | const match = regex.exec(fileName); 27 | if (!match) { 28 | return; 29 | } 30 | 31 | const [, semver] = match; 32 | 33 | entries.push({ 34 | fileName: fileName, 35 | version: semver 36 | }); 37 | 38 | // global regular expression object is STATEFUL!!! 39 | regex.lastIndex = 0; 40 | }); 41 | 42 | resolve(entries); 43 | }); 44 | }); 45 | } 46 | 47 | export function findLatestReleaseNotes(entries: ReleaseNotesEntry[]) { 48 | let latest = entries[0]; 49 | entries.forEach(entry => { 50 | if (gt(entry.version, latest.version)) { 51 | latest = entry; 52 | } 53 | }); 54 | 55 | return latest; 56 | } 57 | -------------------------------------------------------------------------------- /src/utils/scheduler.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as vscode from "vscode"; 5 | import { onIdle } from "./idle"; 6 | import * as _ from "lodash"; 7 | 8 | interface Action { 9 | name: string; 10 | resolve: (name: string) => void; 11 | } 12 | 13 | const actionQueue: Action[] = []; 14 | const pastActions: string[] = []; 15 | 16 | export function initialize(context: vscode.ExtensionContext) { 17 | context.subscriptions.push(onIdle(() => idleHandler())); 18 | } 19 | 20 | // This is to queue the actions that need attention from users. One thing at a time, only on idle. 21 | export function scheduleAction(name: string, isImmediate: boolean = false, isOneTime: boolean = false): Promise { 22 | const isPastAction = _.some(actionQueue, (action) => action.name === name) || _.some(pastActions, name); 23 | if (isOneTime && isPastAction) { 24 | return Promise.reject(`Action (${name}) was already scheduled or performed once.`); 25 | } 26 | 27 | return new Promise((resolve, _reject) => { 28 | if (isImmediate) { 29 | setImmediate(() => resolve(name)); 30 | return; 31 | } 32 | 33 | actionQueue.push({ 34 | name: name, 35 | resolve: resolve 36 | }); 37 | }); 38 | } 39 | 40 | function idleHandler() { 41 | if (_.isEmpty(actionQueue)) { 42 | return; 43 | } 44 | 45 | const action = actionQueue.shift(); 46 | pastActions.push(action && action.name || ""); 47 | 48 | if (action) { 49 | action.resolve(action && action.name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/utils/webview.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | * URL for webview commands. 6 | * By executing the returned command, telemetry is sent before finally executing {command} {args}. 7 | * 8 | * @param webview ID of the webview where the command runs 9 | * @param identifier will be record in telemetry 10 | * @param command command to execute 11 | * @param args must be an array, if provided 12 | * @returns 13 | */ 14 | export function encodeCommandUriWithTelemetry(webview: string, identifier: string, command: string, args?: any[]) { 15 | const helperCommand = "java.webview.runCommand"; 16 | const wrappedArgs = { 17 | webview, 18 | identifier, 19 | command, 20 | args 21 | }; 22 | return `command:${helperCommand}?${encodeURIComponent(JSON.stringify(wrappedArgs))}`; 23 | } 24 | 25 | export function encodeExternalLinkWithTelemetry(webview: string, name: string, url: string) { 26 | return encodeCommandUriWithTelemetry(webview, name, "java.helper.openUrl", [url]); 27 | } 28 | 29 | /** 30 | * Check if navigator.platform matches os. 31 | * @param os "win", "linux", "mac" 32 | */ 33 | export function supportedByNavigator(os: string): boolean { 34 | // Refer the implementation at https://github.com/microsoft/vscode/blob/413963c489fafa5163b5d6513731c7953de07fb3/src/vs/base/common/platform.ts#L86-L96 35 | const userAgent = navigator.userAgent; 36 | switch(os) { 37 | case "win": 38 | return userAgent.indexOf("Windows") >= 0; 39 | case "linux": 40 | return userAgent.indexOf("Linux") >= 0; 41 | case "mac": 42 | return userAgent.indexOf("Macintosh") >= 0; 43 | } 44 | 45 | return navigator.platform.toLowerCase().indexOf(os.toLowerCase()) === 0; 46 | } 47 | 48 | 49 | export enum ProjectType { 50 | Default = "Default project", 51 | UnmanagedFolder = "Unmanaged folder", 52 | Maven = "Maven", 53 | Gradle = "Gradle", 54 | Others = "Others", 55 | } 56 | 57 | export enum NatureId { 58 | Maven = "org.eclipse.m2e.core.maven2Nature", 59 | Gradle = "org.eclipse.buildship.core.gradleprojectnature", 60 | GradleBs = "com.microsoft.gradle.bs.importer.GradleBuildServerProjectNature", 61 | UnmanagedFolder = "org.eclipse.jdt.ls.unmanagedFolderNature", 62 | } 63 | -------------------------------------------------------------------------------- /src/welcome/assets/components/ControllerPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import React from "react"; 5 | import { Form } from "react-bootstrap"; 6 | import { setWelcomeVisibility } from "../utils"; 7 | 8 | export default class ControllerPanel extends React.Component<{ 9 | showWhenUsingJava?: boolean; 10 | }> { 11 | render() { 12 | let {showWhenUsingJava} = this.props; 13 | 14 | return
15 | 16 | ; 17 | } 18 | 19 | } 20 | 21 | function toggleVisibility(event: React.ChangeEvent) { 22 | setWelcomeVisibility(event.target.checked); 23 | } 24 | -------------------------------------------------------------------------------- /src/welcome/assets/components/GetStartedPage.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import { Col, Container, Row } from "react-bootstrap"; 6 | import ControllerPanel from "./ControllerPanel"; 7 | import Header from "./Header"; 8 | import NavigationPanel from "./NavigationPanel"; 9 | import QuickActionPanel from "./QuickActionPanel"; 10 | import SocialMediaPanel from "./SocialMediaPanel"; 11 | import TourPage from "./TourPage"; 12 | 13 | export class GetStartedPage extends React.Component<{ 14 | showWhenUsingJava: boolean, 15 | firstTimeRun: boolean, 16 | isAwtDisabled: boolean, 17 | }> { 18 | 19 | render() { 20 | return this.renderWelcomePage(); 21 | } 22 | 23 | renderWelcomePage() { 24 | const {showWhenUsingJava, isAwtDisabled} = this.props; 25 | return ( 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | 60 | /** 61 | * @deprecated 62 | */ 63 | renderTourPage() { 64 | return ; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/welcome/assets/components/Header.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import { encodeCommandUriWithTelemetry } from "../../../utils/webview"; 6 | import { WEBVIEW_ID } from "../utils"; 7 | 8 | const DEV_BLOG_LINK = "https://devblogs.microsoft.com/?s=Java+on+Visual+Studio+Code"; 9 | export default class Header extends React.Component { 10 | render() { 11 | const openBlogCommand = encodeCommandUriWithTelemetry(WEBVIEW_ID, "blogs", "java.helper.openUrl", [DEV_BLOG_LINK]); 12 | const title =

Java Help Center

; 13 | const blogsLink = blogs; 14 | const subtitle = Check our {blogsLink} to see what's new; 15 | return ( 16 |
17 |
18 | {title} 19 | {subtitle} 20 |
21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/welcome/assets/components/QuickActionPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import { ListGroup } from "react-bootstrap"; 6 | import { encodeCommandUriWithTelemetry, supportedByNavigator } from "../../../utils/webview"; 7 | import { WEBVIEW_ID } from "../utils"; 8 | 9 | export default class QuickActionPanel extends React.Component<{}, {}> { 10 | render() { 11 | const newProjectElement = 12 | {"Create a "} 13 | {"New Project"} 14 | ; 15 | const existingProjectElement = 16 | {"Open an "} 17 | {"Existing Project"} 18 | ; 19 | const tourElement = 20 | {"Take a "} 21 | {"Tour"} 22 | ; 23 | const actions: any[] = [ 24 | { name: "Create a New Project", command: "java.project.create", element: newProjectElement }, 25 | { name: "Open an Existing Project", command: "workbench.action.files.openFolder", os: "win", element: existingProjectElement }, 26 | { name: "Open an Existing Project", command: "workbench.action.files.openFolder", os: "linux", element: existingProjectElement }, 27 | { name: "Open an Existing Project", command: "workbench.action.files.openFileFolder", os: "mac", element: existingProjectElement }, 28 | { name: "Take a Tour", command: "workbench.action.openWalkthrough", args: ["vscjava.vscode-java-pack#javaWelcome"], element: tourElement } 29 | ]; 30 | const actionItems = actions.filter(action => !action.os || supportedByNavigator(action.os)).map(action => ( 31 | {action.element} 36 | )); 37 | return ( 38 |
39 |
Get Started
40 | 41 | {actionItems} 42 | 43 |
44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/welcome/assets/components/SocialMediaPanel.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import { Icon } from "@iconify/react"; 6 | import bookIcon from "@iconify-icons/codicon/book"; 7 | import githubIcon from "@iconify-icons/codicon/github-inverted"; 8 | import { ListGroup } from "react-bootstrap"; 9 | import { encodeCommandUriWithTelemetry } from "../../../utils/webview"; 10 | import { WEBVIEW_ID } from "../utils"; 11 | 12 | export default class SocialMediaPanel extends React.Component { 13 | render() { 14 | const links = [ 15 | { name: "Documentation", command: "java.helper.openUrl", args: ["https://code.visualstudio.com/docs/java/java-tutorial"], icon: bookIcon }, 16 | { name: "Questions & Issues", command: "java.helper.openUrl", args: ["https://github.com/microsoft/vscode-java-pack/issues"], icon: githubIcon }, 17 | ]; 18 | const elements = links.map(link => ( 19 | {link.name} 23 | 24 | )); 25 | return ( 26 | 27 | {elements} 28 | 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/welcome/assets/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import * as React from "react"; 5 | import * as ReactDOM from "react-dom"; 6 | import { GetStartedPage } from "./components/GetStartedPage"; 7 | import "./style.scss"; 8 | import { onWillFetchInitProps } from "./utils"; 9 | 10 | 11 | const onInitialize = (event: any) => { 12 | const { data } = event; 13 | if (data.command === "onDidFetchInitProps") { 14 | ReactDOM.render(React.createElement(GetStartedPage, data.props), document.getElementById("content")); 15 | } 16 | }; 17 | 18 | window.addEventListener("message", onInitialize); 19 | onWillFetchInitProps(); 20 | -------------------------------------------------------------------------------- /src/welcome/assets/resources/debugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/src/welcome/assets/resources/debugger.png -------------------------------------------------------------------------------- /src/welcome/assets/resources/done.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/welcome/assets/resources/open-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/src/welcome/assets/resources/open-project.png -------------------------------------------------------------------------------- /src/welcome/assets/resources/project-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/src/welcome/assets/resources/project-manager.png -------------------------------------------------------------------------------- /src/welcome/assets/resources/testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/vscode-java-pack/99645e12afb3f9cba365dee6e413a297fb2e9c3b/src/welcome/assets/resources/testing.png -------------------------------------------------------------------------------- /src/welcome/assets/style.scss: -------------------------------------------------------------------------------- 1 | @import "../../assets/vscode.scss"; 2 | 3 | // Custom styles dedicated to this webview: 4 | $nav-tabs-link-active-color: var(--vscode-panelTitle-activeForeground); 5 | $nav-tabs-link-active-bg: transparent; 6 | $nav-tabs-link-active-border-color: transparent; 7 | $nav-tabs-link-hover-border-color: transparent; 8 | $nav-tabs-border-color: transparent; 9 | 10 | $list-group-bg: var(--vscode-peekViewTitle-background); 11 | $list-group-border-color: var(--vscode-peekViewTitle-background); 12 | $list-group-action-active-bg: $list-group-bg; 13 | 14 | @import "~bootstrap/scss/bootstrap"; 15 | 16 | .nav-link, 17 | .nav-link:hover { 18 | color: var(--vscode-panelTitle-inactiveForeground); 19 | text-transform: uppercase; 20 | } 21 | 22 | .nav-tabs a:hover div, 23 | .nav-tabs a.active div { 24 | border-color: transparent transparent var(--vscode-panelTitle-activeBorder) 25 | transparent; 26 | } 27 | 28 | .nav-tabs a div { 29 | border: solid 1px; 30 | padding-bottom: 8px; 31 | border-color: transparent; 32 | } 33 | 34 | .navigation-tab { 35 | padding: 8px 0px 4px 0px; 36 | margin-right: 20px; 37 | } 38 | 39 | .navigation-tabcontent { 40 | padding: 24px 0px 0px 0px; 41 | } 42 | 43 | .tab-content a { 44 | &:hover { 45 | color: var(--vscode-panelTitle-activeForeground); 46 | } 47 | color: var(--vscode-foreground); 48 | width: fit-content; 49 | 50 | svg.codicon { 51 | margin-right: 0.5em; 52 | } 53 | } 54 | 55 | .root { 56 | display: flex; 57 | flex-direction: column; 58 | min-height: 100vh; 59 | width: 400px; 60 | } 61 | 62 | svg.codicon { 63 | width: 1.2em; 64 | height: 1.2em; 65 | } 66 | 67 | .footer { 68 | margin-top: auto; 69 | 70 | a, 71 | a:hover { 72 | color: var(--vscode-editor-foreground); 73 | } 74 | 75 | .page-indicator .dot { 76 | height: 10px; 77 | width: 10px; 78 | background-color: var(--vscode-panelTitle-inactiveForeground); 79 | border-radius: 50%; 80 | display: inline-block; 81 | margin: 5px; 82 | cursor: pointer; 83 | 84 | &.active { 85 | background-color: var(--vscode-textLink-activeForeground); 86 | } 87 | } 88 | } 89 | 90 | $logo-size: 50px; 91 | img.logo { 92 | width: $logo-size; 93 | height: $logo-size; 94 | min-width: $logo-size; 95 | max-width: $logo-size; 96 | } 97 | 98 | div.header { 99 | display: flex; 100 | 101 | h2 { 102 | margin-bottom: 0px; 103 | } 104 | 105 | img.logo { 106 | margin-right: 14px; 107 | } 108 | } 109 | 110 | .list-group a { 111 | margin-bottom: 12px; 112 | } 113 | 114 | div.quick-actions { 115 | a { 116 | color: var(--vscode-descriptionForeground); 117 | 118 | span.highlight { 119 | color: var(--vscode-foreground); 120 | } 121 | } 122 | } 123 | 124 | div.page-content { 125 | img, 126 | div { 127 | margin-top: 20px; 128 | margin-bottom: 20px; 129 | } 130 | 131 | img.screenshot { 132 | width: 360px; 133 | height: 270px; 134 | } 135 | } -------------------------------------------------------------------------------- /src/welcome/assets/utils.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | export const WEBVIEW_ID: string = "java.welcome"; 5 | 6 | // RPC calls to VS Code 7 | declare function acquireVsCodeApi(): any; 8 | const vscode = acquireVsCodeApi && acquireVsCodeApi(); 9 | 10 | export function setWelcomeVisibility(visibility: boolean) { 11 | vscode.postMessage({ 12 | command: "setWelcomeVisibility", 13 | visibility 14 | }); 15 | } 16 | 17 | 18 | export function reportTabSwitch(from: string, to: string) { 19 | vscode.postMessage({ 20 | command: "sendInfo", 21 | data: { 22 | name: "switchTabs", 23 | from, 24 | to 25 | } 26 | }); 27 | } 28 | 29 | export function reportSkipTour(from: string) { 30 | vscode.postMessage({ 31 | command: "sendInfo", 32 | data: { 33 | name: "skipTour", 34 | from 35 | } 36 | }); 37 | } 38 | 39 | /** 40 | * Request main process to fetch init properties for welcome page. 41 | */ 42 | export function onWillFetchInitProps() { 43 | vscode.postMessage({ 44 | command: "onWillFetchInitProps" 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "*": [ 6 | "types/*" 7 | ] 8 | }, 9 | "module": "commonjs", 10 | "target": "es6", 11 | "outDir": "out", 12 | "lib": [ 13 | "es6", 14 | "dom", 15 | "ES2016" 16 | ], 17 | "sourceMap": true, 18 | "rootDir": "src", 19 | /* Strict Type-Checking Option */ 20 | "strict": true, /* enable all strict type-checking options */ 21 | /* Additional Checks */ 22 | "noUnusedLocals": true, /* Report errors on unused locals. */ 23 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 24 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 25 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 26 | "skipLibCheck": true, 27 | "jsx": "react", 28 | /* Enabled for React */ 29 | "esModuleInterop": true, 30 | "allowSyntheticDefaultImports": true, 31 | "noImplicitThis": false /* disabled for jQuery */ 32 | }, 33 | "exclude": [ 34 | "node_modules", 35 | ".vscode-test", 36 | "**/assets", 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-string-throw": true, 4 | "no-unused-expression": true, 5 | "no-duplicate-variable": true, 6 | "curly": true, 7 | "class-name": true, 8 | "semicolon": [ 9 | true, 10 | "always" 11 | ], 12 | "triple-equals": true, 13 | "quotemark": true 14 | }, 15 | "defaultSeverity": "warning" 16 | } 17 | -------------------------------------------------------------------------------- /walkthrough/runtime.md: -------------------------------------------------------------------------------- 1 | ## Install JDK 2 | 3 | If you don't have JDK installed on your machine, you can install it by clicking on __Install JDK__. 4 | 5 | To verify it's installed, [create a new terminal](command:workbench.action.terminal.new) and try running the following command: 6 | 7 | ``` 8 | java -version 9 | ``` 10 | 11 | You should see something similar to the following: 12 | 13 | ``` 14 | java version "1.8.0_311" 15 | Java(TM) SE Runtime Environment (build 1.8.0_311-b11) 16 | Java HotSpot(TM) 64-Bit Server VM (build 25.311-b11, mixed mode) 17 | ``` 18 | 19 | The detailed output will be based on the JDK you install. -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | 4 | module.exports = function (env, argv) { 5 | env = env || {}; 6 | 7 | return [{ 8 | name: 'assets', 9 | mode: 'none', 10 | entry: { 11 | overview: './src/overview/assets/index.ts', 12 | 'beginner-tips': './src/beginner-tips/assets/index.tsx', 13 | 'ext-guide': './src/ext-guide/assets/index.ts', 14 | welcome: './src/welcome/assets/index.ts', 15 | 'project-settings': './src/project-settings/assets/index.tsx', 16 | 'formatter-settings': './src/formatter-settings/assets/index.tsx', 17 | 'install-jdk': './src/install-jdk/assets/index.tsx' 18 | }, 19 | module: { 20 | rules: [{ 21 | test: /\.ts(x?)$/, 22 | exclude: /node_modules/, 23 | use: 'ts-loader' 24 | }, { 25 | test: /\.(scss)$/, 26 | use: [{ 27 | loader: 'style-loader' 28 | }, { 29 | loader: 'css-loader' 30 | }, { 31 | loader: 'postcss-loader', 32 | options: { 33 | postcssOptions: { 34 | plugins: [ 35 | [ 36 | "autoprefixer", 37 | { 38 | // Options 39 | }, 40 | ], 41 | ], 42 | }, 43 | } 44 | }, { 45 | loader: 'sass-loader' 46 | }] 47 | }, { 48 | test: /\.(jpg|png|svg|ico|icns)$/, 49 | type: 'asset', 50 | parser: { 51 | dataUrlCondition: { 52 | maxSize: 200000, 53 | }, 54 | }, 55 | }, { 56 | test: /\.(css)$/, 57 | use: [{ 58 | loader: 'style-loader' 59 | }, { 60 | loader: 'css-loader' 61 | }] 62 | }, { 63 | test: /\.(woff2|ttf)$/, 64 | type: 'asset/inline', 65 | }] 66 | }, 67 | output: { 68 | filename: 'assets/[name]/index.js', 69 | path: path.resolve(__dirname, 'out'), 70 | publicPath: '/', 71 | devtoolModuleFilenameTemplate: "../[resource-path]" 72 | }, 73 | plugins: [ 74 | new webpack.ProvidePlugin({ 75 | process: 'process/browser', 76 | }), 77 | ], 78 | devtool: 'source-map', 79 | resolve: { 80 | extensions: ['.js', '.ts', '.tsx'], 81 | // https://github.com/react-dnd/react-dnd/issues/3425#issuecomment-1214554950 82 | fallback: { 83 | 'process/browser': require.resolve('process/browser'), 84 | } 85 | } 86 | }, { 87 | name: 'extension', 88 | target: 'node', 89 | mode: 'none', 90 | entry: { 91 | extension: './src/extension.ts' 92 | }, 93 | module: { 94 | rules: [{ 95 | test: /\.ts$/, 96 | exclude: /node_modules/, 97 | use: 'ts-loader' 98 | }] 99 | }, 100 | resolve: { 101 | modules: ['node_modules', path.resolve(__dirname, 'src')], 102 | mainFiles: ['index'], 103 | extensions: ['.js', '.ts', '.json'], 104 | preferRelative: true 105 | }, 106 | output: { 107 | filename: '[name].js', 108 | path: path.resolve(__dirname, 'out'), 109 | libraryTarget: "commonjs2", 110 | publicPath: '/', 111 | devtoolModuleFilenameTemplate: "../[resource-path]" 112 | }, 113 | externals: { 114 | 'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module 115 | 'diagnostic-channel-publishers': 'commonjs diagnostic-channel-publishers', 116 | vscode: 'commonjs vscode' 117 | }, 118 | devtool: 'source-map' 119 | }] 120 | }; 121 | -------------------------------------------------------------------------------- /webview-resources/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs2015.css 3 | */ 4 | /* 5 | * Visual Studio 2015 dark style 6 | * Author: Nicolas LLOBERA 7 | */ 8 | 9 | 10 | .hljs-keyword, 11 | .hljs-literal, 12 | .hljs-symbol, 13 | .hljs-name { 14 | color: #569CD6; 15 | } 16 | .hljs-link { 17 | color: #569CD6; 18 | text-decoration: underline; 19 | } 20 | 21 | .hljs-built_in, 22 | .hljs-type { 23 | color: #4EC9B0; 24 | } 25 | 26 | .hljs-number, 27 | .hljs-class { 28 | color: #B8D7A3; 29 | } 30 | 31 | .hljs-string, 32 | .hljs-meta-string { 33 | color: #D69D85; 34 | } 35 | 36 | .hljs-regexp, 37 | .hljs-template-tag { 38 | color: #9A5334; 39 | } 40 | 41 | .hljs-subst, 42 | .hljs-function, 43 | .hljs-title, 44 | .hljs-params, 45 | .hljs-formula { 46 | color: #DCDCDC; 47 | } 48 | 49 | .hljs-comment, 50 | .hljs-quote { 51 | color: #57A64A; 52 | font-style: italic; 53 | } 54 | 55 | .hljs-doctag { 56 | color: #608B4E; 57 | } 58 | 59 | .hljs-meta, 60 | .hljs-meta-keyword, 61 | .hljs-tag { 62 | color: #9B9B9B; 63 | } 64 | 65 | .hljs-variable, 66 | .hljs-template-variable { 67 | color: #BD63C5; 68 | } 69 | 70 | .hljs-attr, 71 | .hljs-attribute, 72 | .hljs-builtin-name { 73 | color: #9CDCFE; 74 | } 75 | 76 | .hljs-section { 77 | color: gold; 78 | } 79 | 80 | .hljs-emphasis { 81 | font-style: italic; 82 | } 83 | 84 | .hljs-strong { 85 | font-weight: bold; 86 | } 87 | 88 | /*.hljs-code { 89 | font-family:'Monospace'; 90 | }*/ 91 | 92 | .hljs-bullet, 93 | .hljs-selector-tag, 94 | .hljs-selector-id, 95 | .hljs-selector-class, 96 | .hljs-selector-attr, 97 | .hljs-selector-pseudo { 98 | color: #D7BA7D; 99 | } 100 | 101 | .hljs-addition { 102 | background-color: var(--vscode-diffEditor-insertedTextBackground, rgba(155, 185, 85, 0.2)); 103 | color: rgb(155, 185, 85); 104 | display: inline-block; 105 | width: 100%; 106 | } 107 | 108 | .hljs-deletion { 109 | background: var(--vscode-diffEditor-removedTextBackground, rgba(255, 0, 0, 0.2)); 110 | color: rgb(255, 0, 0); 111 | display: inline-block; 112 | width: 100%; 113 | } 114 | 115 | 116 | /* 117 | From https://raw.githubusercontent.com/isagalaev/highlight.js/master/src/styles/vs.css 118 | */ 119 | /* 120 | 121 | Visual Studio-like style based on original C# coloring by Jason Diamond 122 | 123 | */ 124 | 125 | .vscode-light .hljs-function, 126 | .vscode-light .hljs-params, 127 | .vscode-light .hljs-number, 128 | .vscode-light .hljs-class { 129 | color: inherit; 130 | } 131 | 132 | .vscode-light .hljs-comment, 133 | .vscode-light .hljs-quote, 134 | .vscode-light .hljs-number, 135 | .vscode-light .hljs-class, 136 | .vscode-light .hljs-variable { 137 | color: #008000; 138 | } 139 | 140 | .vscode-light .hljs-keyword, 141 | .vscode-light .hljs-selector-tag, 142 | .vscode-light .hljs-name, 143 | .vscode-light .hljs-tag { 144 | color: #00f; 145 | } 146 | 147 | .vscode-light .hljs-built_in, 148 | .vscode-light .hljs-builtin-name { 149 | color: #007acc; 150 | } 151 | 152 | .vscode-light .hljs-string, 153 | .vscode-light .hljs-section, 154 | .vscode-light .hljs-attribute, 155 | .vscode-light .hljs-literal, 156 | .vscode-light .hljs-template-tag, 157 | .vscode-light .hljs-template-variable, 158 | .vscode-light .hljs-type { 159 | color: #a31515; 160 | } 161 | 162 | .vscode-light .hljs-selector-attr, 163 | .vscode-light .hljs-selector-pseudo, 164 | .vscode-light .hljs-meta, 165 | .vscode-light .hljs-meta-keyword { 166 | color: #2b91af; 167 | } 168 | 169 | .vscode-light .hljs-title, 170 | .vscode-light .hljs-doctag { 171 | color: #808080; 172 | } 173 | 174 | .vscode-light .hljs-attr { 175 | color: #f00; 176 | } 177 | 178 | .vscode-light .hljs-symbol, 179 | .vscode-light .hljs-bullet, 180 | .vscode-light .hljs-link { 181 | color: #00b0e8; 182 | } 183 | 184 | 185 | .vscode-light .hljs-emphasis { 186 | font-style: italic; 187 | } 188 | 189 | .vscode-light .hljs-strong { 190 | font-weight: bold; 191 | } --------------------------------------------------------------------------------