├── .eslintrc.js ├── .gitignore ├── .npmignore ├── LICENSE ├── Readme.md ├── package.json ├── scripts └── launcher.bat ├── server └── com.microsoft.java.debug.plugin-0.44.0.jar ├── src ├── build.ts ├── classFilter.ts ├── commands.ts ├── configurationProvider.ts ├── debugCodeLensProvider.ts ├── index.ts ├── languageServerPlugin.ts ├── launchCommand.ts ├── lists.ts ├── mainClassPicker.ts ├── processPicker.ts ├── processTree.ts ├── utility.ts └── vimspectorPlugin.ts ├── testprojects ├── .project ├── 1.helloworld │ ├── .classpath │ └── src │ │ └── main │ │ └── java │ │ └── HelloWorld.java ├── 10.junit │ ├── .classpath │ ├── .project │ ├── build.gradle_ │ └── src │ │ ├── main │ │ └── java │ │ │ └── MyClass.java │ │ └── test │ │ └── java │ │ └── MyTest.java ├── 11.maven │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── mycompany │ │ │ │ └── app │ │ │ │ └── App.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── mycompany │ │ │ └── app │ │ │ └── AppTest.java │ └── target │ │ ├── classes │ │ └── com │ │ │ └── mycompany │ │ │ └── app │ │ │ └── App.class │ │ ├── maven-status │ │ └── maven-compiler-plugin │ │ │ ├── compile │ │ │ └── default-compile │ │ │ │ ├── createdFiles.lst │ │ │ │ └── inputFiles.lst │ │ │ └── testCompile │ │ │ └── default-testCompile │ │ │ ├── createdFiles.lst │ │ │ └── inputFiles.lst │ │ ├── surefire-reports │ │ ├── TEST-com.mycompany.app.AppTest.xml │ │ └── com.mycompany.app.AppTest.txt │ │ └── test-classes │ │ └── com │ │ └── mycompany │ │ └── app │ │ └── AppTest.class ├── 12.gradle │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── GradleTest.java ├── 13.customcl │ ├── .classpath │ ├── .project │ ├── replacement │ │ └── Foo.class │ └── src │ │ └── main │ │ └── java │ │ ├── CustomCL.java │ │ ├── CustomClassLoaderTest.java │ │ ├── Foo.java │ │ └── IFoo.java ├── 14.encoding │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.core.resources.prefs │ └── src │ │ └── main │ │ └── java │ │ └── EncodingTest.java ├── 15.specialname │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── ab$c │ │ └── Hello$orld.java ├── 16.resolvemainclass │ ├── .classpath │ ├── .project │ ├── build.gradle_ │ └── src │ │ ├── main │ │ └── java │ │ │ └── MyApp.java │ │ └── test │ │ └── java │ │ └── MyAppTest.java ├── 17.argstest │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.jdt.core.prefs │ └── src │ │ └── test │ │ └── ArgsTest.java ├── 18.attachdebug │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.jdt.core.prefs │ └── src │ │ └── test │ │ └── attachdebug.java ├── 19.java9-app │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ ├── com │ │ │ └── microsoft │ │ │ │ └── app │ │ │ │ ├── App.java │ │ │ │ └── Launcher.java │ │ │ └── module-info.java │ │ └── test │ │ └── java │ │ └── com │ │ └── microsoft │ │ └── app │ │ └── AppTest.java ├── 2.callstack │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ ├── Bar.java │ │ ├── CallStack.java │ │ └── Foo.java ├── 20.usersettings │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── usersettings │ │ └── UserSettings.java ├── 21.evaluate │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── evaluate │ │ └── EvaluateTest.java ├── 21.single-file │ └── Main.java ├── 22.jdkversion │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── JdkVersion.java ├── 23.console-app │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── microsoft │ │ │ └── test │ │ │ └── App.java │ │ └── test │ │ └── java │ │ └── com │ │ └── microsoft │ │ └── test │ │ └── AppTest.java ├── 24.hotCodeReplace │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.jdt.core.prefs │ └── src │ │ └── com │ │ └── microsoft │ │ └── debug │ │ ├── HelloWorld.java │ │ ├── NameProvider.java │ │ └── Person.java ├── 25.restartFrame │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.jdt.core.prefs │ └── src │ │ └── com │ │ └── microsoft │ │ └── debug │ │ ├── HelloWorld.java │ │ ├── NameProvider.java │ │ └── Person.java ├── 26.environmentVariables │ ├── .classpath │ ├── .env │ ├── .project │ ├── .vscode │ │ └── launch.json │ └── src │ │ └── main │ │ └── java │ │ └── EnvrionmentVariable.java ├── 27.runtimeClassEntry │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── github │ │ │ │ └── kdvolder │ │ │ │ └── helloworldservice │ │ │ │ ├── Constants.java │ │ │ │ ├── DemoApplication.java │ │ │ │ ├── Greeter.java │ │ │ │ └── MyProperties.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── github │ │ └── kdvolder │ │ └── helloworldservice │ │ └── DemoApplicationTests.java ├── 28.debugfeatures │ ├── .vscode │ │ └── settings.json │ ├── Java12Preview.java │ ├── LogicalStructure.java │ ├── StackTrace.java │ └── Variables.java ├── 3.thread │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── ThreadTest.java ├── 4.variable │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── VariableTest.java ├── 5.breakpoint │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── BreakPointTest.java ├── 6.recursivefunction │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ └── RecursiveTest.java ├── 7.variableperformance │ ├── .classpath │ ├── .project │ └── src │ │ └── main │ │ └── java │ │ ├── TooManyVariables.java │ │ └── VariablePerfTest.java ├── 8.nosource │ ├── .classpath │ ├── .project │ ├── build.gradle_ │ └── src │ │ └── main │ │ └── java │ │ └── NoSourceTest.java ├── 9.realcase.lucene │ ├── .classpath │ ├── .project │ ├── build.gradle_ │ └── src │ │ └── main │ │ └── java │ │ └── LuceneTest.java ├── longclasspath │ ├── .gitignore │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── longclasspath │ │ │ │ └── DemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── longclasspath │ │ └── DemoApplicationTests.java └── resolveClasspath │ ├── insurance-decision │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ └── resources │ │ │ ├── META-INF │ │ │ ├── kie-deployment-descriptor.xml │ │ │ ├── kmodule.xml │ │ │ └── persistence.xml │ │ │ └── com │ │ │ └── demo │ │ │ └── InsurancePricing.dmn │ │ └── test │ │ ├── java │ │ └── testscenario │ │ │ ├── Launch.java │ │ │ └── ScenarioJunitActivatorTest.java │ │ └── resources │ │ └── com │ │ └── demo │ │ └── test-scenario.scesim │ └── kie-client │ ├── .gitignore │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── client │ │ ├── EmbedMain.java │ │ └── Main.java │ └── resources │ ├── META-INF │ └── MANIFEST.MF │ └── logback.xml ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true, 4 | }, 5 | parser: '@typescript-eslint/parser', 6 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'prettier/@typescript-eslint'], 7 | rules: { 8 | '@typescript-eslint/ban-ts-comment': 'off', 9 | '@typescript-eslint/no-explicit-any': 'off', 10 | '@typescript-eslint/no-non-null-assertion': 'off', 11 | '@typescript-eslint/no-namespace': 'off', 12 | '@typescript-eslint/no-empty-function': 'off', 13 | '@typescript-eslint/explicit-function-return-type': 'off', 14 | '@typescript-eslint/explicit-module-boundary-types': 'off', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | lib/ 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | node_modules 3 | tsconfig.json 4 | *.map 5 | .tags 6 | .DS_Store 7 | webpack.config.js 8 | yarn.lock 9 | yarn-error.log 10 | .github 11 | .eslintrc.js 12 | .prettierrc 13 | .eslintrc.js 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 lidulibai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # !! DEPRECATED 2 | I use [neovim](https://github.com/neovim/neovim) now, [nvim-jdtls](https://github.com/mfussenegger/nvim-jdtls) and [nvim-dap](https://github.com/mfussenegger/nvim-dap) 3 | # coc-java-vimspector 4 | 5 | Fork of [vscode-java-debug](https://github.com/microsoft/vscode-java-debug) to 6 | works with [coc.vim](https://github.com/neoclide/coc.nvim) 7 | and [coc-java](https://github.com/neoclide/coc-java) 8 | 9 | 10 | 11 | https://user-images.githubusercontent.com/14270445/164477764-04025fec-2af7-4251-b511-98209958e001.mov 12 | 13 | 14 | ## Overview 15 | A lightweight Java Debugger based on [Java Debug Server](https://github.com/Microsoft/java-debug) which extends the [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java). It allows users to debug Java code using Visual Studio Code (VS Code). Here's a list of features: 16 | 17 | - Launch/Attach 18 | - Breakpoints/Conditional Breakpoints/Logpoints 19 | - Exceptions 20 | - Pause & Continue 21 | - Step In/Out/Over 22 | - Variables 23 | - Callstacks 24 | - Threads 25 | - Debug console 26 | - Evaluation 27 | - Hot Code Replace 28 | 29 | ## Requirements 30 | - JDK (version 1.8.0 or later) 31 | - coc.nvim (version 0.0.80 or later) 32 | - coc-java 33 | - vimspector 34 | - [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) (version 0.14.0 or later) 35 | 36 | ## Install 37 | 38 | 1. Install this extension by run command: 39 | 40 | ``` 41 | :CocInstall coc-java-vimspector 42 | ``` 43 | 44 | ## Use 45 | 46 | - Launch Vim or Nvim 47 | - Open a Java project (Maven/Gradle/Eclipse) 48 | - Open a Java file to activate the extensions 49 | - :CocList mainClassListRun and select class to start 50 | 51 | Please also check the documentation of [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) if you have trouble setting up your project. 52 | 53 | ## Options 54 | 55 | ### Launch 56 | 57 | - `mainClass` (required) - The fully qualified class name (e.g. [java module name/]com.xyz.MainApp) or the java file path of the program entry. 58 | - `args` - The command line arguments passed to the program. Use `"${command:SpecifyProgramArgs}"` to prompt for program arguments. It accepts a string or an array of string. 59 | - `sourcePaths` - The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories. 60 | - `modulePaths` - The modulepaths for launching the JVM. If not specified, the debugger will automatically resolve from current project. 61 | - `classPaths` - The classpaths for launching the JVM. If not specified, the debugger will automatically resolve from current project. 62 | - `encoding` - The `file.encoding` setting for the JVM. If not specified, 'UTF-8' will be used. Possible values can be found in https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html. 63 | - `vmArgs` - The extra options and system properties for the JVM (e.g. -Xms\ -Xmx\ -D\=\), it accepts a string or an array of string. 64 | - `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. It is required when the workspace has multiple java projects, otherwise the expression evaluation and conditional breakpoint may not work. 65 | - `cwd` - The working directory of the program. Defaults to `${workspaceFolder}`. 66 | - `env` - The extra environment variables for the program. 67 | - `envFile` - Absolute path to a file containing environment variable definitions. 68 | - `stopOnEntry` - Automatically pause the program after launching. 69 | - `console` - The specified console to launch the program. If not specified, use the console specified by the `java.debug.settings.console` user setting. 70 | - `internalConsole` - VS Code debug console (input stream not supported). 71 | - `integratedTerminal` - VS Code integrated terminal. 72 | - `externalTerminal` - External terminal that can be configured in user settings. 73 | - `shortenCommandLine` - When the project has long classpath or big VM arguments, the command line to launch the program may exceed the maximum command line string limitation allowed by the OS. This configuration item provides multiple approaches to shorten the command line. Defaults to `auto`. 74 | - `none` - Launch the program with the standard command line 'java [options] classname [args]'. 75 | - `jarmanifest` - Generate the classpath parameters to a temporary classpath.jar file, and launch the program with the command line 'java -cp classpath.jar classname [args]'. 76 | - `argfile` - Generate the classpath parameters to a temporary argument file, and launch the program with the command line 'java @argfile [args]'. This value only applies to Java 9 and higher. 77 | - `auto` - Automatically detect the command line length and determine whether to shorten the command line via an appropriate approach. 78 | - `stepFilters` - Skip specified classes or methods when stepping. 79 | - `classNameFilters` - [**Deprecated** - replaced by `skipClasses`] Skip the specified classes when stepping. Class names should be fully qualified. Wildcard is supported. 80 | - `skipClasses` - Skip the specified classes when stepping. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo 81 | - `skipSynthetics` - Skip synthetic methods when stepping. 82 | - `skipStaticInitializers` - Skip static initializer methods when stepping. 83 | - `skipConstructors` - Skip constructor methods when stepping. 84 | 85 | ### Attach 86 | 87 | - `hostName` (required, unless using `processId`) - The host name or IP address of remote debuggee. 88 | - `port` (required, unless using `processId`) - The debug port of remote debuggee. 89 | - `processId` - Use process picker to select a process to attach, or Process ID as integer. 90 | - `${command:PickJavaProcess}` - Use process picker to select a process to attach. 91 | - an integer pid - Attach to the specified local process. 92 | - `timeout` - Timeout value before reconnecting, in milliseconds (default to 30000ms). 93 | - `sourcePaths` - The extra source directories of the program. The debugger looks for source code from project settings by default. This option allows the debugger to look for source code in extra directories. 94 | - `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. It is required when the workspace has multiple java projects, otherwise the expression evaluation and conditional breakpoint may not work. 95 | - `stepFilters` - Skip specified classes or methods when stepping. 96 | - `classNameFilters` - [**Deprecated** - replaced by `skipClasses`] Skip the specified classes when stepping. Class names should be fully qualified. Wildcard is supported. 97 | - `skipClasses` - Skip the specified classes when stepping. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo 98 | - `skipSynthetics` - Skip synthetic methods when stepping. 99 | - `skipStaticInitializers` - Skip static initializer methods when stepping. 100 | - `skipConstructors` - Skip constructor methods when stepping. 101 | 102 | ### User Settings 103 | 104 | - `java.debug.logLevel`: minimum level of debugger logs that are sent to VS Code, defaults to `warn`. 105 | - `java.debug.settings.showHex`: show numbers in hex format in "Variables" viewlet, defaults to `false`. 106 | - `java.debug.settings.showStaticVariables`: show static variables in "Variables" viewlet, defaults to `false`. 107 | - `java.debug.settings.showQualifiedNames`: show fully qualified class names in "Variables" viewlet, defaults to `false`. 108 | - `java.debug.settings.showLogicalStructure`: show the logical structure for the Collection and Map classes in "Variables" viewlet, defaults to `true`. 109 | - `java.debug.settings.showToString`: show 'toString()' value for all classes that override 'toString' method in "Variables" viewlet, defaults to `true`. 110 | - `java.debug.settings.maxStringLength`: the maximum length of string displayed in "Variables" or "Debug Console" viewlet, the string longer than this length will be trimmed, defaults to `0` which means no trim is performed. 111 | - `java.debug.settings.numericPrecision`: the precision when formatting doubles in "Variables" or "Debug Console" viewlet. 112 | - `java.debug.settings.hotCodeReplace`: Reload the changed Java classes during debugging, defaults to `manual`. Make sure `java.autobuild.enabled` is not disabled for [VSCode Java](https://github.com/redhat-developer/vscode-java). See the [wiki page](https://github.com/Microsoft/vscode-java-debug/wiki/Hot-Code-Replace) for more information about usages and limitations. 113 | - manual - Click the toolbar to apply the changes. 114 | - auto - Automatically apply the changes after compilation. 115 | - never - Never apply the changes. 116 | - `java.debug.settings.enableRunDebugCodeLens`: enable the code lens provider for the run and debug buttons over main entry points, defaults to `true`. 117 | - `java.debug.settings.forceBuildBeforeLaunch`: force building the workspace before launching java program, defaults to `true`. 118 | - `java.debug.settings.onBuildFailureProceed`: Force to proceed when build fails, defaults to false. 119 | - `java.debug.settings.console`: The specified console to launch Java program, defaults to `integratedTerminal`. If you want to customize the console for a specific debug session, please modify the 'console' config in launch.json. 120 | - `internalConsole` - VS Code debug console (input stream not supported). 121 | - `integratedTerminal` - VS Code integrated terminal. 122 | - `externalTerminal` - External terminal that can be configured in user settings. 123 | - `java.debug.settings.exceptionBreakpoint.skipClasses`: Skip the specified classes when breaking on exception. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo 124 | - `java.debug.settings.stepping.skipClasses`: Skip the specified classes when stepping. You could use the built-in variables such as '$JDK' and '$Libraries' to skip a group of classes, or add a specific class name expression, e.g. java.*, *.Foo 125 | - `java.debug.settings.stepping.skipSynthetics`: Skip synthetic methods when stepping. 126 | - `java.debug.settings.stepping.skipStaticInitializers`: Skip static initializer methods when stepping. 127 | - `java.debug.settings.stepping.skipConstructors`: Skip constructor methods when stepping. 128 | - `java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest`: The maximum number of variables or fields that can be requested in one JDWP request. The higher the value, the less frequently debuggee will be requested when expanding the variable view. Also a large number can cause JDWP request timeout. Defaults to 100. 129 | - `java.debug.settings.jdwp.requestTimeout`: The timeout (ms) of JDWP request when the debugger communicates with the target JVM. Defaults to 3000. 130 | - `java.debug.settings.vmArgs`: The default VM arguments to launch the Java program. Eg. Use '-Xmx1G -ea' to increase the heap size to 1GB and enable assertions. If you want to customize the VM arguments for a specific debug session, please modify the 'vmArgs' config in launch.json. 131 | - `java.silentNotification`: Controls whether notifications can be used to report progress. If true, use status bar to report progress instead. Defaults to `false`. 132 | 133 | 134 | # Troubleshooting 135 | 136 | - See ~/.vimspector.log. 137 | - Run `:messages` to get echoed messages in vim. 138 | 139 | ## License 140 | 141 | EPL 1.0, See [LICENSE](LICENSE) for more information. 142 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coc-java-vimspector", 3 | "version": "0.2.0", 4 | "description": "Java langauage debugging extension for coc.nvim", 5 | "author": "lidulibai <499877253@qq.com>", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/lidulibai/coc-java-vimspector" 10 | }, 11 | "main": "lib/index.js", 12 | "keywords": [ 13 | "coc.nvim", 14 | "java", 15 | "debug", 16 | "debugging", 17 | "debugger" 18 | ], 19 | "engines": { 20 | "coc": "^0.0.80" 21 | }, 22 | "scripts": { 23 | "lint": "eslint src --ext ts", 24 | "clean": "rimraf lib", 25 | "watch": "webpack --watch", 26 | "build": "webpack", 27 | "prepare": "npm-run-all clean build" 28 | }, 29 | "prettier": { 30 | "singleQuote": true, 31 | "printWidth": 120, 32 | "semi": true 33 | }, 34 | "devDependencies": { 35 | "@types/lodash": "^4.14.167", 36 | "@typescript-eslint/eslint-plugin": "^4.8.2", 37 | "@typescript-eslint/parser": "^4.8.2", 38 | "coc.nvim": "^0.0.80", 39 | "eslint": "^7.14.0", 40 | "eslint-config-prettier": "^7.1.0", 41 | "eslint-plugin-prettier": "^3.1.4", 42 | "npm-run-all": "^4.1.5", 43 | "prettier": "^2.2.0", 44 | "rimraf": "^3.0.2", 45 | "ts-loader": "^8.0.11", 46 | "typescript": "^4.1.2", 47 | "webpack": "^5.9.0", 48 | "webpack-cli": "^4.2.0" 49 | }, 50 | "activationEvents": [ 51 | "onLanguage:java" 52 | ], 53 | "contributes": { 54 | "breakpoints": [ 55 | { 56 | "language": "java" 57 | } 58 | ], 59 | "javaExtensions": [ 60 | "./server/com.microsoft.java.debug.plugin-0.44.0.jar" 61 | ], 62 | "configuration": { 63 | "type": "object", 64 | "title": "coc-java-vimspector configuration", 65 | "properties": { 66 | "launch.configurations": { 67 | "type": "array", 68 | "title": "coc-java-vimspector launch configuration", 69 | "default": [], 70 | "description": "Configuration list" 71 | }, 72 | "java.debug.logLevel": { 73 | "type": "string", 74 | "default": "warn", 75 | "description": "%java.debugger.configuration.logLevel.description%", 76 | "enum": [ 77 | "error", 78 | "warn", 79 | "info", 80 | "verbose" 81 | ] 82 | }, 83 | "java.debug.settings.showHex": { 84 | "type": "boolean", 85 | "description": "%java.debugger.configuration.showHex.description%", 86 | "default": false 87 | }, 88 | "java.debug.settings.showStaticVariables": { 89 | "type": "boolean", 90 | "description": "%java.debugger.configuration.showStaticVariables.description%", 91 | "default": false 92 | }, 93 | "java.debug.settings.showQualifiedNames": { 94 | "type": "boolean", 95 | "description": "%java.debugger.configuration.showQualifiedNames.description%", 96 | "default": false 97 | }, 98 | "java.debug.settings.showLogicalStructure": { 99 | "type": "boolean", 100 | "description": "%java.debugger.configuration.showLogicalStructure.description%", 101 | "default": true 102 | }, 103 | "java.debug.settings.showToString": { 104 | "type": "boolean", 105 | "description": "%java.debugger.configuration.showToString.description%", 106 | "default": true 107 | }, 108 | "java.debug.settings.maxStringLength": { 109 | "type": "number", 110 | "description": "%java.debugger.configuration.maxStringLength.description%", 111 | "default": 0 112 | }, 113 | "java.debug.settings.numericPrecision": { 114 | "type": "number", 115 | "description": "%java.debugger.configuration.numericPrecision.description%", 116 | "default": 0 117 | }, 118 | "java.debug.settings.hotCodeReplace": { 119 | "type": "string", 120 | "default": "manual", 121 | "description": "%java.debugger.configuration.hotCodeReplace.description%", 122 | "enum": [ 123 | "auto", 124 | "manual", 125 | "never" 126 | ] 127 | }, 128 | "java.debug.settings.enableRunDebugCodeLens": { 129 | "type": "boolean", 130 | "description": "%java.debugger.configuration.enableRunDebugCodeLens.description%", 131 | "default": true 132 | }, 133 | "java.debug.settings.forceBuildBeforeLaunch": { 134 | "type": "boolean", 135 | "description": "%java.debugger.configuration.forceBuildBeforeLaunch%", 136 | "default": true 137 | }, 138 | "java.debug.settings.onBuildFailureProceed": { 139 | "type": "boolean", 140 | "description": "%java.debugger.configuration.onBuildFailureProceed%", 141 | "default": false 142 | }, 143 | "java.debug.settings.console": { 144 | "type": "string", 145 | "enum": [ 146 | "internalConsole", 147 | "integratedTerminal", 148 | "externalTerminal" 149 | ], 150 | "enumDescriptions": [ 151 | "%java.debugger.launch.internalConsole.description%", 152 | "%java.debugger.launch.integratedTerminal.description%", 153 | "%java.debugger.launch.externalTerminal.description%" 154 | ], 155 | "description": "%java.debugger.configuration.console%", 156 | "default": "integratedTerminal" 157 | }, 158 | "java.debug.settings.exceptionBreakpoint.skipClasses": { 159 | "type": "array", 160 | "description": "%java.debugger.configuration.exceptionBreakpoint.skipClasses%", 161 | "items": { 162 | "anyOf": [ 163 | { 164 | "enum": [ 165 | "$JDK", 166 | "$Libraries", 167 | "java.lang.ClassLoader", 168 | "" 169 | ], 170 | "enumDescriptions": [ 171 | "%java.debugger.launch.skipClasses.skipJDK%", 172 | "%java.debugger.launch.skipClasses.skipLibraries%", 173 | "%java.debugger.launch.skipClasses.skipClassLoader%", 174 | "%java.debugger.launch.skipClasses.skipClassPattern%" 175 | ] 176 | }, 177 | "string" 178 | ] 179 | }, 180 | "default": [] 181 | }, 182 | "java.debug.settings.stepping.skipClasses": { 183 | "type": "array", 184 | "description": "%java.debugger.launch.skipClasses.description%", 185 | "items": { 186 | "anyOf": [ 187 | { 188 | "enum": [ 189 | "$JDK", 190 | "$Libraries", 191 | "java.lang.ClassLoader", 192 | "" 193 | ], 194 | "enumDescriptions": [ 195 | "%java.debugger.launch.skipClasses.skipJDK%", 196 | "%java.debugger.launch.skipClasses.skipLibraries%", 197 | "%java.debugger.launch.skipClasses.skipClassLoader%", 198 | "%java.debugger.launch.skipClasses.skipClassPattern%" 199 | ] 200 | }, 201 | "string" 202 | ] 203 | }, 204 | "default": [] 205 | }, 206 | "java.debug.settings.stepping.skipSynthetics": { 207 | "type": "boolean", 208 | "description": "%java.debugger.launch.skipSynthetics.description%", 209 | "default": false 210 | }, 211 | "java.debug.settings.stepping.skipStaticInitializers": { 212 | "type": "boolean", 213 | "description": "%java.debugger.launch.skipStaticInitializers.description%", 214 | "default": false 215 | }, 216 | "java.debug.settings.stepping.skipConstructors": { 217 | "type": "boolean", 218 | "description": "%java.debugger.launch.skipConstructors.description%", 219 | "default": false 220 | }, 221 | "java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest": { 222 | "type": "number", 223 | "description": "%java.debugger.configuration.jdwp.limitOfVariablesPerJdwpRequest.description%", 224 | "default": 100, 225 | "minimum": 1 226 | }, 227 | "java.debug.settings.jdwp.requestTimeout": { 228 | "type": "number", 229 | "description": "%java.debugger.configuration.jdwp.requestTimeout.description%", 230 | "default": 3000, 231 | "minimum": 100 232 | }, 233 | "java.debug.settings.vmArgs": { 234 | "type": "string", 235 | "description": "%java.debugger.configuration.vmArgs.description%", 236 | "default": "" 237 | }, 238 | "java.silentNotification": { 239 | "type": "boolean", 240 | "description": "%java.debugger.configuration.silentNotification%", 241 | "default": false 242 | } 243 | } 244 | }, 245 | "commands": [ 246 | { 247 | "command": "coc-java-vimspector.Command", 248 | "title": "coc-java-vimspector command title" 249 | } 250 | ] 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /scripts/launcher.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM Change code page to UTF-8 for better compatibility. 4 | @chcp.com 65001 > NUL 5 | 6 | REM Execute real command passed by args 7 | %* 8 | -------------------------------------------------------------------------------- /server/com.microsoft.java.debug.plugin-0.44.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/server/com.microsoft.java.debug.plugin-0.44.0.jar -------------------------------------------------------------------------------- /src/build.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import {commands as Commands, diagnosticManager, DiagnosticSeverity, window, workspace} from 'coc.nvim'; 3 | 4 | import * as commands from './commands'; 5 | import * as lsPlugin from './languageServerPlugin'; 6 | 7 | const JAVA_DEBUG_CONFIGURATION = 'java.debug.settings'; 8 | const ON_BUILD_FAILURE_PROCEED = 'onBuildFailureProceed'; 9 | 10 | export async function buildWorkspace(): Promise { 11 | try { 12 | // this command does not return the result or accept call back function 13 | await commands.executeJavaExtensionCommand(commands.JAVA_BUILD_WORKSPACE, false); 14 | return true; 15 | } catch (e) { 16 | /* handle error */ 17 | window.showErrorMessage("Build error..."); 18 | return false; 19 | } 20 | 21 | // return handleBuildFailure(buildResult.operationId, buildResult.error); 22 | } 23 | 24 | async function handleBuildFailure(operationId: string, err: any): Promise { 25 | const configuration = workspace.getConfiguration(JAVA_DEBUG_CONFIGURATION); 26 | const onBuildFailureProceed = configuration.get(ON_BUILD_FAILURE_PROCEED); 27 | 28 | window.showErrorMessage('Build failed'); 29 | if ( 30 | !onBuildFailureProceed && 31 | (err === lsPlugin.CompileWorkspaceStatus.WITHERROR || err === lsPlugin.CompileWorkspaceStatus.FAILED) 32 | ) { 33 | if (checkErrorsReportedByJavaExtension()) { 34 | Commands.executeCommand('workbench.actions.view.problems'); 35 | } 36 | 37 | const ans = await window.showErrorMessage('Build failed, do you want to continue?', 'Proceed', 'Fix...', 'Cancel'); 38 | if (ans === 'Proceed') { 39 | return true; 40 | } else if (ans === 'Fix...') { 41 | // showFixSuggestions(operationId); 42 | } 43 | 44 | return false; 45 | } 46 | 47 | return true; 48 | } 49 | 50 | function checkErrorsReportedByJavaExtension(): boolean { 51 | const problems = diagnosticManager.getDiagnostics(workspace.root) || []; 52 | for (const problem of problems) { 53 | const fileName = path.basename(problem[0].fsPath || ''); 54 | if (fileName.endsWith('.java') || fileName === 'pom.xml' || fileName.endsWith('.gradle')) { 55 | if (problem[1].filter((diagnostic) => diagnostic.severity === DiagnosticSeverity.Error).length) { 56 | return true; 57 | } 58 | } 59 | } 60 | 61 | return false; 62 | } 63 | -------------------------------------------------------------------------------- /src/classFilter.ts: -------------------------------------------------------------------------------- 1 | import {DebugConfiguration} from './debugCodeLensProvider'; 2 | import {resolveClassFilters} from './languageServerPlugin'; 3 | 4 | export async function populateStepFilters(config: DebugConfiguration) { 5 | if (!config.stepFilters) { 6 | return; 7 | } 8 | 9 | const skipClasses = await substituteFilterVariables(config.stepFilters.skipClasses); 10 | // Migrate classNameFilters to skipClasses. 11 | if (Array.isArray(config.stepFilters.classNameFilters)) { 12 | mergeResult(config.stepFilters.classNameFilters, skipClasses); 13 | } 14 | config.stepFilters.classNameFilters = undefined; 15 | config.stepFilters.skipClasses = skipClasses; 16 | } 17 | 18 | export async function substituteFilterVariables(skipClasses: string[]): Promise { 19 | if (!skipClasses) { 20 | return []; 21 | } 22 | 23 | try { 24 | // Preprocess skipClasses configurations. 25 | if (Array.isArray(skipClasses)) { 26 | const hasReservedName = skipClasses.some((filter) => filter === '$JDK' || filter === '$Libraries'); 27 | return hasReservedName ? await resolveClassFilters(skipClasses) : skipClasses; 28 | } else { 29 | // tslint:disable-next-line:no-console 30 | console.error('Invalid type for skipClasses config:' + skipClasses); 31 | } 32 | } catch (e) { 33 | // tslint:disable-next-line:no-console 34 | console.error(e); 35 | } 36 | 37 | return []; 38 | } 39 | 40 | function mergeResult(newItems: any[], result: string[]) { 41 | newItems.forEach((item) => { 42 | if (result.indexOf(item) < 0) { 43 | result.push(String(item)); 44 | } 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /src/commands.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import {commands, extensions, workspace, Extension, ExtensionInfo, ExtensionState} from 'coc.nvim'; 5 | import * as utility from './utility'; 6 | 7 | export const VSCODE_STARTDEBUG = 'vscode.startDebug'; 8 | 9 | export const VSCODE_ADD_DEBUGCONFIGURATION = 'debug.addConfiguration'; 10 | 11 | export const JAVA_START_DEBUGSESSION = 'vscode.java.startDebugSession'; 12 | 13 | export const JAVA_RESOLVE_CLASSPATH = 'vscode.java.resolveClasspath'; 14 | 15 | export const JAVA_RESOLVE_MAINCLASS = 'vscode.java.resolveMainClass'; 16 | 17 | export const JAVA_VALIDATE_LAUNCHCONFIG = 'vscode.java.validateLaunchConfig'; 18 | 19 | export const JAVA_BUILD_WORKSPACE = 'java.workspace.compile'; 20 | 21 | export const JAVA_EXECUTE_WORKSPACE_COMMAND = 'java.execute.workspaceCommand'; 22 | 23 | export const JAVA_FETCH_USAGE_DATA = 'vscode.java.fetchUsageData'; 24 | 25 | export const JAVA_UPDATE_DEBUG_SETTINGS = 'vscode.java.updateDebugSettings'; 26 | 27 | export const JAVA_RESOLVE_MAINMETHOD = 'vscode.java.resolveMainMethod'; 28 | 29 | export const JAVA_INFER_LAUNCH_COMMAND_LENGTH = 'vscode.java.inferLaunchCommandLength'; 30 | 31 | export const JAVA_CHECK_PROJECT_SETTINGS = 'vscode.java.checkProjectSettings'; 32 | 33 | export const JAVA_RESOLVE_ELEMENT_AT_SELECTION = 'vscode.java.resolveElementAtSelection'; 34 | 35 | export const JAVA_RESOLVE_BUILD_FILES = 'vscode.java.resolveBuildFiles'; 36 | 37 | export const JAVA_IS_ON_CLASSPATH = 'vscode.java.isOnClasspath'; 38 | 39 | export const JAVA_RESOLVE_JAVAEXECUTABLE = 'vscode.java.resolveJavaExecutable'; 40 | 41 | export const JAVA_FETCH_PLATFORM_SETTINGS = 'vscode.java.fetchPlatformSettings'; 42 | 43 | export const JAVA_RESOLVE_CLASSFILTERS = 'vscode.java.resolveClassFilters'; 44 | 45 | export const JAVA_RESOLVE_SOURCE_URI = 'vscode.java.resolveSourceUri'; 46 | 47 | /** 48 | * vscode-java-debug command to start a debug session. 49 | */ 50 | export const JAVA_START_DEBUG_SESSION = 'vscode.java.startDebugSession'; 51 | 52 | /** 53 | * coc command to start a java debugger session and connect vimspector to it. 54 | */ 55 | export const JAVA_DEBUG_VIMSPECTOR_START = 'java.debug.vimspector.start1'; 56 | 57 | /** 58 | * Execute Workspace Command 59 | */ 60 | export const EXECUTE_WORKSPACE_COMMAND = 'java.execute.workspaceCommand'; 61 | 62 | export function executeJavaLanguageServerCommand(...rest) { 63 | return executeJavaExtensionCommand(JAVA_EXECUTE_WORKSPACE_COMMAND, ...rest); 64 | } 65 | 66 | export async function executeJavaExtensionCommand(commandName: string, ...rest) { 67 | // TODO: need to handle error and trace telemetry 68 | // const javaExtension = utility.getJavaExtension(); 69 | // if (!javaExtension) { 70 | // workspace.showMessage(`Cannot execute command ${commandName}, VS Code Java Extension is not enabled.`); 71 | // } 72 | // if (!javaExtension.isActive) { 73 | // await javaExtension.activate(); 74 | // } 75 | return commands.executeCommand(commandName, ...rest); 76 | } 77 | -------------------------------------------------------------------------------- /src/configurationProvider.ts: -------------------------------------------------------------------------------- 1 | import {Uri, window, workspace, WorkspaceConfiguration, WorkspaceFolder} from 'coc.nvim'; 2 | import _ from 'lodash'; 3 | import {buildWorkspace} from './build'; 4 | import {populateStepFilters} from './classFilter'; 5 | import {DebugConfiguration} from './debugCodeLensProvider'; 6 | import * as lsPlugin from './languageServerPlugin'; 7 | import { 8 | addMoreHelpfulVMArgs, 9 | getJavaVersion, 10 | getShortenApproachForCLI, 11 | validateRuntimeCompatibility, 12 | } from './launchCommand'; 13 | import {resolveJavaProcess} from './processPicker'; 14 | import * as utility from './utility'; 15 | import fs from 'fs'; 16 | import {mainClassPicker} from './mainClassPicker'; 17 | import path from 'path'; 18 | import * as os from 'os'; 19 | 20 | export async function resolveAndValidateDebugConfiguration(folder: WorkspaceFolder | null, config: DebugConfiguration) { 21 | // If no debug configuration is provided, then generate one in memory. 22 | if (isEmptyConfig(config)) { 23 | config.type = 'java'; 24 | config.name = 'Java Debug'; 25 | config.request = 'launch'; 26 | } 27 | 28 | if (config.request === 'launch') { 29 | // If the user doesn't specify 'vmArgs' in launch.json, use the global setting to get the default vmArgs. 30 | if (config.vmArgs === undefined) { 31 | const debugSettings: WorkspaceConfiguration = workspace.getConfiguration('java.debug.settings'); 32 | config.vmArgs = debugSettings.vmArgs; 33 | } 34 | // If the user doesn't specify 'console' in launch.json, use the global setting to get the launch console. 35 | if (!config.console) { 36 | const debugSettings: WorkspaceConfiguration = workspace.getConfiguration('java.debug.settings'); 37 | config.console = debugSettings.console; 38 | } 39 | // If the console is integratedTerminal, don't auto switch the focus to DEBUG CONSOLE. 40 | if (config.console === 'integratedTerminal' && !config.internalConsoleOptions) { 41 | config.internalConsoleOptions = 'neverOpen'; 42 | } 43 | 44 | if (needsBuildWorkspace()) { 45 | window.showMessage('Compiling...'); 46 | const proceed = await buildWorkspace(); 47 | if (!proceed) { 48 | return undefined; 49 | } 50 | } 51 | 52 | if (!config.mainClass) { 53 | window.showMessage('Resolving main class...'); 54 | } else { 55 | window.showMessage('Resolving launch configuration...'); 56 | } 57 | const mainClassOption = await resolveAndValidateMainClass(folder && Uri.parse(folder.uri), config); 58 | if (!mainClassOption || !mainClassOption.mainClass) { 59 | // Exit silently if the user cancels the prompt fix by ESC. 60 | // Exit the debug session. 61 | return undefined; 62 | } 63 | 64 | config.mainClass = mainClassOption.mainClass; 65 | config.projectName = mainClassOption.projectName; 66 | 67 | if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) { 68 | const result = await lsPlugin.resolveClasspath(config.mainClass, config.projectName); 69 | config.modulePaths = result[0]; 70 | config.classPaths = result[1]; 71 | config.classPathString = result[1].toString().replace(/,/g, ' '); 72 | } 73 | if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) { 74 | window.showErrorMessage( 75 | 'Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.' 76 | ); 77 | return undefined; 78 | } 79 | 80 | config.javaExec = await lsPlugin.resolveJavaExecutable(config.mainClass, config.projectName); 81 | // Add the default launch options to the config. 82 | config.cwd = config.cwd || _.get(folder, 'uri.fsPath'); 83 | if (Array.isArray(config.args)) { 84 | config.args = concatArgs(config.args); 85 | } 86 | 87 | if (Array.isArray(config.vmArgs)) { 88 | config.vmArgs = concatArgs(config.vmArgs); 89 | } 90 | 91 | // Populate the class filters to the debug configuration. 92 | await populateStepFilters(config); 93 | 94 | const targetJavaVersion: number = await getJavaVersion(config.javaExec); 95 | // Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag. 96 | if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) { 97 | config.vmArgs = (config.vmArgs || '') + ' --enable-preview'; 98 | validateRuntimeCompatibility(targetJavaVersion); 99 | } 100 | 101 | // Add more helpful vmArgs. 102 | await addMoreHelpfulVMArgs(config, targetJavaVersion); 103 | 104 | if (!config.shortenCommandLine || config.shortenCommandLine === 'auto') { 105 | config.shortenCommandLine = await getShortenApproachForCLI(config, targetJavaVersion); 106 | } 107 | 108 | if (process.platform === 'win32' && config.console !== 'internalConsole') { 109 | config.launcherScript = utility.getLauncherScriptPath(); 110 | } 111 | } else if (config.request === 'attach') { 112 | if (config.hostName && config.port) { 113 | config.processId = undefined; 114 | // Continue if the hostName and port are configured. 115 | } else if (config.processId !== undefined) { 116 | // tslint:disable-next-line 117 | if (config.processId === '${command:PickJavaProcess}') { 118 | return undefined; 119 | } 120 | 121 | const pid = Number(config.processId); 122 | if (Number.isNaN(pid)) { 123 | window.showErrorMessage(`The processId config '${config.processId}' is not a valid process id.`); 124 | return undefined; 125 | } 126 | 127 | const javaProcess = await resolveJavaProcess(pid); 128 | if (!javaProcess) { 129 | window.showErrorMessage( 130 | `Attach to process: pid '${config.processId}' is not a debuggable Java process. ` + 131 | `Please make sure the process has turned on debug mode using vmArgs like ` + 132 | `'-agentlib:jdwp=transport=dt_socket,server=y,address=5005.'` 133 | ); 134 | return undefined; 135 | } 136 | 137 | config.processId = undefined; 138 | config.hostName = javaProcess.hostName; 139 | config.port = javaProcess.debugPort; 140 | } else { 141 | window.showErrorMessage( 142 | 'Please specify the hostName/port directly, or provide the processId of the remote debuggee in the launch.json.' 143 | ); 144 | } 145 | 146 | // Populate the class filters to the debug configuration. 147 | await populateStepFilters(config); 148 | } else { 149 | window.showErrorMessage( 150 | `Request type "${config.request}" is not supported. Only "launch" and "attach" are supported.` 151 | ); 152 | return undefined; 153 | } 154 | 155 | delete config.__progressId; 156 | return config; 157 | } 158 | 159 | /** 160 | * When VS Code cannot find any available DebugConfiguration, it passes a { noDebug?: boolean } to resolve. 161 | * This function judges whether a DebugConfiguration is empty by filtering out the field "noDebug". 162 | */ 163 | function isEmptyConfig(config: DebugConfiguration): boolean { 164 | return Object.keys(config).filter((key: string) => key !== 'noDebug').length === 0; 165 | } 166 | 167 | function needsBuildWorkspace(): boolean { 168 | const debugSettingsRoot: WorkspaceConfiguration = workspace.getConfiguration('java.debug.settings'); 169 | return debugSettingsRoot ? debugSettingsRoot.forceBuildBeforeLaunch : true; 170 | } 171 | 172 | /** 173 | * Converts an array of arguments to a string as the args and vmArgs. 174 | */ 175 | function concatArgs(args: any[]): string { 176 | return _.join( 177 | _.map(args, (arg: any): string => { 178 | const str = String(arg); 179 | // if it has quotes or spaces, use double quotes to wrap it 180 | if (/["\s]/.test(str)) { 181 | return '"' + str.replace(/(["\\])/g, '\\$1') + '"'; 182 | } 183 | return str; 184 | 185 | // if it has only single quotes 186 | }), 187 | ' ' 188 | ); 189 | } 190 | 191 | async function resolveAndValidateMainClass( 192 | folder: Uri | null, 193 | config: DebugConfiguration 194 | ): Promise { 195 | if (!config.mainClass || isFile(config.mainClass)) { 196 | const currentFile = config.mainClass || workspace.nvim.eval("expand('%:p')"); 197 | window.showMessage(currentFile); 198 | if (currentFile) { 199 | const mainEntries = await lsPlugin.resolveMainMethod(Uri.file(currentFile)); 200 | if (mainEntries.length) { 201 | return mainClassPicker.showQuickPick(mainEntries, 'Please select a main class you want to run.'); 202 | } 203 | } 204 | 205 | const hintMessage = currentFile 206 | ? `The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` 207 | : 'Please select a main class you want to run.'; 208 | return promptMainClass(folder, hintMessage); 209 | } 210 | 211 | const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths); 212 | const validationResponse = await lsPlugin.validateLaunchConfig( 213 | config.mainClass, 214 | config.projectName, 215 | containsExternalClasspaths, 216 | folder 217 | ); 218 | if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) { 219 | return fixMainClass(folder, config, validationResponse); 220 | } 221 | 222 | return { 223 | mainClass: config.mainClass, 224 | projectName: config.projectName, 225 | }; 226 | } 227 | 228 | function isFile(filePath: string): boolean { 229 | try { 230 | return fs.lstatSync(filePath).isFile(); 231 | } catch (error) { 232 | // do nothing 233 | return false; 234 | } 235 | } 236 | 237 | async function promptMainClass( 238 | folder: Uri | null, 239 | hintMessage?: string 240 | ): Promise { 241 | const res = await lsPlugin.resolveMainClass(folder); 242 | if (res.length === 0) { 243 | const workspaceFolder = folder ? workspace.getWorkspaceFolder(folder.toString()) : undefined; 244 | window.showErrorMessage( 245 | `Cannot find a class with the main method${workspaceFolder ? " in the folder '" + workspaceFolder.name + "'" : '' 246 | }.` 247 | ); 248 | } 249 | return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || 'Select main class'); 250 | } 251 | 252 | async function fixMainClass( 253 | folder: Uri | null, 254 | config: DebugConfiguration, 255 | validationResponse: lsPlugin.ILaunchValidationResponse 256 | ): Promise { 257 | const errors: string[] = []; 258 | if (!validationResponse.mainClass.isValid) { 259 | errors.push(String(validationResponse.mainClass.message)); 260 | } 261 | 262 | if (!validationResponse.projectName.isValid) { 263 | errors.push(String(validationResponse.projectName.message)); 264 | } 265 | 266 | if (validationResponse.proposals && validationResponse.proposals.length) { 267 | window.showErrorMessage(errors.join(os.EOL)); 268 | const selectedFix = await mainClassPicker.showQuickPick( 269 | validationResponse.proposals, 270 | 'Please select main class.', 271 | false 272 | ); 273 | if (selectedFix) { 274 | await persistMainClassOption(folder, config, selectedFix); 275 | } 276 | return selectedFix; 277 | } 278 | } 279 | 280 | async function persistMainClassOption( 281 | folder: Uri | null, 282 | oldConfig: DebugConfiguration, 283 | change: lsPlugin.IMainClassOption 284 | ): Promise { 285 | const newConfig: DebugConfiguration = _.cloneDeep(oldConfig); 286 | newConfig.mainClass = change.mainClass; 287 | newConfig.projectName = change.projectName; 288 | 289 | return persistLaunchConfig(folder, oldConfig, newConfig); 290 | } 291 | 292 | async function persistLaunchConfig( 293 | folder: Uri | null, 294 | oldConfig: DebugConfiguration, 295 | newConfig: DebugConfiguration 296 | ): Promise { 297 | const launchConfigurations: WorkspaceConfiguration = workspace.getConfiguration('launch', folder?.toString()); 298 | const rawConfigs: DebugConfiguration[] = launchConfigurations.configurations; 299 | const targetIndex: number = _.findIndex(rawConfigs, (config) => _.isEqual(config, oldConfig)); 300 | if (targetIndex >= 0) { 301 | window.showMessage("--update") 302 | rawConfigs[targetIndex] = newConfig; 303 | launchConfigurations.update('configurations', rawConfigs); 304 | } else { 305 | window.showMessage("--update 2") 306 | launchConfigurations.update('configurations', newConfig); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /src/debugCodeLensProvider.ts: -------------------------------------------------------------------------------- 1 | import {commands, Uri, window, workspace as Workspace, WorkspaceFolder} from 'coc.nvim'; 2 | import _ from 'lodash'; 3 | import path from 'path'; 4 | import {isOnClasspath} from './languageServerPlugin'; 5 | import * as vimspector from './vimspectorPlugin'; 6 | import fs from 'fs'; 7 | 8 | export async function startDebugging( 9 | mainClass: string, 10 | projectName: string | undefined, 11 | uri: Uri, 12 | _noDebug: boolean 13 | ): Promise { 14 | const workspaceFolder: WorkspaceFolder | null = Workspace.getWorkspaceFolder(uri.toString()); 15 | const workspaceUri = workspaceFolder ? Uri.parse(workspaceFolder.uri) : undefined; 16 | const onClasspath = await isOnClasspath(uri.toString()); 17 | if (workspaceUri && onClasspath === false && !(await addToClasspath(uri))) { 18 | return false; 19 | } 20 | 21 | const debugConfig: DebugConfiguration = await constructDebugConfig(mainClass, projectName, workspaceUri); 22 | debugConfig.projectName = projectName; 23 | // debugConfig.noDebug = noDebug; 24 | // debugConfig.__progressId = progressReporter?.getId(); 25 | 26 | return vimspector.startVimspector(workspaceFolder, debugConfig); 27 | } 28 | 29 | async function addToClasspath(uri: Uri): Promise { 30 | const fileName = path.basename(uri.fsPath || ''); 31 | const parentFsPath = path.dirname(uri.fsPath || ''); 32 | if (!parentFsPath) { 33 | return true; 34 | } 35 | 36 | const parentUri = Uri.file(parentFsPath); 37 | console.log(parentUri.toString()); 38 | let parentPath = parentUri.path; 39 | if (parentPath === parentUri.fsPath) { 40 | parentPath = path.basename(parentFsPath); 41 | } 42 | const message = 43 | `The file ${fileName} isn't on the classpath, the runtime may throw class not found error. ` + 44 | `Do you want to add the parent folder "${parentPath}" to Java source path?`; 45 | const ans = await window.showWarningMessage(message); 46 | if (!ans) { 47 | return true; 48 | } else { 49 | commands.executeCommand('java.project.addToSourcePath', parentUri); 50 | } 51 | 52 | return false; 53 | } 54 | 55 | /** 56 | * Configuration for a debug session. 57 | */ 58 | export interface DebugConfiguration { 59 | /** 60 | * The type of the debug session. 61 | */ 62 | type: string; 63 | 64 | /** 65 | * The name of the debug session. 66 | */ 67 | name: string; 68 | 69 | /** 70 | * The request type of the debug session. 71 | */ 72 | request: string; 73 | 74 | /** 75 | * Additional debug type specific properties. 76 | */ 77 | [key: string]: any; 78 | } 79 | 80 | /** 81 | * The configuration target 82 | */ 83 | export enum ConfigurationTarget { 84 | /** 85 | * Global configuration 86 | */ 87 | Global = 1, 88 | 89 | /** 90 | * Workspace configuration 91 | */ 92 | Workspace = 2, 93 | 94 | /** 95 | * Workspace folder configuration 96 | */ 97 | WorkspaceFolder = 3, 98 | } 99 | 100 | async function constructDebugConfig( 101 | mainClass: string, 102 | projectName: string | undefined, 103 | workspace: Uri | undefined 104 | ): Promise { 105 | const launchConfigurations = Workspace.getConfiguration('launch', workspace?.toString()); 106 | const rawConfigs: DebugConfiguration[] = launchConfigurations.configurations; 107 | 108 | let debugConfig: DebugConfiguration | undefined = _.find(rawConfigs, (config) => { 109 | return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName); 110 | }); 111 | 112 | if (!debugConfig) { 113 | debugConfig = _.find(rawConfigs, (config) => { 114 | return config.mainClass === mainClass && !config.projectName; 115 | }); 116 | } 117 | 118 | if (!debugConfig) { 119 | debugConfig = { 120 | type: 'java', 121 | name: `CodeLens (Launch) - ${mainClass.substr(mainClass.lastIndexOf('.') + 1)}`, 122 | request: 'launch', 123 | console: 'externalTerminal', 124 | mainClass, 125 | projectName, 126 | }; 127 | 128 | // Persist the configuration into launch.json only if the launch.json file already exists in the workspace. 129 | window.showMessage("first: " + (rawConfigs && rawConfigs.length)) 130 | window.showMessage("second: " + await launchJsonExists(workspace)) 131 | if ((rawConfigs && rawConfigs.length) || (await launchJsonExists(workspace))) { 132 | try { 133 | // Insert the default debug configuration to the beginning of launch.json. 134 | const rawConfigsCopy = _.cloneDeep(rawConfigs); 135 | rawConfigsCopy.splice(0, 0, debugConfig); 136 | launchConfigurations.update('configurations', rawConfigsCopy); 137 | window.showMessage("workspace root: " + Workspace.root) 138 | fs.writeFileSync(Workspace.root + '/.vimspector.json', buildVimspectorConfig(rawConfigsCopy)); 139 | } catch (error) { 140 | window.showErrorMessage(error); 141 | // When launch.json has unsaved changes before invoking the update api, it will throw the error below: 142 | // 'Unable to write into launch configuration file because the file is dirty. Please save it first and then try again.' 143 | // It's safe to ignore it because the only impact is the configuration is not saved, but you can continue to start the debugger. 144 | } 145 | } 146 | } 147 | 148 | return _.cloneDeep(debugConfig); 149 | } 150 | 151 | function buildVimspectorConfig(rawConfigs: DebugConfiguration[]): string { 152 | let vimspectorJson = {}; 153 | let configurations = {}; 154 | rawConfigs.forEach(config => { 155 | configurations[config.name] = { 156 | "adapter": "vscode-java", 157 | "default": true, 158 | "breakpoints": { 159 | "exception": { 160 | "caught": "N", 161 | "uncaught": "N" 162 | } 163 | }, 164 | "configuration": { 165 | "classPaths": ["*${classPathString}"], 166 | ...config 167 | } 168 | }; 169 | }) 170 | vimspectorJson["configurations"] = configurations; 171 | return JSON.stringify(vimspectorJson, null, '\t'); 172 | } 173 | 174 | async function launchJsonExists(workspace: Uri | undefined): Promise { 175 | if (!workspace) { 176 | return false; 177 | } 178 | 179 | const workspaceFolder = Workspace.getWorkspaceFolder(workspace.toString()); 180 | const result: string = path.resolve(Workspace.root, '.vimspector.json'); 181 | return Workspace.getWorkspaceFolder(result) === workspaceFolder; 182 | } 183 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | commands, 3 | ExtensionContext, 4 | listManager, 5 | Uri, 6 | window, 7 | workspace, 8 | WorkspaceConfiguration, 9 | WorkspaceFolder 10 | } from 'coc.nvim'; 11 | import _ from 'lodash'; 12 | import * as path from 'path'; 13 | import {DebugConfiguration, startDebugging} from './debugCodeLensProvider'; 14 | import {IMainClassOption, resolveMainMethod} from './languageServerPlugin'; 15 | import DemoList from './lists'; 16 | import * as utility from './utility'; 17 | import * as vimspector from './vimspectorPlugin'; 18 | 19 | export async function activate(context: ExtensionContext): Promise { 20 | window.showMessage(`coc-java-vimspector works!`); 21 | 22 | context.subscriptions.push( 23 | commands.registerCommand('java.debug.debugJavaFile', async (uri: string) => { 24 | await runJavaFile(uri, false); 25 | }) 26 | ); 27 | context.subscriptions.push( 28 | commands.registerCommand('java.debug.debugFromProjectView', async (node: any) => { 29 | await runJavaProject(node, false); 30 | }) 31 | ); 32 | 33 | context.subscriptions.push( 34 | listManager.registerList(new DemoList(workspace.nvim)), 35 | 36 | workspace.registerKeymap( 37 | ['n'], 38 | 'java-vimspector-keymap', 39 | async () => { 40 | window.showMessage(`registerKeymap`); 41 | }, 42 | {sync: false} 43 | ) 44 | ); 45 | } 46 | 47 | export async function runJavaFile(uri: string, noDebug: boolean) { 48 | // TODO: check extentions is activated 49 | // check current file is java file 50 | let currentFile = await workspace.nvim.eval('expand("%:p")'); 51 | if (!uri && _.endsWith(path.basename(currentFile.toString()), '.java')) { 52 | uri = currentFile.toString(); 53 | } 54 | console.info('uri : ' + uri); 55 | 56 | if (!uri) { 57 | window.showErrorMessage(`${noDebug ? 'Run' : 'Debug'} failed. Please open a Java file with main method first.`); 58 | } 59 | const mainClasses: IMainClassOption[] = await resolveMainMethod(Uri.file(uri)); 60 | const placeHolder = `The file '${path.basename(uri)}' is not executable, please select a main class you want to run.`; 61 | await launchMain(mainClasses, Uri.parse(uri), noDebug, placeHolder); 62 | } 63 | 64 | async function runJavaProject(node: any, noDebug: boolean) { 65 | if (!node || !node.name || !node.uri) { 66 | window.showErrorMessage( 67 | `Failed to ${noDebug ? 'run' : 'debug'} the project because of invalid project node. ` + 68 | 'This command only applies to Project Explorer view.' 69 | ); 70 | return; 71 | } 72 | 73 | window.showMessage('Resolving main class...'); 74 | const mainClassesOptions: IMainClassOption[] = await utility.searchMainMethods(Uri.parse(node.uri)); 75 | 76 | if (!mainClassesOptions || !mainClassesOptions.length) { 77 | window.showErrorMessage( 78 | `Failed to ${noDebug ? 'run' : 'debug'} this project '${node._nodeData.displayName || node.name}' ` + 79 | 'because it does not contain any main class.' 80 | ); 81 | return; 82 | } 83 | 84 | const classes: string[] = []; 85 | for (let index = 0; index < mainClassesOptions.length; index++) { 86 | classes.push(mainClassesOptions[index].mainClass); 87 | } 88 | const pick = await window.showQuickpick(classes, 'Select the main class to run.'); 89 | if (!pick || pick === -1) { 90 | return; 91 | } 92 | 93 | window.showMessage('Launching main class...'); 94 | const projectName: string | undefined = mainClassesOptions[pick].projectName; 95 | const mainClass: string = mainClassesOptions[pick].mainClass; 96 | const filePath: string | undefined = mainClassesOptions[pick].filePath; 97 | const workspaceFolder: WorkspaceFolder | null = filePath ? workspace.workspaceFolder : null; 98 | const launchConfigurations: WorkspaceConfiguration = workspace.getConfiguration('launch', workspaceFolder?.uri); 99 | const existingConfigs: DebugConfiguration[] = launchConfigurations.configurations; 100 | const existConfig: DebugConfiguration | undefined = _.find(existingConfigs, (config) => { 101 | return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName); 102 | }); 103 | const debugConfig = existConfig || { 104 | type: 'java', 105 | name: `Launch ${mainClass.substr(mainClass.lastIndexOf('.') + 1)}`, 106 | request: 'launch', 107 | mainClass, 108 | projectName, 109 | }; 110 | debugConfig.noDebug = noDebug; 111 | // debugConfig.__progressId = progressReporter.getId(); 112 | vimspector.startVimspector(workspaceFolder, debugConfig); 113 | } 114 | 115 | async function launchMain( 116 | mainMethods: IMainClassOption[], 117 | uri: Uri, 118 | noDebug: boolean, 119 | placeHolder: string 120 | ): Promise { 121 | if (!mainMethods || !mainMethods.length) { 122 | window.showMessage( 123 | 'Error: Main method not found in the file, please define the main method as: public static void main(String[] args)', 124 | 'error' 125 | ); 126 | return; 127 | } 128 | if (mainMethods.length === 1) { 129 | startDebugging(mainMethods[0].mainClass, mainMethods[0].projectName || '', uri, noDebug); 130 | return; 131 | } 132 | 133 | const pickList: string[] = []; 134 | mainMethods.forEach((value) => { 135 | pickList.push(value.mainClass); 136 | }); 137 | window.showQuickpick(pickList, placeHolder).then((idx) => { 138 | if (idx == -1) { 139 | return; 140 | } 141 | window.showMessage('Launching main class...'); 142 | startDebugging(mainMethods[idx].mainClass, mainMethods[idx].projectName || '', uri, noDebug); 143 | }); 144 | } 145 | -------------------------------------------------------------------------------- /src/languageServerPlugin.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | import {CancellationToken, Range, Uri} from 'coc.nvim'; 5 | import * as commands from './commands'; 6 | import {DebugConfiguration} from './debugCodeLensProvider'; 7 | 8 | export enum CompileWorkspaceStatus { 9 | FAILED = 0, 10 | SUCCEED = 1, 11 | WITHERROR = 2, 12 | CANCELLED = 3, 13 | } 14 | 15 | export interface IMainMethod extends IMainClassOption { 16 | range: Range; 17 | } 18 | 19 | export interface IMainClassOption { 20 | readonly mainClass: string; 21 | readonly projectName?: string; 22 | readonly filePath?: string; 23 | } 24 | 25 | export interface IValidationResult { 26 | readonly isValid: boolean; 27 | readonly message?: string; 28 | } 29 | 30 | export interface ILaunchValidationResponse { 31 | readonly mainClass: IValidationResult; 32 | readonly projectName: IValidationResult; 33 | readonly proposals?: IMainClassOption[]; 34 | } 35 | 36 | export async function resolveMainMethod(uri: Uri, token?: CancellationToken): Promise { 37 | if (token) { 38 | return ( 39 | await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINMETHOD, uri.toString(), token) 40 | ); 41 | } 42 | 43 | return ( 44 | await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINMETHOD, uri.toString()) 45 | ); 46 | } 47 | 48 | export function startDebugSession() { 49 | return commands.executeJavaLanguageServerCommand(commands.JAVA_START_DEBUGSESSION); 50 | } 51 | 52 | export function resolveClasspath(mainClass: any, projectName: any) { 53 | return commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_CLASSPATH, mainClass, projectName); 54 | } 55 | 56 | export function resolveMainClass(workspaceUri?: Uri | null): Promise { 57 | if (workspaceUri) { 58 | return >( 59 | commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS, workspaceUri.toString()) 60 | ); 61 | } 62 | return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS); 63 | } 64 | 65 | export function validateLaunchConfig( 66 | mainClass: string, 67 | projectName: string, 68 | containsExternalClasspaths: boolean, 69 | workspaceUri?: Uri | null 70 | ): Promise { 71 | return >( 72 | commands.executeJavaLanguageServerCommand( 73 | commands.JAVA_VALIDATE_LAUNCHCONFIG, 74 | workspaceUri ? workspaceUri.toString() : undefined, 75 | mainClass, 76 | projectName, 77 | containsExternalClasspaths 78 | ) 79 | ); 80 | } 81 | 82 | export function inferLaunchCommandLength(config: DebugConfiguration): Promise { 83 | return >( 84 | commands.executeJavaLanguageServerCommand(commands.JAVA_INFER_LAUNCH_COMMAND_LENGTH, JSON.stringify(config)) 85 | ); 86 | } 87 | 88 | export function checkProjectSettings( 89 | className: string, 90 | projectName: string, 91 | inheritedOptions: boolean, 92 | expectedOptions: {[key: string]: string} 93 | ): Promise { 94 | return >commands.executeJavaLanguageServerCommand( 95 | commands.JAVA_CHECK_PROJECT_SETTINGS, 96 | JSON.stringify({ 97 | className, 98 | projectName, 99 | inheritedOptions, 100 | expectedOptions, 101 | }) 102 | ); 103 | } 104 | 105 | const COMPILER_PB_ENABLE_PREVIEW_FEATURES = 'org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures'; 106 | export async function detectPreviewFlag(className: string, projectName: string): Promise { 107 | const expectedOptions = { 108 | [COMPILER_PB_ENABLE_PREVIEW_FEATURES]: 'enabled', 109 | }; 110 | return checkProjectSettings(className, projectName, true, expectedOptions); 111 | } 112 | 113 | export function resolveElementAtSelection(uri: string, line: number, character: number): Promise { 114 | return >( 115 | commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_ELEMENT_AT_SELECTION, uri, line, character) 116 | ); 117 | } 118 | 119 | export function resolveBuildFiles(): Promise { 120 | return >commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_BUILD_FILES); 121 | } 122 | 123 | export async function isOnClasspath(uri: string): Promise { 124 | try { 125 | return await commands.executeJavaExtensionCommand(commands.JAVA_IS_ON_CLASSPATH, uri); 126 | } catch (error) { 127 | return true; 128 | } 129 | } 130 | 131 | export function resolveJavaExecutable(mainClass: any, projectName: any) { 132 | return commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_JAVAEXECUTABLE, mainClass, projectName); 133 | } 134 | 135 | export function fetchPlatformSettings(): any { 136 | return commands.executeJavaLanguageServerCommand(commands.JAVA_FETCH_PLATFORM_SETTINGS); 137 | } 138 | 139 | export async function resolveClassFilters(patterns: string[]): Promise { 140 | return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_CLASSFILTERS, ...patterns); 141 | } 142 | 143 | export async function resolveSourceUri(line: string): Promise { 144 | return await commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_SOURCE_URI, line); 145 | } 146 | -------------------------------------------------------------------------------- /src/launchCommand.ts: -------------------------------------------------------------------------------- 1 | import * as cp from 'child_process'; 2 | import {window} from 'coc.nvim'; 3 | import * as fs from 'fs'; 4 | import _ from 'lodash'; 5 | import * as path from 'path'; 6 | import {DebugConfiguration} from './debugCodeLensProvider'; 7 | 8 | import {fetchPlatformSettings, inferLaunchCommandLength} from './languageServerPlugin'; 9 | import {getJavaHome} from './utility'; 10 | 11 | enum shortenApproach { 12 | none = 'none', 13 | jarmanifest = 'jarmanifest', 14 | argfile = 'argfile', 15 | } 16 | 17 | const HELPFUL_NPE_VMARGS = '-XX:+ShowCodeDetailsInExceptionMessages'; 18 | 19 | /** 20 | * Returns the recommended approach to shorten the command line length. 21 | * @param config the launch configuration 22 | * @param runtimeVersion the target runtime version 23 | */ 24 | export async function getShortenApproachForCLI( 25 | config: DebugConfiguration, 26 | runtimeVersion: number 27 | ): Promise { 28 | const recommendedShortenApproach = runtimeVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile; 29 | return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none; 30 | } 31 | 32 | /** 33 | * Validates whether the specified runtime version could be supported by the Java tooling. 34 | * @param runtimeVersion the target runtime version 35 | */ 36 | export async function validateRuntimeCompatibility(runtimeVersion: number) { 37 | try { 38 | const platformSettings = await fetchPlatformSettings(); 39 | if (platformSettings && platformSettings.latestSupportedJavaVersion) { 40 | const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion); 41 | if (latestSupportedVersion < runtimeVersion) { 42 | window.showWarningMessage( 43 | 'The compiled classes are not compatible with the runtime JDK. To mitigate the issue, please refer to "Learn More".' 44 | ); 45 | } 46 | } 47 | } catch (err) { 48 | // do nothing 49 | } 50 | } 51 | 52 | /** 53 | * Add some helpful VM arguments to the launch configuration based on the target runtime version. 54 | * @param config the launch configuration 55 | * @param runtimeVersion the target runtime version 56 | */ 57 | export async function addMoreHelpfulVMArgs(config: DebugConfiguration, runtimeVersion: number) { 58 | try { 59 | if (runtimeVersion >= 14) { 60 | // JEP-358: https://openjdk.java.net/jeps/358 61 | if (config.vmArgs && config.vmArgs.indexOf(HELPFUL_NPE_VMARGS) >= 0) { 62 | return; 63 | } 64 | 65 | config.vmArgs = (config.vmArgs || '') + ' ' + HELPFUL_NPE_VMARGS; 66 | } 67 | } catch (error) { 68 | // do nothing. 69 | } 70 | } 71 | 72 | /** 73 | * Returns the target runtime version. If the javaExec is not specified, then return the current Java version 74 | * that the Java tooling used. 75 | * @param javaExec the path of the Java executable 76 | */ 77 | export async function getJavaVersion(javaExec: string): Promise { 78 | javaExec = javaExec || path.join(await getJavaHome(), 'bin', 'java'); 79 | let javaVersion = await checkVersionInReleaseFile(path.resolve(javaExec, '..', '..')); 80 | if (!javaVersion) { 81 | javaVersion = await checkVersionByCLI(javaExec); 82 | } 83 | return javaVersion; 84 | } 85 | 86 | async function checkVersionInReleaseFile(javaHome: string): Promise { 87 | if (!javaHome) { 88 | return 0; 89 | } 90 | const releaseFile = path.join(javaHome, 'release'); 91 | if (!fs.existsSync(releaseFile)) { 92 | return 0; 93 | } 94 | 95 | try { 96 | const content = fs.readFileSync(releaseFile); 97 | const regexp = /^JAVA_VERSION="(.*)"/gm; 98 | const match = regexp.exec(content.toString()); 99 | if (!match) { 100 | return 0; 101 | } 102 | const majorVersion = flattenMajorVersion(match[1]); 103 | return majorVersion; 104 | } catch (error) { 105 | // ignore 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | /** 112 | * Get version by parsing `JAVA_HOME/bin/java -version` 113 | */ 114 | async function checkVersionByCLI(javaExec: string): Promise { 115 | if (!javaExec) { 116 | return 0; 117 | } 118 | return new Promise((resolve) => { 119 | cp.execFile(javaExec, ['-version'], {}, (_error, _stdout, stderr) => { 120 | const regexp = /version "(.*)"/g; 121 | const match = regexp.exec(stderr); 122 | if (!match) { 123 | return resolve(0); 124 | } 125 | const javaVersion = flattenMajorVersion(match[1]); 126 | resolve(javaVersion); 127 | }); 128 | }); 129 | } 130 | 131 | function flattenMajorVersion(version: string): number { 132 | // Ignore '1.' prefix for legacy Java versions 133 | if (version.startsWith('1.')) { 134 | version = version.substring(2); 135 | } 136 | 137 | // look into the interesting bits now 138 | const regexp = /\d+/g; 139 | const match = regexp.exec(version); 140 | let javaVersion = 0; 141 | if (match) { 142 | javaVersion = parseInt(match[0], 10); 143 | } 144 | 145 | return javaVersion; 146 | } 147 | 148 | async function shouldShortenIfNecessary(config: DebugConfiguration): Promise { 149 | const cliLength = await inferLaunchCommandLength(config); 150 | const classPaths = config.classPaths || []; 151 | const modulePaths = config.modulePaths || []; 152 | const classPathLength = classPaths.join(path.delimiter).length; 153 | const modulePathLength = modulePaths.join(path.delimiter).length; 154 | if (!config.console || config.console === 'internalConsole') { 155 | return ( 156 | cliLength >= getMaxProcessCommandLineLength(config) || 157 | classPathLength >= getMaxArgLength() || 158 | modulePathLength >= getMaxArgLength() 159 | ); 160 | } else { 161 | return classPaths.length > 1 || modulePaths.length > 1; 162 | } 163 | } 164 | 165 | function getMaxProcessCommandLineLength(config: DebugConfiguration): number { 166 | const ARG_MAX_WINDOWS = 32768; 167 | const ARG_MAX_MACOS = 262144; 168 | const ARG_MAX_LINUX = 2097152; 169 | // for Posix systems, ARG_MAX is the maximum length of argument to the exec functions including environment data. 170 | // POSIX suggests to subtract 2048 additionally so that the process may safely modify its environment. 171 | // see https://www.in-ulm.de/~mascheck/various/argmax/ 172 | if (process.platform === 'win32') { 173 | // https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553/ 174 | // On windows, the max process commmand line length is 32k (32768) characters. 175 | return ARG_MAX_WINDOWS - 2048; 176 | } else if (process.platform === 'darwin') { 177 | return ARG_MAX_MACOS - getEnvironmentLength(config) - 2048; 178 | } else if (process.platform === 'linux') { 179 | return ARG_MAX_LINUX - getEnvironmentLength(config) - 2048; 180 | } 181 | 182 | return Number.MAX_SAFE_INTEGER; 183 | } 184 | 185 | function getEnvironmentLength(config: DebugConfiguration): number { 186 | const env = config.env || {}; 187 | return _.isEmpty(env) 188 | ? 0 189 | : Object.keys(env) 190 | .map((key) => strlen(key) + strlen(env[key]) + 1) 191 | .reduce((a, b) => a + b); 192 | } 193 | 194 | function strlen(str: string): number { 195 | return str ? str.length : 0; 196 | } 197 | 198 | function getMaxArgLength(): number { 199 | const MAX_ARG_STRLEN_LINUX = 131072; 200 | if (process.platform === 'linux') { 201 | // On Linux, MAX_ARG_STRLEN (kernel >= 2.6.23) is the maximum length of a command line argument (or environment variable). Its value 202 | // cannot be changed without recompiling the kernel. 203 | return MAX_ARG_STRLEN_LINUX - 2048; 204 | } 205 | 206 | return Number.MAX_SAFE_INTEGER; 207 | } 208 | -------------------------------------------------------------------------------- /src/lists.ts: -------------------------------------------------------------------------------- 1 | import {BasicList, ListAction, ListItem, Neovim} from 'coc.nvim'; 2 | import {runJavaFile} from '.'; 3 | import {IMainClassOption} from './languageServerPlugin'; 4 | import {searchMainMethods} from './utility'; 5 | 6 | export default class DemoList extends BasicList { 7 | public readonly name = 'mainClassListRun'; 8 | public readonly description = 'CocList for coc-java-vimspector'; 9 | public readonly defaultAction = 'run'; 10 | public actions: ListAction[] = []; 11 | 12 | constructor(nvim: Neovim) { 13 | super(nvim); 14 | 15 | this.addAction('run', (item: ListItem) => { 16 | runJavaFile(item.location, true); 17 | }); 18 | } 19 | 20 | public async loadItems(): Promise { 21 | const mainClasses: IMainClassOption[] = await searchMainMethods(); 22 | const result: Array = []; 23 | mainClasses.forEach((value) => { 24 | result.push({ 25 | label: `${value.mainClass} : ${value.filePath}`, 26 | location: value.filePath, 27 | }); 28 | }); 29 | return result; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/mainClassPicker.ts: -------------------------------------------------------------------------------- 1 | import {window} from 'coc.nvim'; 2 | import * as path from 'path'; 3 | import {IMainClassOption} from './languageServerPlugin'; 4 | 5 | const defaultLabelFormatter = (option: IMainClassOption) => { 6 | return option.mainClass; 7 | }; 8 | type Formatter = (option: IMainClassOption) => string; 9 | 10 | class MainClassPicker { 11 | private cache: {[key: string]: number} = {}; 12 | 13 | // tslint:disable-next-line 14 | public async showQuickPick(options: IMainClassOption[], placeHolder: string): Promise; 15 | // tslint:disable-next-line 16 | public async showQuickPick( 17 | options: IMainClassOption[], 18 | placeHolder: string, 19 | labelFormatter: Formatter 20 | ): Promise; 21 | // tslint:disable-next-line 22 | public async showQuickPick( 23 | options: IMainClassOption[], 24 | placeHolder: string, 25 | autoPick: boolean 26 | ): Promise; 27 | // tslint:disable-next-line 28 | public async showQuickPick( 29 | options: IMainClassOption[], 30 | placeHolder: string, 31 | parameter3?: Formatter | boolean, 32 | parameter4?: boolean 33 | ): Promise { 34 | let labelFormatter: Formatter = defaultLabelFormatter; 35 | let autoPick = true; 36 | if (typeof parameter3 === 'function') { 37 | labelFormatter = parameter3; 38 | } else if (typeof parameter3 === 'boolean') { 39 | autoPick = parameter3; 40 | } 41 | if (typeof parameter4 === 'boolean') { 42 | autoPick = parameter4; 43 | } 44 | 45 | if (!options || !options.length) { 46 | return undefined; 47 | } else if (autoPick && options.length === 1) { 48 | return options[0]; 49 | } 50 | 51 | const pickItems = options.map((option) => { 52 | return { 53 | label: labelFormatter(option), 54 | description: option.filePath ? path.basename(option.filePath) : '', 55 | detail: option.projectName ? `Project: ${option.projectName}` : '', 56 | data: option, 57 | }; 58 | }); 59 | const pickItemsString: string[] = []; 60 | pickItems.forEach((value) => pickItemsString.push(value.detail)); 61 | 62 | const selected = await window.showQuickpick(pickItemsString, placeHolder); 63 | if (selected) { 64 | return pickItems[selected].data; 65 | } 66 | return undefined; 67 | } 68 | 69 | // tslint:disable-next-line 70 | public async showQuickPickWithRecentlyUsed( 71 | options: IMainClassOption[], 72 | placeHolder: string 73 | ): Promise; 74 | // tslint:disable-next-line 75 | public async showQuickPickWithRecentlyUsed( 76 | options: IMainClassOption[], 77 | placeHolder: string, 78 | labelFormatter: Formatter 79 | ): Promise; 80 | // tslint:disable-next-line 81 | public async showQuickPickWithRecentlyUsed( 82 | options: IMainClassOption[], 83 | placeHolder: string, 84 | autoPick: boolean 85 | ): Promise; 86 | // tslint:disable-next-line 87 | public async showQuickPickWithRecentlyUsed( 88 | options: IMainClassOption[], 89 | placeHolder: string, 90 | parameter3?: Formatter | boolean, 91 | parameter4?: boolean 92 | ): Promise { 93 | // Record the main class picking history in a most recently used cache. 94 | let labelFormatter: Formatter = defaultLabelFormatter; 95 | let autoPick = true; 96 | if (typeof parameter3 === 'function') { 97 | labelFormatter = parameter3; 98 | } else if (typeof parameter3 === 'boolean') { 99 | autoPick = parameter3; 100 | } 101 | if (typeof parameter4 === 'boolean') { 102 | autoPick = parameter4; 103 | } 104 | 105 | if (!options || !options.length) { 106 | return undefined; 107 | } else if (autoPick && options.length === 1) { 108 | return options[0]; 109 | } 110 | 111 | // Sort the Main Class options with the recently used timestamp. 112 | options.sort((a: IMainClassOption, b: IMainClassOption) => { 113 | return this.getMRUTimestamp(b) - this.getMRUTimestamp(a); 114 | }); 115 | 116 | const mostRecentlyUsedOption: IMainClassOption | undefined = 117 | options.length && this.contains(options[0]) ? options[0] : undefined; 118 | const isMostRecentlyUsed = (option: IMainClassOption): boolean => { 119 | return ( 120 | !!mostRecentlyUsedOption && 121 | mostRecentlyUsedOption.mainClass === option.mainClass && 122 | mostRecentlyUsedOption.projectName === option.projectName 123 | ); 124 | }; 125 | const isPrivileged = (option: IMainClassOption): boolean => { 126 | return isMostRecentlyUsed(option); 127 | }; 128 | 129 | // Show the most recently used Main Class as the first one, 130 | // then the Main Class from Active Editor as second, 131 | // finally other Main Class. 132 | const adjustedOptions: IMainClassOption[] = []; 133 | options.forEach((option: IMainClassOption) => { 134 | if (isPrivileged(option)) { 135 | adjustedOptions.push(option); 136 | } 137 | }); 138 | options.forEach((option: IMainClassOption) => { 139 | if (!isPrivileged(option)) { 140 | adjustedOptions.push(option); 141 | } 142 | }); 143 | 144 | const pickItems = adjustedOptions.map((option) => { 145 | const adjustedDetail = []; 146 | const detail: string = adjustedDetail.join(', '); 147 | 148 | return { 149 | label: labelFormatter ? labelFormatter(option) : defaultLabelFormatter(option), 150 | description: option.filePath ? path.basename(option.filePath) : '', 151 | detail, 152 | data: option, 153 | }; 154 | }); 155 | const pickItemsString: string[] = []; 156 | pickItems.forEach((v) => pickItemsString.push(v.detail)); 157 | 158 | const selected = await window.showQuickpick(pickItemsString, placeHolder); 159 | if (selected) { 160 | this.updateMRUTimestamp(pickItems[selected].data); 161 | return pickItems[selected].data; 162 | } 163 | return undefined; 164 | } 165 | 166 | /** 167 | * Checks whether the item options can be picked automatically without popping up the QuickPick box. 168 | * @param options the item options to pick 169 | * @param autoPick pick it automatically if only one option is available 170 | */ 171 | public isAutoPicked(options: IMainClassOption[], autoPick?: boolean) { 172 | const shouldAutoPick: boolean = autoPick === undefined ? true : !!autoPick; 173 | if (!options || !options.length) { 174 | return true; 175 | } else if (shouldAutoPick && options.length === 1) { 176 | return true; 177 | } 178 | 179 | return false; 180 | } 181 | 182 | private getMRUTimestamp(mainClassOption: IMainClassOption): number { 183 | return this.cache[this.getKey(mainClassOption)] || 0; 184 | } 185 | 186 | private updateMRUTimestamp(mainClassOption: IMainClassOption): void { 187 | this.cache[this.getKey(mainClassOption)] = Date.now(); 188 | } 189 | 190 | private contains(mainClassOption: IMainClassOption): boolean { 191 | return Boolean(this.cache[this.getKey(mainClassOption)]); 192 | } 193 | 194 | private getKey(mainClassOption: IMainClassOption): string { 195 | return mainClassOption.mainClass + '|' + mainClassOption.projectName; 196 | } 197 | } 198 | 199 | export const mainClassPicker: MainClassPicker = new MainClassPicker(); 200 | -------------------------------------------------------------------------------- /src/processPicker.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import {window} from 'coc.nvim'; 3 | import {getProcesses, getProcessTree} from './processTree'; 4 | 5 | const JAVA_PATTERN = /(?:java|javaw|j9|j9w)$/i; 6 | const DEBUG_MODE_PATTERN = /(-agentlib|-Xrunjdwp):\S*(address=[^\s,]+)/i; 7 | 8 | interface IJavaProcess { 9 | pid: number; 10 | command: string; 11 | args: string; 12 | hostName: string; 13 | debugPort: number; 14 | } 15 | 16 | function convertToJavaProcess(pid: number, command: string, args: string): IJavaProcess | undefined { 17 | if (process.platform === 'win32' && command.indexOf('\\??\\') === 0) { 18 | // remove leading device specifier 19 | command = command.replace('\\??\\', ''); 20 | } 21 | 22 | const simpleName = path.basename(command, '.exe'); 23 | if (JAVA_PATTERN.test(simpleName) && args) { 24 | const match = args.match(DEBUG_MODE_PATTERN); 25 | if (match && match.length) { 26 | const address = match[2].split('=')[1].split(':'); 27 | const hostName = address.length > 1 ? address[0] : '127.0.0.1'; 28 | const debugPort = parseInt(address[address.length - 1], 10); 29 | const exeName = path.basename(command); 30 | const binPath = path.dirname(command); 31 | const commandPath = 32 | path.basename(binPath) === 'bin' ? path.join(path.basename(path.dirname(binPath)), 'bin', exeName) : exeName; 33 | return { 34 | pid, 35 | command: commandPath, 36 | args, 37 | hostName, 38 | debugPort, 39 | }; 40 | } 41 | } 42 | 43 | return undefined; 44 | } 45 | 46 | export async function pickJavaProcess(): Promise { 47 | const javaProcesses: IJavaProcess[] = []; 48 | try { 49 | await getProcesses((pid: number, _ppid: number, command: string, args: string) => { 50 | const javaProcess = convertToJavaProcess(pid, command, args); 51 | if (javaProcess) { 52 | javaProcesses.push(javaProcess); 53 | } 54 | }); 55 | } catch (error) { 56 | throw new Error('Process picker failed: ' + error); 57 | } 58 | 59 | if (!javaProcesses.length) { 60 | throw new Error( 61 | 'Process picker: Cannot find any debuggable Java process. Please make sure to use vmArgs like ' + 62 | "'-agentlib:jdwp=transport=dt_socket,server=y,address=5005' to turn on debug mode when you start your " + 63 | 'program.' 64 | ); 65 | } 66 | 67 | const items = javaProcesses.map((process) => { 68 | return { 69 | label: process.command, 70 | description: process.args, 71 | detail: `process id: ${process.pid}, debug port: ${process.debugPort}`, 72 | process, 73 | }; 74 | }); 75 | const itemsString: string[] = []; 76 | items.forEach((value) => itemsString.push(value.detail)); 77 | 78 | const pick = await window.showQuickpick(itemsString, 'Pick Java process to attach to'); 79 | 80 | if (pick) { 81 | return items[pick].process; 82 | } 83 | 84 | return undefined; 85 | } 86 | 87 | export async function resolveJavaProcess(pid: number): Promise { 88 | const processTree = await getProcessTree(pid); 89 | if (!processTree || processTree.pid !== pid) { 90 | return undefined; 91 | } 92 | 93 | return convertToJavaProcess(processTree.pid, processTree.command, processTree.args); 94 | } 95 | -------------------------------------------------------------------------------- /src/processTree.ts: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | * 5 | * Copied from https://github.com/microsoft/vscode-node-debug/blob/master/src/node/extension/processTree.ts 6 | *--------------------------------------------------------------------------------------------*/ 7 | /* tslint:disable */ 8 | 'use strict'; 9 | 10 | import {spawn, ChildProcess} from 'child_process'; 11 | import {join} from 'path'; 12 | 13 | export class ProcessTreeNode { 14 | children?: ProcessTreeNode[]; 15 | 16 | constructor(public pid: number, public ppid: number, public command: string, public args: string) {} 17 | } 18 | 19 | export async function getProcessTree(rootPid: number): Promise { 20 | const map = new Map(); 21 | 22 | map.set(0, new ProcessTreeNode(0, 0, '???', '')); 23 | 24 | try { 25 | await getProcesses((pid: number, ppid: number, command: string, args: string) => { 26 | if (pid !== ppid) { 27 | map.set(pid, new ProcessTreeNode(pid, ppid, command, args)); 28 | } 29 | }); 30 | } catch (err) { 31 | return undefined; 32 | } 33 | 34 | const values = map.values(); 35 | for (const p of values) { 36 | const parent = map.get(p.ppid); 37 | if (parent && parent !== p) { 38 | if (!parent.children) { 39 | parent.children = []; 40 | } 41 | parent.children.push(p); 42 | } 43 | } 44 | 45 | if (!isNaN(rootPid) && rootPid > 0) { 46 | return map.get(rootPid); 47 | } 48 | return map.get(0); 49 | } 50 | 51 | export function getProcesses( 52 | one: (pid: number, ppid: number, command: string, args: string, date?: number) => void 53 | ): Promise { 54 | // returns a function that aggregates chunks of data until one or more complete lines are received and passes them to a callback. 55 | function lines(callback: (a: string) => void) { 56 | let unfinished = ''; // unfinished last line of chunk 57 | return (data: string | Buffer) => { 58 | const lines = data.toString().split(/\r?\n/); 59 | const finishedLines = lines.slice(0, lines.length - 1); 60 | finishedLines[0] = unfinished + finishedLines[0]; // complete previous unfinished line 61 | unfinished = lines[lines.length - 1]; // remember unfinished last line of this chunk for next round 62 | for (const s of finishedLines) { 63 | callback(s); 64 | } 65 | }; 66 | } 67 | 68 | return new Promise((resolve, reject) => { 69 | let proc: ChildProcess; 70 | 71 | if (process.platform === 'win32') { 72 | // attributes columns are in alphabetic order! 73 | const CMD_PAT = /^(.*)\s+([0-9]+)\.[0-9]+[+-][0-9]+\s+([0-9]+)\s+([0-9]+)$/; 74 | 75 | const wmic = join(process.env['WINDIR'] || 'C:\\Windows', 'System32', 'wbem', 'WMIC.exe'); 76 | proc = spawn(wmic, ['process', 'get', 'CommandLine,CreationDate,ParentProcessId,ProcessId']); 77 | proc.stdout?.setEncoding('utf8'); 78 | proc.stdout?.on( 79 | 'data', 80 | lines((line) => { 81 | const matches = CMD_PAT.exec(line.trim()); 82 | if (matches && matches.length === 5) { 83 | const pid = Number(matches[4]); 84 | const ppid = Number(matches[3]); 85 | const date = Number(matches[2]); 86 | let args = matches[1].trim(); 87 | if (!isNaN(pid) && !isNaN(ppid) && args) { 88 | let command = args; 89 | if (args[0] === '"') { 90 | const end = args.indexOf('"', 1); 91 | if (end > 0) { 92 | command = args.substr(1, end - 1); 93 | args = args.substr(end + 2); 94 | } 95 | } else { 96 | const end = args.indexOf(' '); 97 | if (end > 0) { 98 | command = args.substr(0, end); 99 | args = args.substr(end + 1); 100 | } else { 101 | args = ''; 102 | } 103 | } 104 | one(pid, ppid, command, args, date); 105 | } 106 | } 107 | }) 108 | ); 109 | } else if (process.platform === 'darwin') { 110 | // OS X 111 | 112 | proc = spawn('/bin/ps', ['-x', '-o', `pid,ppid,comm=${'a'.repeat(256)},command`]); 113 | proc.stdout?.setEncoding('utf8'); 114 | proc.stdout?.on( 115 | 'data', 116 | lines((line) => { 117 | const pid = Number(line.substr(0, 5)); 118 | const ppid = Number(line.substr(6, 5)); 119 | const command = line.substr(12, 256).trim(); 120 | const args = line.substr(269 + command.length); 121 | 122 | if (!isNaN(pid) && !isNaN(ppid)) { 123 | one(pid, ppid, command, args); 124 | } 125 | }) 126 | ); 127 | } else { 128 | // linux 129 | 130 | proc = spawn('/bin/ps', ['-ax', '-o', 'pid,ppid,comm:20,command']); 131 | proc.stdout?.setEncoding('utf8'); 132 | proc.stdout?.on( 133 | 'data', 134 | lines((line) => { 135 | const pid = Number(line.substr(0, 5)); 136 | const ppid = Number(line.substr(6, 5)); 137 | let command = line.substr(12, 20).trim(); 138 | let args = line.substr(33); 139 | 140 | let pos = args.indexOf(command); 141 | if (pos >= 0) { 142 | pos = pos + command.length; 143 | while (pos < args.length) { 144 | if (args[pos] === ' ') { 145 | break; 146 | } 147 | pos++; 148 | } 149 | command = args.substr(0, pos); 150 | args = args.substr(pos + 1); 151 | } 152 | 153 | if (!isNaN(pid) && !isNaN(ppid)) { 154 | one(pid, ppid, command, args); 155 | } 156 | }) 157 | ); 158 | } 159 | 160 | proc.on('error', (err) => { 161 | reject(err); 162 | }); 163 | 164 | proc.stderr?.setEncoding('utf8'); 165 | proc.stderr?.on('data', (data) => { 166 | const e = data.toString(); 167 | if (e.indexOf('screen size is bogus') >= 0) { 168 | // ignore this error silently; see https://github.com/microsoft/vscode/issues/75932 169 | } else { 170 | reject(new Error(data.toString())); 171 | } 172 | }); 173 | 174 | proc.on('close', (code, signal) => { 175 | if (code === 0) { 176 | resolve(); 177 | } else if (!code || code > 0) { 178 | reject(new Error(`process terminated with exit code: ${code}`)); 179 | } 180 | if (signal) { 181 | reject(new Error(`process terminated with signal: ${signal}`)); 182 | } 183 | }); 184 | 185 | proc.on('exit', (code, signal) => { 186 | if (typeof code === 'number') { 187 | if (code === 0) { 188 | //resolve(); 189 | } else if (code > 0) { 190 | reject(new Error(`process terminated with exit code: ${code}`)); 191 | } 192 | } 193 | if (signal) { 194 | reject(new Error(`process terminated with signal: ${signal}`)); 195 | } 196 | }); 197 | }); 198 | } 199 | -------------------------------------------------------------------------------- /src/utility.ts: -------------------------------------------------------------------------------- 1 | import {Extension, ExtensionApi, extensions, Thenable, Uri, window} from 'coc.nvim'; 2 | import {IMainClassOption, resolveMainClass} from './languageServerPlugin'; 3 | import * as path from 'path'; 4 | 5 | const JAVA_EXTENSION_ID = 'redhat.java'; 6 | const DEBUGGER_EXTENSION_ID = 'coc-java-vimspector'; 7 | 8 | export function getJavaExtension(): Extension | undefined { 9 | return extensions.all.find((value) => value.id === JAVA_EXTENSION_ID); 10 | } 11 | 12 | export async function searchMainMethods(uri?: Uri): Promise { 13 | try { 14 | window.showMessage('Searching main classes...'); 15 | return resolveMainClass(uri); 16 | } catch (ex) { 17 | window.showMessage(String((ex && ex.message) || ex), 'error'); 18 | throw ex; 19 | } 20 | } 21 | 22 | export function getLauncherScriptPath() { 23 | const ext = extensions.all.find((value) => { 24 | value.id === DEBUGGER_EXTENSION_ID; 25 | }); 26 | return path.join(ext!.extensionPath, 'scripts', 'launcher.bat'); 27 | } 28 | 29 | export async function getJavaHome(): Promise { 30 | const extensionApi = await getJavaExtensionAPI(); 31 | if (extensionApi && extensionApi.javaRequirement) { 32 | return extensionApi.javaRequirement.java_home; 33 | } 34 | 35 | return ''; 36 | } 37 | 38 | export function getJavaExtensionAPI(): Promise | undefined { 39 | const extension = extensions.all.find((value) => value.id === JAVA_EXTENSION_ID); 40 | if (!extension) { 41 | window.showErrorMessage('VS Code Java Extension is not enabled.'); 42 | } 43 | return new Promise(async (resolve) => { 44 | resolve(await extension?.activate()); 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /src/vimspectorPlugin.ts: -------------------------------------------------------------------------------- 1 | import {commands, window, workspace, WorkspaceFolder} from 'coc.nvim'; 2 | import * as Commands from './commands'; 3 | import {DebugConfiguration} from './debugCodeLensProvider'; 4 | import * as configuration from './configurationProvider'; 5 | 6 | export async function startVimspector( 7 | folder: WorkspaceFolder | null, 8 | nameOrConfiguration: string | DebugConfiguration 9 | ): Promise { 10 | let debugConfig: DebugConfiguration | undefined; 11 | if (typeof nameOrConfiguration === 'string') { 12 | debugConfig = workspace.getConfiguration('launch').configurations[nameOrConfiguration]; 13 | } else if (typeof nameOrConfiguration !== 'string') { 14 | debugConfig = await configuration.resolveAndValidateDebugConfiguration(folder, nameOrConfiguration); 15 | } 16 | console.log("===debugConfig : " + JSON.stringify(debugConfig)); 17 | if (typeof debugConfig == 'undefined') { 18 | window.showMessage('debug configuration undefined'); 19 | return; 20 | } 21 | const debugPort: string = await commands.executeCommand( 22 | Commands.EXECUTE_WORKSPACE_COMMAND, 23 | Commands.JAVA_START_DEBUG_SESSION 24 | ); 25 | 26 | window.showMessage(`Java debug server started on port: ${debugPort}`); 27 | 28 | const settings = { 29 | "default": { 30 | adapter: "vscode-java", 31 | variables: { 32 | DAPPort: debugPort, 33 | }, 34 | configuration: { 35 | ...debugConfig 36 | }, 37 | "breakpoints": { 38 | "exception": { 39 | "caught": "N", 40 | "uncaught": "N" 41 | } 42 | } 43 | } 44 | }; 45 | 46 | const vimspectorSettings = JSON.stringify(settings); 47 | // See https://github.com/puremourning/vimspector#launch-with-options 48 | // window.showMessage(vimspectorSettings); 49 | return workspace.nvim.eval(`vimspector#LaunchWithConfigurations(${vimspectorSettings})`); 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /testprojects/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1.helloworld 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | 19 | 1625795656865 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /testprojects/1.helloworld/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/1.helloworld/src/main/java/HelloWorld.java: -------------------------------------------------------------------------------- 1 | public class HelloWorld { 2 | public static void main(String[] args) { 3 | System.out.print("hello"); 4 | if (args != null && args.length > 0) { 5 | for (String arg : args) { 6 | System.out.print(" " + arg); 7 | } 8 | System.out.println(); 9 | } else { 10 | System.out.println(" world"); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /testprojects/10.junit/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /testprojects/10.junit/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10.junit 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/10.junit/build.gradle_: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | 5 | buildscript { 6 | repositories { 7 | mavenCentral() 8 | } 9 | dependencies { classpath "commons-io:commons-io:2.5" } 10 | } 11 | 12 | import org.apache.commons.io.FilenameUtils; 13 | 14 | sourceSets { 15 | main.java.srcDirs = ['src/main/java'] 16 | } 17 | dependencies { 18 | testCompile 'junit:junit:4.12' 19 | } 20 | 21 | 22 | repositories { 23 | mavenCentral() 24 | } 25 | 26 | def getShortJar = { e -> FilenameUtils.getName(e) } 27 | eclipse.classpath.file { 28 | withXml{xml -> 29 | def node = xml.asNode() 30 | 31 | node.classpathentry.each{ 32 | if (it.@kind == 'lib') { 33 | it.@path = 'lib/' + getShortJar(it.@path); 34 | it.@sourcepath = 'lib/' + getShortJar(it.@sourcepath); 35 | } 36 | 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /testprojects/10.junit/src/main/java/MyClass.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 Microsoft Corporation and others. All rights reserved. 3 | * This program and the accompanying materials are made available under the 4 | * terms of the Eclipse Public License v1.0 which accompanies this distribution, 5 | * and is available at http://www.eclipse.org/legal/epl-v10.html 6 | * 7 | * Contributors: Microsoft Corporation - initial API and implementation 8 | *******************************************************************************/ 9 | 10 | public class MyClass { 11 | public int multiply(int x, int y) { 12 | if (x > 999) { 13 | throw new IllegalArgumentException("X should be less than 1000"); 14 | } 15 | return x * y; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /testprojects/10.junit/src/test/java/MyTest.java: -------------------------------------------------------------------------------- 1 | import static org.junit.Assert.assertEquals; 2 | 3 | import org.junit.Test; 4 | 5 | public class MyTest { 6 | 7 | @Test(expected = IllegalArgumentException.class) 8 | public void testExceptionIsThrown() { 9 | MyClass tester = new MyClass(); 10 | tester.multiply(1000, 5); 11 | } 12 | 13 | @Test 14 | public void testMultiply() { 15 | MyClass tester = new MyClass(); 16 | assertEquals("10 x 5 must be 50", 50, tester.multiply(10, 5)); 17 | } 18 | } -------------------------------------------------------------------------------- /testprojects/11.maven/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.mycompany.app 5 | my-app 6 | jar 7 | 1.0-SNAPSHOT 8 | my-app 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /testprojects/11.maven/src/main/java/com/mycompany/app/App.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testprojects/11.maven/src/test/java/com/mycompany/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.mycompany.app; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/classes/com/mycompany/app/App.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/testprojects/11.maven/target/classes/com/mycompany/app/App.class -------------------------------------------------------------------------------- /testprojects/11.maven/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com/mycompany/app/App.class 2 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /home/zq/Code/GitSpace/coc-java-vimspector/testprojects/11.maven/src/main/java/com/mycompany/app/App.java 2 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com/mycompany/app/AppTest.class 2 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /home/zq/Code/GitSpace/coc-java-vimspector/testprojects/11.maven/src/test/java/com/mycompany/app/AppTest.java 2 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/surefire-reports/TEST-com.mycompany.app.AppTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 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 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/surefire-reports/com.mycompany.app.AppTest.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | Test set: com.mycompany.app.AppTest 3 | ------------------------------------------------------------------------------- 4 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec 5 | -------------------------------------------------------------------------------- /testprojects/11.maven/target/test-classes/com/mycompany/app/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/testprojects/11.maven/target/test-classes/com/mycompany/app/AppTest.class -------------------------------------------------------------------------------- /testprojects/12.gradle/.gitignore: -------------------------------------------------------------------------------- 1 | # Language server somehow recognizes build.gradle and compile this project. 2 | # Ignore following generated files to keep SCM clean. 3 | .gradle/ 4 | .settings/ 5 | .project 6 | .classpath 7 | -------------------------------------------------------------------------------- /testprojects/12.gradle/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | 4 | sourceSets { 5 | main.java.srcDirs = ['src/main/java'] 6 | } -------------------------------------------------------------------------------- /testprojects/12.gradle/src/main/java/GradleTest.java: -------------------------------------------------------------------------------- 1 | public class GradleTest { 2 | public static void main(String[] args) { 3 | System.out.println("This is a sample gradle project"); 4 | } 5 | } -------------------------------------------------------------------------------- /testprojects/13.customcl/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/13.customcl/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13.customcl 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/13.customcl/replacement/Foo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/testprojects/13.customcl/replacement/Foo.class -------------------------------------------------------------------------------- /testprojects/13.customcl/src/main/java/CustomCL.java: -------------------------------------------------------------------------------- 1 | import java.io.ByteArrayOutputStream; 2 | import java.io.File; 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.nio.file.Files; 6 | import java.nio.file.Paths; 7 | 8 | class CustomCL extends ClassLoader { 9 | private String baseFolder; 10 | 11 | public CustomCL(String baseFolder) { 12 | super(null); 13 | this.baseFolder = baseFolder; 14 | } 15 | 16 | @Override 17 | protected Class findClass(String name) throws ClassNotFoundException { 18 | // load from parent 19 | Class result = findLoadedClass(name); 20 | if (result != null) { 21 | return result; 22 | } 23 | 24 | try { 25 | File classFile = new File(baseFolder, name + ".class"); 26 | if (classFile.exists()) { 27 | byte[] bytes = Files.readAllBytes(Paths.get(classFile.getAbsolutePath())); 28 | return defineClass(name, bytes, 0, bytes.length); 29 | } 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } 33 | return getSystemClassLoader().loadClass(name); 34 | 35 | } 36 | 37 | @Override 38 | protected Class loadClass(String name, boolean resolve) 39 | throws ClassNotFoundException { 40 | Class cls; 41 | 42 | cls = findLoadedClass(name); 43 | if (cls == null) { 44 | cls = findClass(name); 45 | } 46 | 47 | if (cls == null) { 48 | throw new ClassNotFoundException(name); 49 | } 50 | 51 | if (resolve) 52 | resolveClass(cls); 53 | return cls; 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /testprojects/13.customcl/src/main/java/CustomClassLoaderTest.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | 3 | public class CustomClassLoaderTest { 4 | public static void main(String[] args) { 5 | File replacement = new File(new File("").getAbsolutePath(), "replacement"); 6 | if (!replacement.exists()) { 7 | replacement = new File(new File("").getAbsolutePath(), "../replacement"); 8 | } 9 | 10 | 11 | final String replacementFolder = replacement.getAbsolutePath(); 12 | new Thread(()-> { 13 | try { 14 | System.out.println("Using " + replacementFolder); 15 | CustomCL cl = new CustomCL(replacementFolder); 16 | Class cls = cl.loadClass("Foo"); 17 | 18 | IFoo foo = (IFoo)cls.newInstance(); 19 | new Foo().sayHello(); 20 | foo.sayHello(); 21 | } catch(Exception ex) { 22 | ex.printStackTrace(); 23 | } 24 | }).start(); 25 | } 26 | } -------------------------------------------------------------------------------- /testprojects/13.customcl/src/main/java/Foo.java: -------------------------------------------------------------------------------- 1 | public class Foo implements IFoo { 2 | public void sayHello() { 3 | System.out.println("hello world! (version one)"); 4 | } 5 | } -------------------------------------------------------------------------------- /testprojects/13.customcl/src/main/java/IFoo.java: -------------------------------------------------------------------------------- 1 | public interface IFoo { 2 | void sayHello(); 3 | } 4 | -------------------------------------------------------------------------------- /testprojects/14.encoding/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/14.encoding/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14.encoding 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/14.encoding/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java/EncodingTest.java=gbk 3 | -------------------------------------------------------------------------------- /testprojects/14.encoding/src/main/java/EncodingTest.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/testprojects/14.encoding/src/main/java/EncodingTest.java -------------------------------------------------------------------------------- /testprojects/15.specialname/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/15.specialname/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15.specialname 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/15.specialname/src/main/java/ab$c/Hello$orld.java: -------------------------------------------------------------------------------- 1 | package ab$c; 2 | public class Hello$orld { 3 | public static void main(String args[]) { 4 | System.out.println("Hello$orld"); 5 | } 6 | } -------------------------------------------------------------------------------- /testprojects/16.resolvemainclass/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testprojects/16.resolvemainclass/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16.resolvemainclass 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/16.resolvemainclass/build.gradle_: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | 5 | buildscript { 6 | repositories { 7 | mavenCentral() 8 | } 9 | dependencies { classpath "commons-io:commons-io:2.5" } 10 | } 11 | 12 | import org.apache.commons.io.FilenameUtils; 13 | 14 | sourceSets { 15 | main.java.srcDirs = ['src/main/java'] 16 | } 17 | dependencies { 18 | testCompile 'junit:junit:4.12' 19 | } 20 | 21 | 22 | repositories { 23 | mavenCentral() 24 | } 25 | 26 | def getShortJar = { e -> FilenameUtils.getName(e) } 27 | eclipse.classpath.file { 28 | withXml{xml -> 29 | def node = xml.asNode() 30 | 31 | node.classpathentry.each{ 32 | if (it.@kind == 'lib') { 33 | it.@path = 'lib/' + getShortJar(it.@path); 34 | it.@sourcepath = 'lib/' + getShortJar(it.@sourcepath); 35 | } 36 | 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /testprojects/16.resolvemainclass/src/main/java/MyApp.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 Microsoft Corporation and others. All rights reserved. 3 | * This program and the accompanying materials are made available under the 4 | * terms of the Eclipse Public License v1.0 which accompanies this distribution, 5 | * and is available at http://www.eclipse.org/legal/epl-v10.html 6 | * 7 | * Contributors: Microsoft Corporation - initial API and implementation 8 | *******************************************************************************/ 9 | 10 | public class MyApp { 11 | public static void main(String agrsp[]) { 12 | System.out.println("Hello App!"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /testprojects/16.resolvemainclass/src/test/java/MyAppTest.java: -------------------------------------------------------------------------------- 1 | 2 | public class MyAppTest { 3 | 4 | public static void main(String agrsp[]) { 5 | System.out.println("Hello test App!"); 6 | } 7 | } -------------------------------------------------------------------------------- /testprojects/17.argstest/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/17.argstest/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17.argstest 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/17.argstest/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /testprojects/17.argstest/src/test/ArgsTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | public class ArgsTest { 9 | 10 | public static void main(String[] args) throws IOException { 11 | 12 | List proList=Arrays.asList(args); 13 | 14 | String sysProp1Value = System.getProperty("sysProp1"); 15 | String sysProp2Value = System.getProperty("sysProp2"); 16 | List vmList=new ArrayList<>(); 17 | vmList.add(sysProp1Value ); 18 | vmList.add(sysProp2Value ); 19 | String encoding=System.getProperty("file.encoding"); 20 | System.out.println("Program Arguments:"+String.join(" ", proList)+" VM Arguments:"+String.join(" ",vmList)); 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /testprojects/18.attachdebug/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/18.attachdebug/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18.attachdebug 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/18.attachdebug/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /testprojects/18.attachdebug/src/test/attachdebug.java: -------------------------------------------------------------------------------- 1 | package test; 2 | import java.util.stream.Stream; 3 | 4 | public class attachdebug { 5 | public static void main(String[] args) { 6 | String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); 7 | Integer[] sixNums = {1, 2, 3, 4, 5, 6}; 8 | int evens = 9 | Stream.of(sixNums).filter(n -> n%2 == 0).reduce(0, Integer::sum); 10 | 11 | System.out.println(concat+" "+evens); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /testprojects/19.java9-app/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.microsoft.app 5 | java9-app 6 | jar 7 | 1.0-SNAPSHOT 8 | java9-app 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | com.google.code.gson 19 | gson 20 | 2.7 21 | 22 | 23 | 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-compiler-plugin 29 | 3.7.0 30 | 31 | 9 32 | 9 33 | true 34 | true 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /testprojects/19.java9-app/src/main/java/com/microsoft/app/App.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.app; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class App 6 | { 7 | public static void main( String[] args ) 8 | { 9 | Gson GSON = new Gson(); 10 | String name = "jinbwan"; 11 | Employee employee = GSON.fromJson("{\"name\": \"" + name + "\"}", Employee.class); 12 | System.out.println(employee.getName()); 13 | } 14 | 15 | static class Employee { 16 | public String name; 17 | 18 | public String getName() { 19 | return this.name; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /testprojects/19.java9-app/src/main/java/com/microsoft/app/Launcher.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.app; 2 | 3 | import java.nio.file.Paths; 4 | 5 | public class Launcher { 6 | public static void main(String[] args) { 7 | System.out.println(Paths.get("").toAbsolutePath().toString()); 8 | 9 | System.out.println(System.getenv("Path")); 10 | } 11 | } -------------------------------------------------------------------------------- /testprojects/19.java9-app/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module com.microsoft.app.mymodule { 2 | requires gson; 3 | requires java.base; 4 | requires java.sql; 5 | opens com.microsoft.app; 6 | } -------------------------------------------------------------------------------- /testprojects/19.java9-app/src/test/java/com/microsoft/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.app; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testprojects/2.callstack/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/2.callstack/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.callstack 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/2.callstack/src/main/java/Bar.java: -------------------------------------------------------------------------------- 1 | public class Bar { 2 | public void testBar(int i) { 3 | System.out.println("This is test method in bar."); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /testprojects/2.callstack/src/main/java/CallStack.java: -------------------------------------------------------------------------------- 1 | public class CallStack { 2 | public static void main(String[] args) { 3 | Foo foo = new Foo(); 4 | foo.testFoo(10); 5 | } 6 | } -------------------------------------------------------------------------------- /testprojects/2.callstack/src/main/java/Foo.java: -------------------------------------------------------------------------------- 1 | public class Foo { 2 | private Bar bar = new Bar(); 3 | 4 | public void testFoo(int j) { 5 | System.out.println("This is test method in foo."); 6 | bar.testBar(j + 10); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /testprojects/20.usersettings/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/20.usersettings/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20.usersettings 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/20.usersettings/src/main/java/usersettings/UserSettings.java: -------------------------------------------------------------------------------- 1 | package usersettings; 2 | 3 | public class UserSettings { 4 | private static int number = 20; 5 | 6 | public static void main(String[] args) { 7 | 8 | String testName = "usersettings"; 9 | System.out.println("Test name is " + testName + " and the test number is " + number); 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /testprojects/21.evaluate/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/21.evaluate/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21.evaluate 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/21.evaluate/src/main/java/evaluate/EvaluateTest.java: -------------------------------------------------------------------------------- 1 | package evaluate; 2 | 3 | public class EvaluateTest { 4 | public static void main(String[] args) { 5 | int i = 0; 6 | i++; 7 | int test1 = new EvaluateTest().test(); 8 | System.out.print(test1 + i); 9 | } 10 | 11 | public static int test() { 12 | return 3; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /testprojects/21.single-file/Main.java: -------------------------------------------------------------------------------- 1 | public class Main{ 2 | public static void main(String[] args) { 3 | String s = "1"; 4 | char sr = 'c'; 5 | int t = 1; 6 | t++; 7 | test(t); 8 | } 9 | 10 | private static void test(int t) { 11 | int s = 1; 12 | System.out.println("test" + s + t); 13 | } 14 | } -------------------------------------------------------------------------------- /testprojects/22.jdkversion/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/22.jdkversion/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22.jdkversion 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/22.jdkversion/src/main/java/JdkVersion.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | 4 | public class JdkVersion { 5 | public static void main(String[] args) { 6 | String jdkVersion = System.getProperty("java.version"); 7 | 8 | List nums = Arrays.asList(1, 2, 3, 4); 9 | float squareNums = nums.stream().map(n -> n * n).reduce((sum, n) -> sum + n).get().floatValue(); 10 | System.out.println(jdkVersion); 11 | System.out.println(squareNums); 12 | } 13 | } -------------------------------------------------------------------------------- /testprojects/23.console-app/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.microsoft.test 5 | console-app 6 | jar 7 | 1.0-SNAPSHOT 8 | console-app 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /testprojects/23.console-app/src/main/java/com/microsoft/test/App.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.test; 2 | 3 | import java.util.Scanner; 4 | 5 | public class App 6 | { 7 | public static void main( String[] args ) 8 | { 9 | System.out.println("Please input your name:"); 10 | 11 | Scanner in = new Scanner(System.in); 12 | String name = in.nextLine(); 13 | 14 | System.out.println("Thanks, " + name); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /testprojects/23.console-app/src/test/java/com/microsoft/test/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.test; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | HelloWorld 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/src/com/microsoft/debug/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | 4 | public class HelloWorld { 5 | static class InnerType { 6 | public static void print() { 7 | System.out.println("Inner Type."); 8 | } 9 | } 10 | 11 | private static int value = 0; 12 | 13 | public static void main(String[] args) throws Exception { 14 | new Thread() { 15 | public void run() { 16 | while (true) { 17 | try { 18 | Thread.sleep(500); 19 | 20 | System.out.println("thread 1"); 21 | 22 | Person person = new Person("c4"); 23 | System.out.println(person.getName()); 24 | person.toString(); 25 | } catch (InterruptedException e) { 26 | } 27 | } 28 | } 29 | }.start(); 30 | 31 | 32 | new Thread() { 33 | public void run() { 34 | while (true) { 35 | try { 36 | Thread.sleep(500); 37 | 38 | System.out.println("thread 2"); 39 | 40 | Person person = new Person("c4"); 41 | System.out.println(person.getName()); 42 | person.toString(); 43 | } catch (InterruptedException e) { 44 | } 45 | } 46 | } 47 | }.start(); 48 | 49 | change(); 50 | while (true) { 51 | try { 52 | Thread.sleep(1000); 53 | } catch (InterruptedException e) { 54 | 55 | } 56 | } 57 | } 58 | 59 | public static void change() { 60 | value++; 61 | System.out.println(value); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/src/com/microsoft/debug/NameProvider.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | public class NameProvider { 4 | 5 | public String fieldName; 6 | 7 | public NameProvider(String fieldName) { 8 | this.fieldName = fieldName; 9 | } 10 | 11 | public String getName() { 12 | return " + Provider" + this.fieldName; 13 | } 14 | } -------------------------------------------------------------------------------- /testprojects/24.hotCodeReplace/src/com/microsoft/debug/Person.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | public class Person { 4 | 5 | private String name; 6 | 7 | public Person(String name) { 8 | this.name = name; 9 | } 10 | 11 | public String getName() { 12 | String res = "old"; 13 | for (int i = 0; i < 2; i++) { 14 | res += i; 15 | } 16 | res += this.getInternalName(); 17 | return res; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | private String getInternalName() { 25 | int i = 2; 26 | NameProvider provider = new NameProvider(""); 27 | i++; 28 | return provider.getName(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /testprojects/25.restartFrame/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/25.restartFrame/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | HelloWorld 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/25.restartFrame/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /testprojects/25.restartFrame/src/com/microsoft/debug/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | 4 | public class HelloWorld { 5 | static class InnerType { 6 | public static void print() { 7 | System.out.println("Inner Type."); 8 | } 9 | } 10 | 11 | private static int value = 0; 12 | 13 | public static void main(String[] args) throws Exception { 14 | new Thread() { 15 | public void run() { 16 | while (true) { 17 | try { 18 | Thread.sleep(500); 19 | 20 | System.out.println("thread 1"); 21 | 22 | Person person = new Person("c4"); 23 | System.out.println(person.getName()); 24 | person.toString(); 25 | } catch (InterruptedException e) { 26 | } 27 | } 28 | } 29 | }.start(); 30 | 31 | 32 | new Thread() { 33 | public void run() { 34 | while (true) { 35 | try { 36 | Thread.sleep(500); 37 | 38 | System.out.println("thread 2"); 39 | 40 | Person person = new Person("c4"); 41 | System.out.println(person.getName()); 42 | person.toString(); 43 | } catch (InterruptedException e) { 44 | } 45 | } 46 | } 47 | }.start(); 48 | 49 | change(); 50 | while (true) { 51 | try { 52 | Thread.sleep(1000); 53 | } catch (InterruptedException e) { 54 | 55 | } 56 | } 57 | } 58 | 59 | public static void change() { 60 | value++; 61 | System.out.println(value); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /testprojects/25.restartFrame/src/com/microsoft/debug/NameProvider.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | public class NameProvider { 4 | 5 | public String fieldName; 6 | 7 | public NameProvider(String fieldName) { 8 | this.fieldName = fieldName; 9 | } 10 | 11 | public String getName() { 12 | return " + Provider" + this.fieldName; 13 | } 14 | } -------------------------------------------------------------------------------- /testprojects/25.restartFrame/src/com/microsoft/debug/Person.java: -------------------------------------------------------------------------------- 1 | package com.microsoft.debug; 2 | 3 | public class Person { 4 | 5 | private String name; 6 | 7 | public Person(String name) { 8 | this.name = name; 9 | } 10 | 11 | public String getName() { 12 | String res = "old"; 13 | for (int i = 0; i < 2; i++) { 14 | res += i; 15 | } 16 | res += this.getInternalName(); 17 | return res; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | private String getInternalName() { 25 | int i = 2; 26 | NameProvider provider = new NameProvider(""); 27 | i++; 28 | return provider.getName(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /testprojects/26.environmentVariables/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/26.environmentVariables/.env: -------------------------------------------------------------------------------- 1 | FILE_ENV_FOR_TEST_PLAN=Successfully loaded an env from a file. -------------------------------------------------------------------------------- /testprojects/26.environmentVariables/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 26.environmentVariables 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/26.environmentVariables/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 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 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "java", 10 | "name": "Debug (Launch)-EnvrionmentVariable<26.environmentVariables>", 11 | "request": "launch", 12 | "cwd": "${workspaceFolder}", 13 | "console": "internalConsole", 14 | "stopOnEntry": false, 15 | "mainClass": "EnvrionmentVariable", 16 | "args": "", 17 | "projectName": "26.environmentVariables", 18 | "env": { 19 | "CUSTOM_ENV_FOR_TEST_PLAN": "This env is for test plan." 20 | }, 21 | "envFile": "${workspaceFolder}/.env" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /testprojects/26.environmentVariables/src/main/java/EnvrionmentVariable.java: -------------------------------------------------------------------------------- 1 | public class EnvrionmentVariable { 2 | public static void main(String[] args) { 3 | String customEnv = System.getenv("CUSTOM_ENV_FOR_TEST_PLAN"); 4 | String systemPath = System.getenv("PATH"); 5 | String envFromFile = System.getenv("FILE_ENV_FOR_TEST_PLAN"); 6 | System.out.println(String.format("CustomEnv: %s", customEnv)); 7 | System.out.println(String.format("SystemPath: %s", systemPath)); 8 | System.out.println(String.format("FileEnv: %s", envFromFile)); 9 | } 10 | } -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.github.kdvolder 7 | hello-world-service 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.0.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-web 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-test 39 | test 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-devtools 44 | runtime 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-configuration-processor 49 | true 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-maven-plugin 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/java/com/github/kdvolder/helloworldservice/Constants.java: -------------------------------------------------------------------------------- 1 | package com.github.kdvolder.helloworldservice; 2 | 3 | public class Constants { 4 | public static final String GREETER_ID = "greeets"; 5 | } -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/java/com/github/kdvolder/helloworldservice/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.kdvolder.helloworldservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | 14 | @SpringBootApplication 15 | @RestController 16 | @EnableScheduling 17 | public class DemoApplication { 18 | 19 | public static class Bar { 20 | } 21 | 22 | public static class Foo { 23 | } 24 | 25 | @Autowired(required=false) void foo(@Qualifier("foobar")Foo foo) { 26 | System.out.println("a Foo got injected"); 27 | } 28 | 29 | @Autowired(required=false) void bar(@Qualifier("foobar")Bar bar) { 30 | System.out.println("a Bar got injected"); 31 | } 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(DemoApplication.class, args); 35 | } 36 | 37 | @GetMapping(value="/") 38 | public String mainpage() { 39 | return "Hello "+System.getProperty("greeting"); 40 | } 41 | 42 | 43 | @GetMapping(value = "/hello/{name}") 44 | public String getMethodName(@PathVariable String name) { 45 | return "Hello "+name; 46 | } 47 | 48 | 49 | @Bean Foo foobar() { 50 | return new Foo(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/java/com/github/kdvolder/helloworldservice/Greeter.java: -------------------------------------------------------------------------------- 1 | package com.github.kdvolder.helloworldservice; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | 6 | @Component 7 | public class Greeter { 8 | 9 | String greeting(String name) { 10 | return "Hello "+name; 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/java/com/github/kdvolder/helloworldservice/MyProperties.java: -------------------------------------------------------------------------------- 1 | package com.github.kdvolder.helloworldservice; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; 5 | 6 | @ConfigurationProperties("my") 7 | public class MyProperties { 8 | 9 | private String hello; 10 | 11 | /** 12 | * @return the hello 13 | */ 14 | @DeprecatedConfigurationProperty(replacement="new.my.hello") 15 | public String getHello() { 16 | return hello; 17 | } 18 | 19 | /** 20 | * @param hello the hello to set 21 | */ 22 | public void setHello(String hello) { 23 | this.hello = hello; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | my.hello=Yadaya 2 | -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | my: 2 | other: stuff 3 | hello: blah 4 | new: 5 | my: 6 | other: stuff -------------------------------------------------------------------------------- /testprojects/27.runtimeClassEntry/src/test/java/com/github/kdvolder/helloworldservice/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.github.kdvolder.helloworldservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /testprojects/28.debugfeatures/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // "java.home": "C:\\Program Files\\Java\\jdk-12", 3 | "java.debug.settings.showLogicalStructure": true, 4 | "java.debug.settings.forceBuildBeforeLaunch": false 5 | } -------------------------------------------------------------------------------- /testprojects/28.debugfeatures/Java12Preview.java: -------------------------------------------------------------------------------- 1 | public class Java12Preview { 2 | 3 | public static void main(String[] args) { 4 | String week = "MONDAY"; 5 | switch (week) { 6 | case "MONDAY" -> { 7 | System.out.println("This is Monday"); 8 | } 9 | case "TUESDAY" -> System.out.println("This is TUESDAY"); 10 | default -> System.out.println("Unknown day."); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /testprojects/28.debugfeatures/LogicalStructure.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class LogicalStructure { 9 | 10 | public static void main(String[] args) { 11 | int[] arrays = new int[] { 1 }; 12 | Object obj = new Object(); 13 | Map emptyMap = new HashMap<>(); 14 | Map bookset = new LinkedHashMap<>(); 15 | bookset.put("Algorithm Introduction", 60); 16 | bookset.put("Thinking in JAVA", 50); 17 | 18 | Map> bigStore = new HashMap<>(); 19 | for (int i = 0; i < 100000; i++) { 20 | bigStore.put("key" + i, bookset); 21 | } 22 | 23 | List emptyList = new ArrayList<>(); 24 | List list = Arrays.asList(new Foo("One"), new Foo("Two")); 25 | List bigList = new ArrayList<>(); 26 | for (int i = 0; i < 100000; i++) { 27 | bigList.add("key" + i); 28 | } 29 | 30 | System.out.println("Exit."); 31 | } 32 | 33 | static class Foo { 34 | private String name; 35 | 36 | Foo(String name) { 37 | this.name = name; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testprojects/28.debugfeatures/StackTrace.java: -------------------------------------------------------------------------------- 1 | public class StackTrace { 2 | 3 | public static void main(String[] args) { 4 | System.out.println("begin."); 5 | new RuntimeException("test").printStackTrace(); 6 | 7 | System.out.println("finish."); 8 | new RuntimeException("test1").printStackTrace(System.out); 9 | 10 | System.out.println("exit"); 11 | throw new RuntimeException("test2"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testprojects/28.debugfeatures/Variables.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Variables { 4 | 5 | public static void main(String[] args) { 6 | int[] a = new int[100000]; 7 | Integer intObj = new Integer(20); 8 | Float floatObj = new Float("1.354"); 9 | Character character = new Character('a'); 10 | Boolean bool = new Boolean(true); 11 | 12 | Map emptyMap = new HashMap<>(); 13 | Map bookset = new LinkedHashMap<>(); 14 | bookset.put("Algorithm Introduction", 60); 15 | bookset.put("Thinking in JAVA", 50); 16 | 17 | Map> smallStore = new HashMap<>(); 18 | smallStore.put("Computer Science", bookset); 19 | 20 | Map> bigStore = new HashMap<>(); 21 | for (int i = 0; i < 100000; i++) { 22 | bigStore.put("key" + i, bookset); 23 | } 24 | 25 | List smallList = Arrays.asList("Algorithm Introduction"); 26 | List bigList = new ArrayList<>(); 27 | for (int i = 0; i < 100000; i++) { 28 | bigList.add("key" + i); 29 | } 30 | 31 | School school = new School(); 32 | Person person = new Person(); 33 | Person person1 = null; 34 | Employee employee = new Employee(); 35 | StringException stringException = new StringException(); 36 | NullString nullString =new NullString(); 37 | Date date = new Date(); 38 | String name = "Test"; 39 | System.out.println("Exit."); 40 | } 41 | 42 | public static class School { 43 | String name = "test"; 44 | 45 | } 46 | 47 | public static class Person { 48 | String name = "jinbo"; 49 | 50 | @Override 51 | public String toString() { 52 | return "Person [name=" + name + "]"; 53 | } 54 | } 55 | 56 | public static class Employee extends Person { 57 | 58 | } 59 | 60 | public static class StringException { 61 | 62 | @Override 63 | public String toString() { 64 | throw new RuntimeException("Unimplemented method exception"); 65 | } 66 | } 67 | 68 | public static class NullString { 69 | 70 | @Override 71 | public String toString() { 72 | return null; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /testprojects/3.thread/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/3.thread/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3.thread 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/3.thread/src/main/java/ThreadTest.java: -------------------------------------------------------------------------------- 1 | import java.util.concurrent.atomic.AtomicInteger; 2 | 3 | public class ThreadTest { 4 | public static void main(String[] args) throws Exception { 5 | Object object = new Object(); 6 | AtomicInteger ai = new AtomicInteger(); 7 | Thread thread1 = new Thread(() -> { 8 | for (;;) { 9 | try { 10 | synchronized(object) { 11 | object.wait(); 12 | } 13 | System.out.println(String.format("Print %d in %d" , ai.incrementAndGet(), Thread.currentThread().getId())); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | break; 17 | } 18 | } 19 | }); 20 | Thread thread2 = new Thread(() -> { 21 | for (;;) { 22 | System.out.println(String.format("Print %d in %d" , ai.incrementAndGet(), Thread.currentThread().getId())); 23 | synchronized(object) { 24 | object.notify(); 25 | } 26 | try { 27 | Thread.sleep(1000); 28 | } catch (InterruptedException e) { 29 | e.printStackTrace(); 30 | break; 31 | } 32 | } 33 | }); 34 | thread1.start(); 35 | thread2.start(); 36 | thread1.join(); 37 | thread2.join(); 38 | } 39 | } -------------------------------------------------------------------------------- /testprojects/4.variable/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/4.variable/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.variable 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/4.variable/src/main/java/VariableTest.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.Array; 2 | import java.util.ArrayList; 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | @SuppressWarnings("unused") 8 | public class VariableTest extends Foo { 9 | private static int x = 100; 10 | 11 | @SuppressWarnings("unchecked") 12 | public static T[] createArray(Class type, int size) { 13 | return (T[]) Array.newInstance(type, size); 14 | } 15 | 16 | private int i = 19099; 17 | @SuppressWarnings({ "rawtypes", "unchecked" }) 18 | public void test() { 19 | int[] arrays = new int[] { 1 }; 20 | int i = 100; 21 | i += 10; 22 | String nullstr = null; 23 | String str = "string test"; 24 | for (int l = 0; l < 1000; l++) { 25 | str += "a"; 26 | } 27 | Object obj = new Object(); 28 | Object test = new VariableTest(); 29 | Object a = new A(); 30 | Class b = A.class; 31 | int[] intarray = new int[] { 1, 2, 3 }; 32 | List strList = new ArrayList<>(); 33 | strList.add(str); 34 | strList.add(null); 35 | Map map = new HashMap(); 36 | String[] t = new String[] { "hello" }; 37 | 38 | String[][] genericArray = createArray((Class) t.getClass(), 10); 39 | String[][][] multi = new String[5][10][32]; 40 | genericArray[0] = t; 41 | map.put("a", 1); 42 | i++; 43 | ArrayList[] d = new ArrayList[0]; 44 | System.out.println(d.length); 45 | 46 | GenericsFoo dd = new GenericsFoo(new Foo()); 47 | ArrayList list = new ArrayList<>(); 48 | list.add(new int[] { 1 }); 49 | i++; 50 | } 51 | 52 | public static void main(String[] args) { 53 | new VariableTest().test(); 54 | } 55 | } 56 | 57 | 58 | @SuppressWarnings("unused") 59 | interface BBB { 60 | static void test() { 61 | int j = 0; 62 | j++; 63 | } 64 | } 65 | 66 | class BaseA { 67 | 68 | class BBB { 69 | } 70 | 71 | int baseI = 10; 72 | } 73 | 74 | class A { 75 | class BB { 76 | public void test() { 77 | A.this.new BB(); 78 | } 79 | 80 | class CC { 81 | class DD { 82 | 83 | } 84 | } 85 | } 86 | } 87 | @SuppressWarnings("unused") 88 | class Foo { 89 | private int x; 90 | } 91 | 92 | class GenericsFoo { 93 | private G x; 94 | 95 | public GenericsFoo(G x) { 96 | this.x = x; 97 | } 98 | 99 | public G getX() { 100 | return x; 101 | } 102 | 103 | public void setX(G x) { 104 | this.x = x; 105 | } 106 | } -------------------------------------------------------------------------------- /testprojects/5.breakpoint/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/5.breakpoint/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5.breakpoint 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/5.breakpoint/src/main/java/BreakPointTest.java: -------------------------------------------------------------------------------- 1 | class A { 2 | void m() { 3 | System.out.println("outer"); 4 | } 5 | } 6 | 7 | public class BreakPointTest { 8 | public static void main(String[] args) { 9 | new BreakPointTest().go(); 10 | int j = 0; 11 | new A() { 12 | void m() { 13 | System.out.println("anonymous"); 14 | } 15 | }.m(); 16 | for (int i = 1; i <= 100; i++) { 17 | if (i <= 99) { 18 | j++; 19 | } else { 20 | System.out.println(j); 21 | } 22 | 23 | } 24 | } 25 | 26 | void go() { 27 | new A().m(); 28 | class A { 29 | void m() { 30 | System.out.println("inner"); 31 | } 32 | } 33 | new A().m(); 34 | } 35 | 36 | static class A { 37 | void m() { 38 | System.out.println("middle"); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /testprojects/6.recursivefunction/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/6.recursivefunction/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6.recursivefunction 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/6.recursivefunction/src/main/java/RecursiveTest.java: -------------------------------------------------------------------------------- 1 | public class RecursiveTest { 2 | public static void main(String[] args) { 3 | testRecursion(1000); 4 | } 5 | 6 | public static int testRecursion(int number) { 7 | if (number == 1) { 8 | return 1; 9 | } else { 10 | int result = 1 + testRecursion(number - 1); 11 | return result; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /testprojects/7.variableperformance/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /testprojects/7.variableperformance/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7.variableperformance 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/7.variableperformance/src/main/java/VariablePerfTest.java: -------------------------------------------------------------------------------- 1 | public class VariablePerfTest { 2 | public static void main(String[] args) { 3 | new TooManyVariables().test(); 4 | } 5 | } -------------------------------------------------------------------------------- /testprojects/8.nosource/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testprojects/8.nosource/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8.nosource 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/8.nosource/build.gradle_: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | 5 | 6 | sourceSets { 7 | main.java.srcDirs = ['src/main/java'] 8 | } 9 | 10 | dependencies { 11 | compile files("lib/test1.jar") 12 | compile files("lib/commons-io-2.5.jar") 13 | } 14 | 15 | 16 | repositories { 17 | mavenCentral() 18 | } 19 | 20 | eclipse.classpath.file { 21 | withXml{xml -> 22 | def node = xml.asNode() 23 | 24 | node.classpathentry.find{ 25 | it.@kind == 'lib' && it.@path.contains('/test1.jar') 26 | }.@sourcepath = 'lib/test1-sources.jar' 27 | } 28 | } -------------------------------------------------------------------------------- /testprojects/8.nosource/src/main/java/NoSourceTest.java: -------------------------------------------------------------------------------- 1 | public class NoSourceTest { 2 | public static void main(String[] args) throws Exception { 3 | new test.Foo().bar(1,2, i-> { 4 | System.out.println(i+10); 5 | }); 6 | } 7 | } -------------------------------------------------------------------------------- /testprojects/9.realcase.lucene/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /testprojects/9.realcase.lucene/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9.realcase.lucene 4 | 5 | 6 | 7 | org.eclipse.jdt.core.javanature 8 | 9 | 10 | 11 | org.eclipse.jdt.core.javabuilder 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /testprojects/9.realcase.lucene/build.gradle_: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | 5 | buildscript { 6 | repositories { 7 | mavenCentral() 8 | } 9 | dependencies { classpath "commons-io:commons-io:2.5" } 10 | } 11 | 12 | import org.apache.commons.io.FilenameUtils; 13 | 14 | sourceSets { 15 | main.java.srcDirs = ['src/main/java'] 16 | } 17 | dependencies { 18 | compile group: 'commons-io', name: 'commons-io', version: '2.5' 19 | compile group: 'org.apache.lucene', name: 'lucene-core', version: '6.6.0' 20 | compile group: 'org.apache.lucene', name: 'lucene-queryparser', version: '6.6.0' 21 | compile group: 'org.apache.lucene', name: 'lucene-analyzers-common', version: '6.6.0' 22 | } 23 | 24 | 25 | repositories { 26 | mavenCentral() 27 | } 28 | 29 | def getShortJar = { e -> FilenameUtils.getName(e) } 30 | eclipse.classpath.file { 31 | withXml{xml -> 32 | def node = xml.asNode() 33 | 34 | node.classpathentry.each{ 35 | if (it.@kind == 'lib') { 36 | it.@path = 'lib/' + getShortJar(it.@path); 37 | it.@sourcepath = 'lib/' + getShortJar(it.@sourcepath); 38 | } 39 | 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /testprojects/9.realcase.lucene/src/main/java/LuceneTest.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.io.IOException; 3 | import java.nio.file.Files; 4 | import java.nio.file.Paths; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.apache.commons.io.FileUtils; 9 | import org.apache.lucene.analysis.standard.StandardAnalyzer; 10 | import org.apache.lucene.document.Document; 11 | import org.apache.lucene.document.Field; 12 | import org.apache.lucene.document.StringField; 13 | import org.apache.lucene.document.TextField; 14 | import org.apache.lucene.index.DirectoryReader; 15 | import org.apache.lucene.index.IndexReader; 16 | import org.apache.lucene.index.IndexWriter; 17 | import org.apache.lucene.index.IndexWriterConfig; 18 | import org.apache.lucene.queryparser.classic.QueryParser; 19 | import org.apache.lucene.search.IndexSearcher; 20 | import org.apache.lucene.search.Query; 21 | import org.apache.lucene.search.ScoreDoc; 22 | import org.apache.lucene.search.TopDocs; 23 | import org.apache.lucene.store.Directory; 24 | import org.apache.lucene.store.FSDirectory; 25 | 26 | public class LuceneTest { 27 | private static String indexDirectory; 28 | 29 | public static void main(String[] args) throws Exception { 30 | File file = Files.createTempDirectory("test_lucene").toFile(); 31 | indexDirectory = file.getAbsolutePath(); 32 | FileUtils.forceDeleteOnExit(file); 33 | IndexWriter writer = createWriter(); 34 | List documents = new ArrayList<>(); 35 | 36 | Document document1 = createDocument(1, "Andy", "XU", "andxu@microsoft.com"); 37 | documents.add(document1); 38 | 39 | Document document2 = createDocument(2, "Jinbo", "Wang", "jinbwan@microsoft.com"); 40 | documents.add(document2); 41 | 42 | //Let's clean everything first 43 | writer.deleteAll(); 44 | 45 | writer.addDocuments(documents); 46 | writer.commit(); 47 | writer.close(); 48 | 49 | IndexSearcher searcher = createSearcher(); 50 | 51 | //Search by ID 52 | TopDocs foundDocs = searchById(2, searcher); 53 | 54 | System.out.println("Total Results :: " + foundDocs.totalHits); 55 | 56 | for (ScoreDoc sd : foundDocs.scoreDocs) { 57 | Document d = searcher.doc(sd.doc); 58 | System.out.println(String.format("%s, %s, %s", d.get("id"), d.get("email"), d.get("firstName"))); 59 | } 60 | 61 | //Search by firstName 62 | TopDocs foundDocs2 = searchByFirstName("Andy", searcher); 63 | 64 | System.out.println("Total Results :: " + foundDocs2.totalHits); 65 | 66 | for (ScoreDoc sd : foundDocs2.scoreDocs) { 67 | Document d = searcher.doc(sd.doc); 68 | System.out.println(String.format("%s, %s, %s", d.get("id"), d.get("email"), d.get("firstName"))); 69 | } 70 | } 71 | 72 | private static Document createDocument(Integer id, String firstName, String lastName, String email) { 73 | Document document = new Document(); 74 | document.add(new StringField("id", id.toString(), Field.Store.YES)); 75 | document.add(new TextField("firstName", firstName, Field.Store.YES)); 76 | document.add(new TextField("lastName", lastName, Field.Store.YES)); 77 | document.add(new TextField("email", email, Field.Store.YES)); 78 | return document; 79 | } 80 | 81 | private static IndexWriter createWriter() throws IOException { 82 | FSDirectory dir = FSDirectory.open(Paths.get(indexDirectory)); 83 | IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer()); 84 | IndexWriter writer = new IndexWriter(dir, config); 85 | return writer; 86 | } 87 | 88 | private static TopDocs searchByFirstName(String firstName, IndexSearcher searcher) throws Exception { 89 | QueryParser qp = new QueryParser("firstName", new StandardAnalyzer()); 90 | Query firstNameQuery = qp.parse(firstName); 91 | TopDocs hits = searcher.search(firstNameQuery, 10); 92 | return hits; 93 | } 94 | 95 | private static TopDocs searchById(Integer id, IndexSearcher searcher) throws Exception { 96 | QueryParser qp = new QueryParser("id", new StandardAnalyzer()); 97 | Query idQuery = qp.parse(id.toString()); 98 | TopDocs hits = searcher.search(idQuery, 10); 99 | return hits; 100 | } 101 | 102 | private static IndexSearcher createSearcher() throws IOException { 103 | Directory dir = FSDirectory.open(Paths.get(indexDirectory)); 104 | IndexReader reader = DirectoryReader.open(dir); 105 | IndexSearcher searcher = new IndexSearcher(reader); 106 | return searcher; 107 | } 108 | } -------------------------------------------------------------------------------- /testprojects/longclasspath/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | -------------------------------------------------------------------------------- /testprojects/longclasspath/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.example' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | compile("org.springframework.boot:spring-boot-starter-data-mongodb") 18 | compile('org.springframework.boot:spring-boot-starter-web') 19 | compile('org.apache.spark:spark-core_2.11:2.4.7') 20 | compile('org.apache.spark:spark-sql_2.11:2.4.7') 21 | // compile('org.mongodb.spark:mongo-spark-connector_2.11:2.3.1') 22 | testImplementation('org.springframework.boot:spring-boot-starter-test') 23 | } 24 | 25 | configurations.all { 26 | exclude module: 'slf4j-log4j12' 27 | } -------------------------------------------------------------------------------- /testprojects/longclasspath/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lidulibai/coc-java-vimspector/05f13b742837c184cd4bc741cd9a2c2494248b0c/testprojects/longclasspath/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /testprojects/longclasspath/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /testprojects/longclasspath/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /testprojects/longclasspath/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /testprojects/longclasspath/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'longclasspath' 7 | -------------------------------------------------------------------------------- /testprojects/longclasspath/src/main/java/com/example/longclasspath/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.longclasspath; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /testprojects/longclasspath/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testprojects/longclasspath/src/test/java/com/example/longclasspath/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.longclasspath; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /local 3 | **/project.repositories 4 | 5 | # Eclipse, Netbeans and IntelliJ files 6 | **/.* 7 | !.gitignore 8 | !.gitattributes 9 | **/nbproject 10 | **/*.ipr 11 | **/*.iws 12 | **/*.iml 13 | 14 | # Repository wide ignore mac DS_Store files 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.demo 5 | InsuranceDecision 6 | 1.0-SNAPSHOT 7 | kjar 8 | InsuranceDecision 9 | 10 | 11 | 7.3.1.GA-redhat-00002 12 | 13 | 14 | 15 | 16 | com.redhat.ba 17 | ba-platform-bom 18 | ${ba.version} 19 | import 20 | pom 21 | 22 | 23 | 24 | 25 | 26 | org.kie 27 | kie-internal 28 | provided 29 | 30 | 31 | org.kie 32 | kie-api 33 | provided 34 | 35 | 36 | 37 | com.thoughtworks.xstream 38 | xstream 39 | test 40 | 41 | 42 | junit 43 | junit 44 | test 45 | 46 | 47 | org.drools 48 | drools-wb-scenario-simulation-editor-api 49 | test 50 | 51 | 52 | org.drools 53 | drools-wb-scenario-simulation-editor-backend 54 | test 55 | 56 | 57 | org.drools 58 | drools-compiler 59 | test 60 | 61 | 62 | org.kie 63 | kie-dmn-feel 64 | test 65 | 66 | 67 | org.kie 68 | kie-dmn-api 69 | test 70 | 71 | 72 | org.kie 73 | kie-dmn-core 74 | test 75 | 76 | 77 | 78 | 79 | 80 | org.kie 81 | kie-maven-plugin 82 | 7.18.0.Final-redhat-00004 83 | true 84 | 85 | 86 | 87 | 88 | 89 | jboss-ga-repository 90 | https://maven.repository.redhat.com/ga/ 91 | 92 | true 93 | 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | jboss-ga-plugin-repository 102 | https://maven.repository.redhat.com/ga/ 103 | 104 | true 105 | 106 | 107 | false 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/src/main/resources/META-INF/kie-deployment-descriptor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.jbpm.domain 4 | org.jbpm.domain 5 | JPA 6 | JPA 7 | SINGLETON 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | true 18 | 19 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/src/main/resources/META-INF/kmodule.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.hibernate.jpa.HibernatePersistenceProvider 5 | java:jboss/datasources/ExampleDS 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/src/test/java/testscenario/Launch.java: -------------------------------------------------------------------------------- 1 | package testscenario; 2 | 3 | public class Launch { 4 | 5 | public static void main(String[] args) { 6 | System.out.println("Main Class in Test Folder!"); 7 | } 8 | } -------------------------------------------------------------------------------- /testprojects/resolveClasspath/insurance-decision/src/test/java/testscenario/ScenarioJunitActivatorTest.java: -------------------------------------------------------------------------------- 1 | package testscenario; 2 | /** 3 | * Do not remove this file 4 | */ 5 | @org.junit.runner.RunWith(org.drools.workbench.screens.scenariosimulation.backend.server.runner.ScenarioJunitActivator.class) 6 | public class ScenarioJunitActivatorTest { 7 | } -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /local 3 | **/project.repositories 4 | 5 | # Eclipse, Netbeans and IntelliJ files 6 | **/.* 7 | !.gitignore 8 | !.gitattributes 9 | **/nbproject 10 | **/*.ipr 11 | **/*.iws 12 | **/*.iml 13 | 14 | # Repository wide ignore mac DS_Store files 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | kie-client 5 | com.demo 6 | 1.0-SNAPSHOT 7 | 8 | 7.3.1.GA-redhat-00002 9 | UTF-8 10 | 1.8 11 | 1.8 12 | 13 | 14 | 15 | 16 | com.redhat.ba 17 | ba-platform-bom 18 | ${ba.version} 19 | pom 20 | import 21 | 22 | 23 | 24 | 25 | 26 | 27 | org.kie.server 28 | kie-server-client 29 | 30 | 31 | 32 | com.demo 33 | InsuranceDecision 34 | 1.0-SNAPSHOT 35 | 36 | 37 | org.kie 38 | kie-dmn-core 39 | 40 | 41 | org.kie 42 | kie-ci 43 | 44 | 45 | 46 | org.slf4j 47 | slf4j-api 48 | 49 | 50 | ch.qos.logback 51 | logback-classic 52 | runtime 53 | 54 | 55 | junit 56 | junit 57 | test 58 | 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 3.8.1 66 | 67 | ${maven.compiler.source} 68 | ${maven.compiler.target} 69 | 70 | 71 | 72 | 73 | org.codehaus.mojo 74 | exec-maven-plugin 75 | 1.2.1 76 | 77 | 78 | 79 | java 80 | 81 | 82 | 83 | 84 | client.EmbedMain 85 | 86 | -verbose:class 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | jboss-ga-repository 95 | https://maven.repository.redhat.com/ga/ 96 | 97 | true 98 | 99 | 100 | false 101 | 102 | 103 | 104 | 105 | 106 | jboss-ga-plugin-repository 107 | https://maven.repository.redhat.com/ga/ 108 | 109 | true 110 | 111 | 112 | false 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/src/main/java/client/EmbedMain.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import java.net.URL; 4 | import java.net.URLClassLoader; 5 | 6 | import org.kie.api.KieServices; 7 | import org.kie.api.runtime.KieContainer; 8 | import org.kie.dmn.api.core.DMNContext; 9 | import org.kie.dmn.api.core.DMNModel; 10 | import org.kie.dmn.api.core.DMNResult; 11 | import org.kie.dmn.api.core.DMNRuntime; 12 | 13 | /** 14 | * EmbedMain 15 | */ 16 | public class EmbedMain { 17 | 18 | public static void main(String[] args) { 19 | try { 20 | Class.forName("org.drools.compiler.commons.jci.readers.ResourceReader"); 21 | } catch (ClassNotFoundException e) { 22 | e.printStackTrace(); 23 | } 24 | ClassLoader cl = EmbedMain.class.getClassLoader(); 25 | 26 | URL[] urls = ((URLClassLoader) cl).getURLs(); 27 | 28 | for (URL url : urls) { 29 | System.out.println(url.getFile()); 30 | } 31 | 32 | KieServices kieServices = KieServices.Factory.get(); 33 | 34 | KieContainer kieContainer = kieServices.getKieClasspathContainer(); 35 | 36 | DMNRuntime dmnRuntime = kieContainer.newKieSession().getKieRuntime(DMNRuntime.class); 37 | 38 | DMNContext dmnContext = dmnRuntime.newContext(); 39 | 40 | dmnContext.set("PreviousIncidents", false); 41 | dmnContext.set("Age", 28); 42 | dmnContext.set("CarAge", 3); 43 | 44 | String namespace = "http://www.trisotech.com/definitions/_bb8b9304-b29f-462e-9f88-03d0d868aec5"; 45 | String modelName = "Insurance Pricing"; 46 | 47 | DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName); 48 | 49 | DMNResult dmnResult = dmnRuntime.evaluateAll(dmnModel, dmnContext); 50 | 51 | System.out.println(dmnResult); 52 | } 53 | } -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/src/main/java/client/Main.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import java.util.Map; 4 | 5 | import org.kie.dmn.api.core.DMNContext; 6 | import org.kie.dmn.api.core.DMNResult; 7 | import org.kie.server.api.model.ServiceResponse; 8 | import org.kie.server.client.DMNServicesClient; 9 | import org.kie.server.client.KieServicesClient; 10 | import org.kie.server.client.KieServicesConfiguration; 11 | import org.kie.server.client.KieServicesFactory; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class Main { 16 | 17 | final static Logger log = LoggerFactory.getLogger(Main.class); 18 | 19 | private static final String URL = "http://localhost:8080/kie-server/services/rest/server"; 20 | private static final String user = System.getProperty("username", "donato"); 21 | private static final String password = System.getProperty("password", "donato"); 22 | private static final String CONTAINER = "InsuranceDecision_1.0-SNAPSHOT"; 23 | 24 | public static void main(String[] args) { 25 | Main clientApp = new Main(); 26 | 27 | long start = System.currentTimeMillis(); 28 | 29 | clientApp.evaluateDMN(); 30 | 31 | long end = System.currentTimeMillis(); 32 | System.out.println("elapsed time: " + (end - start)); 33 | } 34 | 35 | private void evaluateDMN() { 36 | KieServicesClient client = getClient(); 37 | DMNServicesClient dmnClient = client.getServicesClient(DMNServicesClient.class); 38 | 39 | String namespace = "http://www.trisotech.com/definitions/_bb8b9304-b29f-462e-9f88-03d0d868aec5"; 40 | String modelName = "Insurance Pricing"; 41 | 42 | DMNContext dmnContext = dmnClient.newContext(); 43 | 44 | dmnContext.set("PreviousIncidents", false); 45 | dmnContext.set("Age", 28); 46 | dmnContext.set("CarAge", 3); 47 | 48 | ServiceResponse result = dmnClient.evaluateAll(CONTAINER, namespace, modelName, dmnContext); 49 | System.out.println(result); 50 | 51 | } 52 | 53 | private KieServicesClient getClient() { 54 | KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(URL, user, password); 55 | 56 | // Configuration for JMS 57 | // KieServicesConfiguration config = KieServicesFactory.newJMSConfiguration(connectionFactory, requestQueue, responseQueue, username, password) 58 | 59 | Map headers = null; 60 | config.setHeaders(headers); 61 | KieServicesClient client = KieServicesFactory.newKieServicesClient(config); 62 | 63 | return client; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | Main-Class: client.Main -------------------------------------------------------------------------------- /testprojects/resolveClasspath/kie-client/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d [%t] %-5p %m%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "lib": ["es2017", "es2018"], 5 | "module": "commonjs", 6 | "declaration": false, 7 | "sourceMap": true, 8 | "outDir": "lib", 9 | "strict": true, 10 | "moduleResolution": "node", 11 | "noImplicitAny": false, 12 | "esModuleInterop": true 13 | }, 14 | "include": ["src"] 15 | } 16 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | /** @type {import('webpack').Configuration} */ 4 | module.exports = { 5 | entry: './src/index.ts', 6 | target: 'node', 7 | mode: 'none', 8 | resolve: { 9 | mainFields: ['module', 'main'], 10 | extensions: ['.js', '.ts'] 11 | }, 12 | externals: { 13 | 'coc.nvim': 'commonjs coc.nvim' 14 | }, 15 | optimization: { 16 | minimize: false 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.ts$/, 22 | include: [path.resolve(__dirname, 'src')], 23 | use: [ 24 | { 25 | loader: 'ts-loader', 26 | options: { 27 | compilerOptions: { 28 | sourceMap: true 29 | } 30 | } 31 | } 32 | ] 33 | } 34 | ] 35 | }, 36 | output: { 37 | path: path.join(__dirname, 'lib'), 38 | filename: 'index.js', 39 | libraryTarget: 'commonjs' 40 | }, 41 | plugins: [], 42 | node: { 43 | __dirname: false, 44 | __filename: false 45 | } 46 | }; 47 | --------------------------------------------------------------------------------