diff --git a/BUILD.md b/BUILD.md index 8604f3b2..d3a1becc 100644 --- a/BUILD.md +++ b/BUILD.md @@ -121,6 +121,10 @@ This configuration will enable you to debug both the extension’s TypeScript co ```json "jdk.serverVmOptions": ["-J-Dnetbeans.logger.console=true"] ``` +4. For further debugging you can set Log Level to FINEST by appending following argument to the array: + ```json + "jdk.serverVmOptions": ["-J-Dnetbeans.logger.console=true", "-J-Dorg.netbeans.modules.java.lsp.server.lsptrace.level=FINEST"] + ``` Both options will enable logging from the NetBeans server in the VS Code Output Channel. diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index 7d24ab3b..962e2bf6 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -231,7 +231,6 @@ THIRD-PARTY COMPONENT FILE LICENSE -------------------------------------------------------------------------------- bin/nbcode.exe Apache-2.0 bin/nbcode64.exe Apache-2.0 -extide/.lastModified MIT-vscode-uri extide/ant/bin/ant Apache-2.0-ant extide/ant/bin/ant.bat Apache-2.0-ant extide/ant/bin/ant.cmd Apache-2.0-ant @@ -288,8 +287,6 @@ extide/ant/lib/ant-testutil.jar Apache-2.0 extide/ant/lib/ant-xz.jar Apache-2.0-ant extide/ant/lib/ant.jar Apache-2.0-ant extide/modules/gradle/gradle-tooling-api.jar Apache-2.0 -harness/.lastModified MIT-vscode-uri -ide/.lastModified MIT-vscode-uri ide/docs/jaxb-api-doc.jar EDL-1.0 ide/modules/com-google-gson.jar Apache-2.0 ide/modules/com-google-guava-failureaccess.jar Apache-2.0 @@ -320,10 +317,10 @@ ide/modules/ext/jaxb/activation.jar EDL-1.0 ide/modules/ext/jaxb/api/jaxb-api.jar EDL-1.0 ide/modules/ext/jaxb/jaxb-impl.jar CDDL-1.1 ide/modules/ext/jaxb/jaxb-xjc.jar CDDL-1.1-MIT-jaxb-xjc -ide/modules/ext/jcodings-1.0.18.jar MIT-nocopyright +ide/modules/ext/jcodings-1.0.58.jar MIT-nocopyright ide/modules/ext/jline-24.0.0.jar BSD-jline3 ide/modules/ext/jniutils-24.0.0.jar UPL -ide/modules/ext/joni-2.1.11.jar MIT-jruby +ide/modules/ext/joni-2.2.1.jar MIT-jruby ide/modules/ext/json-simple-1.1.1.jar Apache-2.0 ide/modules/ext/jsoup-1.15.4.jar MIT-jsoup ide/modules/ext/junixsocket-common-2.5.1.jar Apache-2.0 @@ -336,12 +333,11 @@ ide/modules/ext/org.eclipse.lsp4j.debug-0.13.0.jar EPL-v20 ide/modules/ext/org.eclipse.lsp4j.generator-0.13.0.jar EPL-v20 ide/modules/ext/org.eclipse.lsp4j.jsonrpc-0.13.0.jar EPL-v20 ide/modules/ext/org.eclipse.lsp4j.jsonrpc.debug-0.13.0.jar EPL-v20 -ide/modules/ext/org.eclipse.tm4e.core-0.4.1-pack1.jar EPL-v20 +ide/modules/ext/org.eclipse.tm4e.core-0.14.0.jar EPL-v20 ide/modules/ext/org.eclipse.xtend.lib-2.24.0.jar EPL-v20 ide/modules/ext/org.eclipse.xtend.lib.macro-2.24.0.jar EPL-v20 ide/modules/ext/org.eclipse.xtext.xbase.lib-2.24.0.jar EPL-v20 ide/modules/ext/polyglot-24.0.0.jar UPL -ide/modules/ext/processtreekiller-2.0.1.jar MIT-processtreekiller ide/modules/ext/resolver-1.2.jar Apache-2.0 ide/modules/ext/simplevalidation-swing.jar Apache-2.0 ide/modules/ext/simplevalidation.jar Apache-2.0 @@ -349,7 +345,6 @@ ide/modules/ext/toml-java-13.4.1.jar Apache-2.0 ide/modules/ext/truffle-api-24.0.0.jar UPL-MIT-jcodings ide/modules/ext/truffle-compiler-24.0.0.jar UPL-MIT-jcodings ide/modules/ext/truffle-runtime-24.0.0.jar UPL-MIT-jcodings -ide/modules/ext/winp-1.28.jar MIT-winp ide/modules/ext/word-24.0.0.jar UPL ide/modules/lib/aarch64/junixsocket-native-2.5.1.dll Apache-2.0 ide/modules/lib/aarch64/libjunixsocket-native-2.5.1.dylib Apache-2.0 @@ -364,7 +359,6 @@ ide/modules/org-eclipse-jgit-ssh-jsch.jar EDL-1.0-jg ide/modules/org-eclipse-jgit.jar EDL-1.0-jgit ide/modules/slf4j-api.jar MIT-slf4j-22 ide/modules/slf4j-jdk14.jar MIT-slf4j-22 -java/.lastModified MIT-vscode-uri java/maven/LICENSE Apache-2.0 java/maven/NOTICE Apache-2.0 java/maven/README.txt Apache-2.0 @@ -467,19 +461,19 @@ java/modules/ext/eclipselink/org.eclipse.persistence.jpa.jpql-2.7.12.jar EPL-v20 java/modules/ext/eclipselink/org.eclipse.persistence.jpa.modelgen.processor-2.7.12.jar EPL-v20 java/modules/ext/eclipselink/org.eclipse.persistence.moxy-2.7.12.jar EPL-v20 java/modules/ext/jdktools-11.0.11.jar Apache-2.0 -java/modules/ext/maven/indexer-core-7.1.4.jar Apache-2.0 +java/modules/ext/maven/indexer-core-7.1.5.jar Apache-2.0 java/modules/ext/maven/javax.annotation-api-1.3.2.jar CDDL-1.1 java/modules/ext/maven/jdom2-2.0.6.1.jar BSD-JDOM -java/modules/ext/maven/lucene-analysis-common-9.11.1.jar Apache-2.0-lucene2 -java/modules/ext/maven/lucene-backward-codecs-9.11.1.jar Apache-2.0-lucene2 -java/modules/ext/maven/lucene-core-9.11.1.jar Apache-2.0-lucene2 -java/modules/ext/maven/lucene-highlighter-9.11.1.jar Apache-2.0-lucene2 -java/modules/ext/maven/lucene-queryparser-9.11.1.jar Apache-2.0-lucene2 +java/modules/ext/maven/lucene-analysis-common-9.12.0.jar Apache-2.0-lucene2 +java/modules/ext/maven/lucene-backward-codecs-9.12.0.jar Apache-2.0-lucene2 +java/modules/ext/maven/lucene-core-9.12.0.jar Apache-2.0-lucene2 +java/modules/ext/maven/lucene-highlighter-9.12.0.jar Apache-2.0-lucene2 +java/modules/ext/maven/lucene-queryparser-9.12.0.jar Apache-2.0-lucene2 java/modules/ext/maven/maven-dependency-tree-2.2.jar Apache-2.0 -java/modules/ext/maven/search-api-7.1.4.jar Apache-2.0 -java/modules/ext/maven/search-backend-smo-7.1.4.jar Apache-2.0 -java/modules/ext/nb-javac-jdk-23-30-api.jar GPL-2-CP -java/modules/ext/nb-javac-jdk-23-30.jar GPL-2-CP +java/modules/ext/maven/search-api-7.1.5.jar Apache-2.0 +java/modules/ext/maven/search-backend-smo-7.1.5.jar Apache-2.0 +java/modules/ext/nb-javac-jdk-24-29-api.jar GPL-2-CP +java/modules/ext/nb-javac-jdk-24-29.jar GPL-2-CP java/modules/ext/org.eclipse.lsp4j-0.13.0.jar EPL-v20 java/modules/ext/org.eclipse.lsp4j.debug-0.13.0.jar EPL-v20 java/modules/ext/org.eclipse.lsp4j.generator-0.13.0.jar EPL-v20 @@ -488,11 +482,9 @@ java/modules/ext/org.eclipse.lsp4j.jsonrpc.debug-0.13.0.jar EPL-v20 java/modules/ext/org.eclipse.xtend.lib-2.24.0.jar EPL-v20 java/modules/ext/org.eclipse.xtend.lib.macro-2.24.0.jar EPL-v20 java/modules/ext/org.eclipse.xtext.xbase.lib-2.24.0.jar EPL-v20 -nb/.lastModified MIT-vscode-uri -platform/.lastModified MIT-vscode-uri -platform/core/asm-9.7.jar BSD-INRIA -platform/core/asm-commons-9.7.jar BSD-INRIA -platform/core/asm-tree-9.7.jar BSD-INRIA +platform/core/asm-9.7.1.jar BSD-INRIA +platform/core/asm-commons-9.7.1.jar BSD-INRIA +platform/core/asm-tree-9.7.1.jar BSD-INRIA platform/docs/junit-4.13.2-javadoc.jar EPL-v10 platform/docs/junit-4.13.2-sources.jar EPL-v10 platform/docs/junit-jupiter-api-5.10.3-javadoc.jar EPL-v20 @@ -507,11 +499,13 @@ platform/lib/nbexec.exe Apache-2.0 platform/lib/nbexec64.dll Apache-2.0 platform/lib/nbexec64.exe Apache-2.0 platform/modules/ext/commons-io-2.16.1.jar Apache-2.0 -platform/modules/ext/flatlaf-3.5.1.jar Apache-2.0 +platform/modules/ext/flatlaf-3.5.2.jar Apache-2.0 platform/modules/ext/hamcrest-core-1.3.jar BSD-hamcrest platform/modules/ext/jcommander-1.78.jar Apache-2.0 +platform/modules/ext/jersey2/jakarta.inject-2.6.1.jar EPL-v20 platform/modules/ext/jna-5.14.0.jar Apache-2.0 platform/modules/ext/jna-platform-5.14.0.jar Apache-2.0 +platform/modules/ext/jsvg-1.6.1.jar MIT-jsvg platform/modules/ext/junit-4.13.2.jar EPL-v10 platform/modules/ext/junit-jupiter-api-5.10.3.jar EPL-v20 platform/modules/ext/junit-jupiter-engine-5.10.3.jar EPL-v20 @@ -542,10 +536,9 @@ platform/modules/net-java-html.jar Apache-2.0 platform/modules/org-apache-commons-codec.jar Apache-2.0 platform/modules/org-apache-commons-lang3.jar Apache-2.0 platform/modules/org-apache-commons-logging.jar Apache-2.0 -platform/modules/org-netbeans-html-ko4j.jar Apache-2.0+knockout +platform/modules/org-netbeans-html-ko4j.jar Apache-2.0-ko4j platform/modules/org-netbeans-html-presenters-spi.jar Apache-2.0 platform/modules/org-netbeans-html-xhr4j.jar Apache-2.0 -webcommon/.lastModified MIT-vscode-uri webcommon/modules/ext/icu4j-24.0.0.jar MIT-icu4j-74 webcommon/modules/ext/js-language-24.0.0.jar UPL webcommon/modules/ext/js-launcher-24.0.0.jar UPL @@ -1699,29 +1692,6 @@ webcommon/libs.nashorn/test/unit/src/com/oracle/js/parser/ManualTest.java webcommon/libs.nashorn/test/unit/src/com/oracle/js/parser/ParserTest.java UPL-graaljs webcommon/typescript.editor/src/org/netbeans/modules/typescript/editor/TypeScript.tmLanguage.json MIT-vscode websvccommon/websvc.saas.api/src/org/netbeans/modules/websvc/saas/model/wadl200902.xsd CDDL-1.0 -NOTICEs for: enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-config_1_0.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-config_1_1.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-config_1_2.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-config_1_3.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-config_1_3-custom.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator-rules.xml -Apache Struts -Copyright 2000-2007 The Apache Software Foundation -NOTICEs for: enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/tiles-config_1_1.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/tiles-config_1_3.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-tiles.tld -Apache Struts Tiles -Copyright 2000-2007 The Apache Software Foundation -NOTICEs for: enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_0.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_0_1.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_1.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_1_3.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_2_0.dtd enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/validator_1_3_0.dtd -Apache Jakarta Commons Validator -Copyright 2001-2006 The Apache Software Foundation -NOTICEs for: enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-bean.tld enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-html.tld enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-logic.tld enterprise/web.struts/src/org/netbeans/modules/web/struts/resources/struts-nested.tld -Apache Struts Taglib -Copyright 2000-2007 The Apache Software Foundation -NOTICEs for: ide/hudson.ui/src/org/netbeans/modules/hudson/ui/resources/instance.png -Original image from the Jenkins project (https://jenkins.io/): -https://github.com/jenkins-infra/jenkins.io/blob/master/content/images/logos/jenkins/jenkins.svg -(placed on square background, rendered to 16x16px with inkscape) -NOTICEs for: java/kotlin.editor/src/org/netbeans/modules/kotlin/editor/kotlin_file.svg java/kotlin.editor/src/org/netbeans/modules/kotlin/editor/kotlin_file.png java/kotlin.editor/src/org/netbeans/modules/kotlin/editor/kotlin_file@2x.png -Kotlin Compiler -Copyright 2010-2019 JetBrains s.r.o and respective authors and developers -NOTICEs for: platform/o.n.swing.plaf/src/org/netbeans/swing/plaf/util/SmoothScrollPaneUI.java -This software includes code from IntelliJ IDEA Community Edition -Copyright (C) JetBrains s.r.o. -https://www.jetbrains.com/idea/ Notes ----- @@ -1879,7 +1849,7 @@ META-INF/NOTICE in archive lib/guice-5.1.0.jar Google Guice - Core Library Copyright 2006-2022 Google, Inc. -META-INF/NOTICE in archive lib/plexus-utils-3.2.1.jar +META-INF/NOTICE in archive lib/plexus-utils-3.5.1.jar and lib/plexus-xml-3.0.0.jar This product includes software developed by the Indiana University Extreme! Lab (http://www.extreme.indiana.edu/). This product includes software developed by @@ -1889,7 +1859,7 @@ javolution (http://javolution.org/). This product includes software developed by Rome (https://rome.dev.java.net/). -about.html in archive lib/org.eclipse.sisu.inject-0.9.0.M2.jar +about.html in archive lib/org.eclipse.sisu.inject-0.9.0.M3.jar @@ -2440,240 +2410,6 @@ Parts of this work are licensed: -=== -====== -========================= Apache-2.0+knockout ========================= - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -This product bundles Knockout JavaScript library v3.5.0, -which is available under a MIT license: - -The MIT License (MIT) - http://www.opensource.org/licenses/mit-license.php - -Copyright (c) Steven Sanderson, the Knockout.js team, and other contributors -http://knockoutjs.com/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - === ====== ========================= Apache-2.0-ant ========================= @@ -2892,86 +2628,314 @@ Foundation. * limitations under the License. */ -W3C� SOFTWARE NOTICE AND LICENSE -https://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 +W3C� SOFTWARE NOTICE AND LICENSE +https://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) agree +that you have read, understood, and will comply with the following terms and +conditions. + +Permission to copy, modify, and distribute this software and its documentation, +with or without modification, for any purpose and without fee or royalty is +hereby granted, provided that you include the following on ALL copies of the +software and documentation or portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + 2. Any pre-existing intellectual property disclaimers, notices, or terms + and conditions. If none exist, the W3C Software Short Notice should be + included (hypertext is preferred, text is permitted) within the body + of any redistributed or derivative code. + 3. Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE +NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT +THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY +PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. + +The name and trademarks of copyright holders may NOT be used in advertising or +publicity pertaining to the software without specific, written prior permission. +Title to copyright in this software and any associated documentation will at +all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 2002. +This version removes the copyright ownership notice such that this license can +be used with materials other than those owned by the W3C, reflects that ERCIM +is now a host of the W3C, includes references to this specific dated version of +the license, and removes the ambiguous grant of "use". Otherwise, this version +is the same as the previous version and is written so as to preserve the Free +Software Foundation's assessment of GPL compatibility and OSI's certification +under the Open Source Definition. Please see our Copyright FAQ for common +questions about using materials from our site, including specific terms and +conditions for packages like libwww, Amaya, and Jigsaw. Other questions about +this notice can be directed to site-policy@w3.org. + +Joseph Reagle + +This license came from: http://www.megginson.com/SAX/copying.html + However please note future versions of SAX may be covered + under http://saxproject.org/?selected=pd + +SAX2 is Free! + +I hereby abandon any property rights to SAX 2.0 (the Simple API for +XML), and release all of the SAX 2.0 source code, compiled code, and +documentation contained in this distribution into the Public Domain. +SAX comes with NO WARRANTY or guarantee of fitness for any +purpose. + +David Megginson, david@megginson.com +2000-05-05 + + +=== +====== +========================= Apache-2.0-freemarker ========================= + +====== The following are the NOTICEs pertaining to components using this license. For the full license text, please see the license text below the NOTICEs +Apache FreeMarker +Copyright 2015-2018 The Apache Software Foundation + + +====== license text follows + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -This work (and included software, documentation such as READMEs, or other -related items) is being provided by the copyright holders under the following -license. By obtaining, using and/or copying this work, you (the licensee) agree -that you have read, understood, and will comply with the following terms and -conditions. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -Permission to copy, modify, and distribute this software and its documentation, -with or without modification, for any purpose and without fee or royalty is -hereby granted, provided that you include the following on ALL copies of the -software and documentation or portions thereof, including modifications: + END OF TERMS AND CONDITIONS - 1. The full text of this NOTICE in a location viewable to users of the - redistributed or derivative work. - 2. Any pre-existing intellectual property disclaimers, notices, or terms - and conditions. If none exist, the W3C Software Short Notice should be - included (hypertext is preferred, text is permitted) within the body - of any redistributed or derivative code. - 3. Notice of any changes or modifications to the files, including the date - changes were made. (We recommend you provide URIs to the location from - which the code is derived.) - -THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE -NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT -THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY -PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + APPENDIX: How to apply the Apache License to your work. -COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -The name and trademarks of copyright holders may NOT be used in advertising or -publicity pertaining to the software without specific, written prior permission. -Title to copyright in this software and any associated documentation will at -all times remain with copyright holders. + Copyright [yyyy] [name of copyright owner] -____________________________________ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -This formulation of W3C's notice and license became active on December 31 2002. -This version removes the copyright ownership notice such that this license can -be used with materials other than those owned by the W3C, reflects that ERCIM -is now a host of the W3C, includes references to this specific dated version of -the license, and removes the ambiguous grant of "use". Otherwise, this version -is the same as the previous version and is written so as to preserve the Free -Software Foundation's assessment of GPL compatibility and OSI's certification -under the Open Source Definition. Please see our Copyright FAQ for common -questions about using materials from our site, including specific terms and -conditions for packages like libwww, Amaya, and Jigsaw. Other questions about -this notice can be directed to site-policy@w3.org. - -Joseph Reagle + http://www.apache.org/licenses/LICENSE-2.0 -This license came from: http://www.megginson.com/SAX/copying.html - However please note future versions of SAX may be covered - under http://saxproject.org/?selected=pd + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -SAX2 is Free! +========================================================================= -I hereby abandon any property rights to SAX 2.0 (the Simple API for -XML), and release all of the SAX 2.0 source code, compiled code, and -documentation contained in this distribution into the Public Domain. -SAX comes with NO WARRANTY or guarantee of fitness for any -purpose. +The source code contains the following binaries, +which were created at the Apache FreeMarker project, and hence are +covered by the same license as the other source files of it: -David Megginson, david@megginson.com -2000-05-05 + src/main/misc/overloadedNumberRules/prices.ods + src/manual/en_US/docgen-originals/figures/overview.odg + src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png + src/manual/en_US/docgen-originals/figures/tree_with_alpha.png + src/manual/en_US/favicon.png + src/manual/en_US/figures/model2sketch.png + src/manual/en_US/figures/overview.png + src/manual/en_US/figures/tree.png + src/manual/en_US/logo.png + src/manual/zh_CN/favicon.png + src/manual/zh_CN/figures/model2sketch.png + src/manual/zh_CN/figures/overview.png + src/manual/zh_CN/figures/tree.png + src/manual/zh_CN/logo.png === ====== -========================= Apache-2.0-freemarker ========================= - -====== The following are the NOTICEs pertaining to components using this license. For the full license text, please see the license text below the NOTICEs -Apache FreeMarker -Copyright 2015-2018 The Apache Software Foundation - - -====== license text follows +========================= Apache-2.0-ko4j ========================= Apache License Version 2.0, January 2004 @@ -3175,32 +3139,37 @@ Copyright 2015-2018 The Apache Software Foundation See the License for the specific language governing permissions and limitations under the License. -========================================================================= -The source code contains the following binaries, -which were created at the Apache FreeMarker project, and hence are -covered by the same license as the other source files of it: +This product bundles Knockout JavaScript library v3.5.0, +which is available under a MIT license: - src/main/misc/overloadedNumberRules/prices.ods - src/manual/en_US/docgen-originals/figures/overview.odg - src/manual/en_US/docgen-originals/figures/model2sketch_with_alpha.png - src/manual/en_US/docgen-originals/figures/tree_with_alpha.png - src/manual/en_US/favicon.png - src/manual/en_US/figures/model2sketch.png - src/manual/en_US/figures/overview.png - src/manual/en_US/figures/tree.png - src/manual/en_US/logo.png - src/manual/zh_CN/favicon.png - src/manual/zh_CN/figures/model2sketch.png - src/manual/zh_CN/figures/overview.png - src/manual/zh_CN/figures/tree.png - src/manual/zh_CN/logo.png +The MIT License (MIT) - http://www.opensource.org/licenses/mit-license.php + +Copyright (c) Steven Sanderson, the Knockout.js team, and other contributors +http://knockoutjs.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. === ====== ========================= Apache-2.0-lucene ========================= - ====== The following are the NOTICEs pertaining to components using this license. For the full license text, please see the license text below the NOTICEs Apache Lucene Copyright 2012 The Apache Software Foundation @@ -7930,6 +7899,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +=== +====== +========================= MIT-jsvg ========================= + +MIT License + +Copyright (c) 2021-2024 Jannis Weis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + === ====== ========================= MIT-markdown ========================= @@ -8007,33 +8003,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -=== -====== -========================= MIT-processtreekiller ========================= - -The MIT License - -Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - === ====== ========================= MIT-requirejs ========================= @@ -8144,48 +8113,6 @@ IN THE SOFTWARE. -=== -====== -========================= MIT-vscode-uri ========================= - -The MIT License (MIT) - -Copyright (c) Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -=== -====== -========================= MIT-winp ========================= - -MIT License - -Copyright (c) 2008-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - === ====== ========================= Maven-EPL-v10 ========================= diff --git a/build.xml b/build.xml index c78b6eb1..3067cd1f 100644 --- a/build.xml +++ b/build.xml @@ -45,21 +45,7 @@ patches/6330.diff - patches/7491.diff patches/7610.diff - patches/7641.diff - patches/7654.diff - patches/7670.diff - patches/7699.diff - patches/7709.diff - patches/7722.diff - patches/7724.diff - patches/7733.diff - patches/7750.diff - patches/7910.diff - patches/7921.diff - patches/7923.diff - patches/7926.diff patches/8036-draft.diff patches/8038-draft.diff patches/mvn-sh.diff @@ -69,7 +55,6 @@ patches/remove-db.diff patches/nbjavac-not-required.diff patches/l10n-licence.diff - patches/no-security-manager-allow.diff patches/dev-dependency-licenses.diff diff --git a/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspApplyEditsImplementation.java b/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspApplyEditsImplementation.java new file mode 100644 index 00000000..fb8a1751 --- /dev/null +++ b/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspApplyEditsImplementation.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.nbcode.integration; + +import org.netbeans.modules.java.lsp.server.ui.AbstractApplyEditsImplementation; +import org.netbeans.spi.lsp.ApplyEditsImplementation; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author sdedic + */ +@ServiceProvider(service = ApplyEditsImplementation.class, position = 10000) +public class LspApplyEditsImplementation extends AbstractApplyEditsImplementation{ + +} \ No newline at end of file diff --git a/nbcode/nbproject/platform.properties b/nbcode/nbproject/platform.properties index 62cd3983..cf3ca564 100644 --- a/nbcode/nbproject/platform.properties +++ b/nbcode/nbproject/platform.properties @@ -394,7 +394,6 @@ disabled.modules=\ org.netbeans.modules.j2ee.sun.dd,\ org.netbeans.modules.j2ee.sun.ddui,\ org.netbeans.modules.jakarta.transformer,\ - org.netbeans.modules.jakarta.web.beans,\ org.netbeans.modules.jakartaee8.api,\ org.netbeans.modules.jakartaee8.platform,\ org.netbeans.modules.javaee7.api,\ diff --git a/netbeans b/netbeans index 2985f1fa..0f82d968 160000 --- a/netbeans +++ b/netbeans @@ -1 +1 @@ -Subproject commit 2985f1fa57ce0c1877bad0f86d5e5504d65f9286 +Subproject commit 0f82d968998b78ef4d323537d1149eb68e747d9a diff --git a/patches/6330.diff b/patches/6330.diff index dc9b931d..21b544c9 100644 --- a/patches/6330.diff +++ b/patches/6330.diff @@ -1,5 +1,5 @@ diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ConnectionSpec.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ConnectionSpec.java -index 9ab389564c..9b7c044c81 100644 +index bb8a4e8183..b9662fe6cd 100644 --- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ConnectionSpec.java +++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/ConnectionSpec.java @@ -25,7 +25,7 @@ import java.io.OutputStream; @@ -86,11 +86,10 @@ index 9ab389564c..9b7c044c81 100644 } catch (IOException ex) { if (isClosed(server)) { break; -@@ -129,26 +152,54 @@ final class ConnectionSpec implements Closeable { - } +@@ -130,25 +153,53 @@ final class ConnectionSpec implements Closeable { }; listeningThread.start(); -- out.write((prefix + " listening at port " + localPort).getBytes()); + out.write((prefix + " listening at port " + localPort + "\n").getBytes()); + StringBuilder message = new StringBuilder(); + message.append(prefix).append(" listening at port ").append(localPort); + if (hash) { @@ -128,7 +127,6 @@ index 9ab389564c..9b7c044c81 100644 + if (hashContent != null) { + for (char c : hashContent) { + byte b = (byte) in.read(); -+ + if (b != c) { + IOException toThrow = new IOException("Hash validation failed!"); + try { @@ -146,10 +144,10 @@ index 9ab389564c..9b7c044c81 100644 connectionObject.getRunningFuture().get(); } catch (IOException | InterruptedException | ExecutionException ex) { diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ConnectionSpecTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ConnectionSpecTest.java -index 1035cf9bc8..55c0488d03 100644 +index f538c953f6..728228c63c 100644 --- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ConnectionSpecTest.java +++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/ConnectionSpecTest.java -@@ -118,7 +118,7 @@ public class ConnectionSpecTest { +@@ -118,10 +118,12 @@ public class ConnectionSpecTest { ByteArrayInputStream in = new ByteArrayInputStream(bytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); conn.prepare("Pipe server", in, os, new LspSession(), ConnectionSpecTest::setCopy, ConnectionSpecTest::copy); @@ -157,4 +155,10 @@ index 1035cf9bc8..55c0488d03 100644 + String reply = os.toString("UTF-8").replaceAll("\n$", ""); String exp = "Pipe server listening at port "; assertTrue(reply, reply.startsWith(exp)); - int port = Integer.parseInt(reply.substring(exp.length())); +- int port = Integer.parseInt(reply.substring(exp.length(), reply.indexOf('\n', exp.length()))); ++ int nextLineIdx = reply.indexOf('\n', exp.length()); ++ if (nextLineIdx < 0) nextLineIdx = reply.length(); ++ int port = Integer.parseInt(reply.substring(exp.length(), nextLineIdx)); + assertTrue("port is specified: " + port, port >= 1024); + try (ConnectionSpec second = ConnectionSpec.parse("connect:" + port)) { + second.prepare("Pipe client", in, os, new LspSession(), ConnectionSpecTest::setCopy, ConnectionSpecTest::copy); diff --git a/patches/7491.diff b/patches/7491.diff deleted file mode 100644 index a0a90593..00000000 --- a/patches/7491.diff +++ /dev/null @@ -1,1907 +0,0 @@ -diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -index 78fdd4caa30d..95ae5235c67a 100644 ---- a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -+++ b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -@@ -176,6 +176,7 @@ TokenSequence nextNonWhitespaceToken(TokenSequence ts) - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - default: - return ts; -@@ -206,6 +207,7 @@ TokenSequence previousNonWhitespaceToken(TokenSequence - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - default: - return ts; -@@ -427,6 +429,7 @@ private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - case ARROW: - scope = controller.getTrees().getScope(blockPath); -@@ -456,6 +459,7 @@ private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - case ARROW: - return new Env(offset, prefix, controller, path, sourcePositions, scope); -diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java -index 9ec7273f86f6..be001bce2358 100644 ---- a/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java -+++ b/java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java -@@ -1608,6 +1608,7 @@ private void insideMemberSelect(Env env) throws IOException { - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - default: - lastNonWhitespaceTokenId = ts.token().id(); -diff --git a/java/java.editor.base/nbproject/project.properties b/java/java.editor.base/nbproject/project.properties -index 1f620a92a638..808db111121e 100644 ---- a/java/java.editor.base/nbproject/project.properties -+++ b/java/java.editor.base/nbproject/project.properties -@@ -16,7 +16,7 @@ - # under the License. - spec.version.base=2.90.0 - is.autoload=true --javac.source=1.8 -+javac.release=17 - javac.compilerargs=-Xlint -Xlint:-serial - - test.config.semantic.includes=\ -diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtils.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtils.java -index a0682653d7f6..0bf0f69914db 100644 ---- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtils.java -+++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtils.java -@@ -51,7 +51,7 @@ - */ - public final class JavadocCompletionUtils { - -- static final Pattern JAVADOC_LINE_BREAK = Pattern.compile("\\n[ \\t]*\\**[ \\t]*\\z"); // NOI18N -+ static final Pattern JAVADOC_LINE_BREAK = Pattern.compile("(\\n[ \\t]*\\**[ \\t]*\\z)|(\\n[ \\t]*///[ \\t]*\\z)"); // NOI18N - static final Pattern JAVADOC_WHITE_SPACE = Pattern.compile("[^ \\t]"); // NOI18N - /** - * javadoc parser considers whatever number of spaces or standalone newline -@@ -62,7 +62,7 @@ public final class JavadocCompletionUtils { - static final Pattern JAVADOC_EMPTY = Pattern.compile("(\\s*\\**\\s*\n)*\\s*\\**\\s*\\**"); // NOI18N - static final Pattern JAVADOC_FIRST_WHITE_SPACE = Pattern.compile("[ \\t]*\\**[ \\t]*"); // NOI18N - private static Set IGNORE_TOKES = EnumSet.of( -- JavaTokenId.WHITESPACE, JavaTokenId.BLOCK_COMMENT, JavaTokenId.LINE_COMMENT); -+ JavaTokenId.WHITESPACE, JavaTokenId.BLOCK_COMMENT, JavaTokenId.LINE_COMMENT, JavaTokenId.JAVADOC_COMMENT_LINE_RUN); - private static final Logger LOGGER = Logger.getLogger(JavadocCompletionUtils.class.getName()); - - /** -@@ -196,6 +196,7 @@ public static TokenSequence findJavadocTokenSequence(Compilation - break; - } - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - if (token.partType() == PartType.COMPLETE) { - return javac.getElements().getDocComment(e) == null - ? null : s.embedded(JavadocTokenId.language()); -@@ -246,36 +247,39 @@ static boolean isInsideIndent(Token token, int offset) { - - /** - * Is javadoc line break? -- * @param token token to test -+ * @param ts a token sequence positioned to the token to test - * @return {@code true} in case the token is something like {@code "\n\t*"} - */ -- public static boolean isLineBreak(Token token) { -- return isLineBreak(token, token.length()); -+ public static boolean isLineBreak(TokenSequence ts) { -+ return isLineBreak(ts, ts.token().length()); - } - - /** - * Tests if the token part before {@code pos} is a javadoc line break. -- * @param token a token to test -+ * @param ts a token sequence positioned to the token to test - * @param pos position in the token - * @return {@code true} in case the token is something like {@code "\n\t* |\n\t*"} - */ -- public static boolean isLineBreak(Token token, int pos) { -+ public static boolean isLineBreak(TokenSequence ts, int pos) { -+ Token token = ts.token(); -+ - if (token == null || token.id() != JavadocTokenId.OTHER_TEXT) { -- return false; -+ return ts.isEmpty() || ts.index() == 0; - } - try { - CharSequence text = token.text(); - if (pos < token.length()) - text = text.subSequence(0, pos); -- boolean result = pos > 0 -+ boolean result = (pos > 0 - && JAVADOC_LINE_BREAK.matcher(text).find() -- && (pos == token.length() || !isInsideIndent(token, pos)); -+ && (pos == token.length() || !isInsideIndent(token, pos)) -+ ); - return result; - } catch (IndexOutOfBoundsException e) { - throw (IndexOutOfBoundsException) new IndexOutOfBoundsException("pos: " + pos + ", token.length: " + token.length() + ", token text: " + token.text()).initCause(e); - } - } -- -+ - public static boolean isWhiteSpace(CharSequence text) { - return text != null && text.length() > 0 && !JAVADOC_WHITE_SPACE.matcher(text).find(); - } -@@ -437,7 +441,8 @@ private static boolean movedToJavadocToken(TokenSequence ts, int of - return false; - } - -- if (ts.token().id() != JavaTokenId.JAVADOC_COMMENT) { -+ if (ts.token().id() != JavaTokenId.JAVADOC_COMMENT && -+ ts.token().id() != JavaTokenId.JAVADOC_COMMENT_LINE_RUN) { - return false; - } - -@@ -456,6 +461,11 @@ private static boolean isEmptyJavadoc(Token token, int offset) { - // check special case /**|*/ - return offset == 3 && "/***/".contentEquals(text); //NOI18N - } -+ if (token != null && token.id() == JavaTokenId.JAVADOC_COMMENT_LINE_RUN) { -+ CharSequence text = token.text(); -+ // check special case ///|\n -+ return offset == 3 && "///\n".contentEquals(text); //NOI18N -+ } - return false; - } - -diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImports.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImports.java -index 07ccd639c0e0..2d91d7065f64 100644 ---- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImports.java -+++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImports.java -@@ -641,7 +641,7 @@ public static boolean isInsideReference(TokenSequence jdts, int - } - case OTHER_TEXT: - isBeforeWS |= JavadocCompletionUtils.isWhiteSpace(jdt); -- isBeforeWS |= JavadocCompletionUtils.isLineBreak(jdt); -+ isBeforeWS |= JavadocCompletionUtils.isLineBreak(jdts); - if (isBeforeWS) { - continue; - } else { -@@ -690,7 +690,9 @@ private static TokenSequence getJavadocTS(CompilationInfo javac, - TokenSequence javadoc = null; - TokenSequence ts = SourceUtils.getJavaTokenSequence(javac.getTokenHierarchy(), start); - -- if (ts.moveNext() && ts.token().id() == JavaTokenId.JAVADOC_COMMENT) { -+ if (ts.moveNext() && -+ (ts.token().id() == JavaTokenId.JAVADOC_COMMENT || -+ ts.token().id() == JavaTokenId.JAVADOC_COMMENT_LINE_RUN)) { - javadoc = ts.embedded(JavadocTokenId.language()); - } - -@@ -893,14 +895,14 @@ private static void insideTag(DocTreePath tag, JavadocContext jdctx, int caretOf - cs = pos < cs.length() ? cs.subSequence(0, pos) : cs; - - if (JavadocCompletionUtils.isWhiteSpace(cs) -- || JavadocCompletionUtils.isLineBreak(jdts.token(), pos)) { -+ || JavadocCompletionUtils.isLineBreak(jdts, pos)) { - noPrefix = true; - } else { - // broken syntax - return; - } - } else if (!(JavadocCompletionUtils.isWhiteSpace(jdts.token()) -- || JavadocCompletionUtils.isLineBreak(jdts.token()))) { -+ || JavadocCompletionUtils.isLineBreak(jdts))) { - // not java reference - return; - } else if (jdts.moveNext()) { -diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtilsTest.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtilsTest.java -index add1ca7dc20d..33926dc0b405 100644 ---- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtilsTest.java -+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocCompletionUtilsTest.java -@@ -270,32 +270,32 @@ public void testIsLineBreak() throws Exception { - TokenSequence jdts = JavadocCompletionUtils.findJavadocTokenSequence(info, offset); - assertTrue(jdts.moveNext()); - assertTrue(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token())); -+ JavadocCompletionUtils.isLineBreak(jdts)); - offset += 1; - jdts = JavadocCompletionUtils.findJavadocTokenSequence(info, offset); - assertTrue(jdts.moveNext()); - // token is INDENT - assertFalse(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token())); -+ JavadocCompletionUtils.isLineBreak(jdts)); - - what = " \n"; - offset = code.indexOf(what); - jdts = JavadocCompletionUtils.findJavadocTokenSequence(info, offset); - assertTrue(jdts.moveNext()); - assertTrue(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token(), offset - jdts.offset())); -+ JavadocCompletionUtils.isLineBreak(jdts, offset - jdts.offset())); - - what = " * {*i"; - offset = code.indexOf(what) + what.length() - 3; - jdts = JavadocCompletionUtils.findJavadocTokenSequence(info, offset); - assertTrue(jdts.moveNext()); - assertFalse(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token())); -+ JavadocCompletionUtils.isLineBreak(jdts)); - assertTrue(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token(), offset - jdts.offset())); -+ JavadocCompletionUtils.isLineBreak(jdts, offset - jdts.offset())); - offset = code.indexOf(what); - assertFalse(insertPointer(code, offset), -- JavadocCompletionUtils.isLineBreak(jdts.token(), offset - jdts.offset())); -+ JavadocCompletionUtils.isLineBreak(jdts, offset - jdts.offset())); - } - - public void testIsLineBreak2() throws Exception { -@@ -319,10 +319,10 @@ public void testIsLineBreak2() throws Exception { - assertTrue(jdts.moveNext()); - assertTrue(jdts.token().id() == JavadocTokenId.OTHER_TEXT); - assertFalse(insertPointer(code, jdts.offset() + jdts.token().length()), -- JavadocCompletionUtils.isLineBreak(jdts.token())); -+ JavadocCompletionUtils.isLineBreak(jdts)); - // test OTHER_TEXT(' * |{') - assertTrue(insertPointer(code, jdts.offset() + jdts.token().length() - 1), -- JavadocCompletionUtils.isLineBreak(jdts.token(), jdts.token().length() - 1)); -+ JavadocCompletionUtils.isLineBreak(jdts, jdts.token().length() - 1)); - } - - public void testIsWhiteSpace() throws Exception { -diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImportsTest.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImportsTest.java -index e64ec4698b52..a880930c5850 100644 ---- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImportsTest.java -+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocImportsTest.java -@@ -207,6 +207,124 @@ public void testComputeReferencedElements() throws Exception { - assertEquals(exp, sortedResult); - } - -+ public void testComputeReferencedElementsMarkdown() throws Exception { -+ String code = -+ """ -+ package p; -+ import java.io.IOException; -+ import java.util.Collections; -+ import java.util.List; -+ class C { -+ ///link1 {@link Runnable} -+ ///link3 {@linkplain Collections#binarySearch(java.util.List, Object) search} -+ ///{@link java. uncomplete reference} -+ ///unclosed link {@value Math#PI} -+ ///@see List -+ ///@throws IOException -+ void m() throws java.io.IOException { -+ } -+ /// -+ ///{@link Collections} -+ /// -+ int field; -+ /// {@link IOException -+ interface InnerInterface {} -+ /// {@link Collections} -+ @interface InnerAnnotationType {} -+ } -+ /// {@link Collections} -+ enum TopLevelEnum { -+ /** {@link Collections} */ E1 -+ } -+ """; -+ //TODO: does not work: -+ //unclosed link {@value Math#PI\n -+ prepareTest(code); -+ -+ // C.m() -+ TreePath member = findPath(code, "m() throws"); -+ assertNotNull(member); -+ List exp = Arrays.asList( -+ info.getElements().getTypeElement("java.lang.Runnable"), -+ info.getElements().getTypeElement("java.lang.Math"), -+ info.getElements().getTypeElement("java.lang.Object"), -+ info.getElements().getTypeElement("java.util.Collections"), -+ info.getElements().getTypeElement("java.util.List"), -+ info.getElements().getTypeElement("java.io.IOException") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ Set result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ List sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ -+ // C.field -+ member = findPath(code, "field;"); -+ assertNotNull(member); -+ exp = Arrays.asList( -+ info.getElements().getTypeElement("java.util.Collections") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ -+ // C.InnerInterface -+ member = findPath(code, "InnerInterface {"); -+ assertNotNull(member); -+ exp = Arrays.asList( -+ info.getElements().getTypeElement("java.io.IOException") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ -+ // C.InnerAnnotationType -+ member = findPath(code, "InnerAnnotationType {"); -+ assertNotNull(member); -+ exp = Arrays.asList( -+ info.getElements().getTypeElement("java.util.Collections") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ -+ // TopLevelEnum -+ member = findPath(code, "TopLevelEnum {"); -+ assertNotNull(member); -+ exp = Arrays.asList( -+ info.getElements().getTypeElement("java.util.Collections") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ -+ // TopLevelEnum.E1 -+ member = findPath(code, "E1\n"); -+ assertNotNull(member); -+ exp = Arrays.asList( -+ info.getElements().getTypeElement("java.util.Collections") -+ ); -+ Collections.sort(exp, new ElementComparator()); -+ result = JavadocImports.computeReferencedElements(info, member); -+ assertNotNull(result); -+ sortedResult = new ArrayList(result); -+ sortedResult.sort(new ElementComparator()); -+ assertEquals(exp, sortedResult); -+ } -+ - public void testComputeTokensOfReferencedElements() throws Exception { - String code = - "package p;\n" + -@@ -286,6 +404,87 @@ public void testComputeTokensOfReferencedElements() throws Exception { - // assertEquals(toFind.toString(), exp, tokens); - } - -+ public void testComputeTokensOfReferencedElementsMarkdown() throws Exception { -+ String code = -+ """ -+ package p; -+ import java.util.Collections; -+ class C { -+ ///link1 {@link Runnable} -+ ///link2 {@link Collections#binarySearch(java.util.List, java.lang.Object) search} -+ ///{@link java. uncomplete reference} ///unclosed link {@value Math#PI} -+ ///@see java.util.Collections -+ ///@throws ThrowsUnresolved -+ /// -+ void m() throws java.io.IOException { -+ Collections.binarySearch(Collections.emptyList(), ""); -+ double pi = Math.PI; -+ } -+ } -+ """; -+ //TODO: does not work: -+ //unclosed link {@value Math#PI\n -+ prepareTest(code); -+ -+ TreePath where = findPath(code, "m() throws"); -+ assertNotNull(where); -+ TokenSequence jdts = JavadocCompletionUtils.findJavadocTokenSequence(info, null, info.getTrees().getElement(where)); -+ assertNotNull(jdts); -+ List exp; -+ -+ // toFind java.lang.Runnable -+ Element toFind = info.getElements().getTypeElement("java.lang.Runnable"); -+ assertNotNull(toFind); -+ List tokens = JavadocImports.computeTokensOfReferencedElements(info, where, toFind); -+ assertNotNull(toFind.toString(), tokens); -+ jdts.move(code.indexOf("Runnable", code.indexOf("link1"))); -+ assertTrue(jdts.moveNext()); -+ exp = Arrays.asList(jdts.token()); -+ assertEquals(toFind.toString(), exp, tokens); -+ -+ // toFind java.util.Collections -+ toFind = info.getElements().getTypeElement("java.util.Collections"); -+ assertNotNull(toFind); -+ tokens = JavadocImports.computeTokensOfReferencedElements(info, where, toFind); -+ assertNotNull(toFind.toString(), tokens); -+ exp = new ArrayList(); -+ jdts.move(code.indexOf("Collections", code.indexOf("link2"))); -+ assertTrue(jdts.moveNext()); -+ exp.add(jdts.token()); -+ jdts.move(code.indexOf("Collections", code.indexOf("///@see"))); -+ assertTrue(jdts.moveNext()); -+ exp.add(jdts.token()); -+ System.err.println("exp:"); -+ for (Token e : exp) { -+ System.err.println(e.text()); -+ } -+ System.err.println("tokens:"); -+ for (Token e : tokens) { -+ System.err.println(e.text()); -+ } -+ assertEquals(toFind.toString(), exp, tokens); -+ -+ // toFind Math#PI -+ toFind = findElement(code, "PI;\n"); -+ assertNotNull(toFind); -+ tokens = JavadocImports.computeTokensOfReferencedElements(info, where, toFind); -+ assertNotNull(toFind.toString(), tokens); -+ jdts.move(code.indexOf("PI", code.indexOf("unclosed link"))); -+ assertTrue(jdts.moveNext()); -+ exp = Arrays.asList(jdts.token()); -+ assertEquals(toFind.toString(), exp, tokens); -+ -+ // toFind Collections#binarySearch -+ toFind = findElement(code, "binarySearch(Collections.emptyList()"); -+ assertNotNull(toFind); -+ tokens = JavadocImports.computeTokensOfReferencedElements(info, where, toFind); -+ assertNotNull(toFind.toString(), tokens); -+ jdts.move(code.indexOf("binarySearch", code.indexOf("link2"))); -+ assertTrue(jdts.moveNext()); -+ exp = Arrays.asList(jdts.token()); -+// assertEquals(toFind.toString(), exp, tokens); -+ } -+ - public void testComputeTokensOfReferencedElementsForParams() throws Exception { - String code = - "package p;\n" + -diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocTestSupport.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocTestSupport.java -index 7c153124956a..8770a3906721 100644 ---- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocTestSupport.java -+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/javadoc/JavadocTestSupport.java -@@ -20,7 +20,9 @@ - package org.netbeans.modules.java.editor.base.javadoc; - - import java.io.File; -+import java.util.ArrayList; - import java.util.Enumeration; -+import java.util.List; - import javax.swing.text.StyledDocument; - import org.netbeans.api.editor.mimelookup.MimePath; - import org.netbeans.api.editor.mimelookup.test.MockMimeLookup; -@@ -62,10 +64,10 @@ protected void setUp() throws Exception { - super.setUp(); - - MockMimeLookup.setInstances(MimePath.parse("text/x-java"), new JavaKit()); -- SourceUtilsTestUtil.prepareTest(new String[0], new Object[] { -- new Pool(), -- new MockMimeLookup(), -- }); -+ List services = new ArrayList<>(); -+ services.add(new Pool()); -+ services.add(new MockMimeLookup()); -+ SourceUtilsTestUtil.prepareTest(new String[0], services.toArray()); - FileUtil.setMIMEType("java", "text/x-java"); - - if (cache == null) { -@@ -115,7 +117,11 @@ protected void prepareTest(String code) throws Exception { - assertNotNull(info); - assertTrue(info.getDiagnostics().toString(), info.getDiagnostics().isEmpty()); - } -- -+ -+ protected Object[] additionalServices() { -+ return new Object[0]; -+ } -+ - /** - * Inserts a marker '|' to string {@code s} on position {@code pos}. Useful - * for assert's debug messages -diff --git a/java/java.editor/nbproject/project.properties b/java/java.editor/nbproject/project.properties -index 914e09646b80..9c667f21de38 100644 ---- a/java/java.editor/nbproject/project.properties -+++ b/java/java.editor/nbproject/project.properties -@@ -19,7 +19,7 @@ javadoc.title=Java Editor - - spec.version.base=2.93.0 - test.qa-functional.cp.extra=${editor.dir}/modules/org-netbeans-modules-editor-fold.jar --javac.source=1.8 -+javac.release=17 - #test.unit.cp.extra= - #test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:${o.n.core.dir}/lib/boot.jar:${libs.xerces.dir}/modules/ext/xerces-2.6.2.jar:${libs.xerces.dir}/modules/ext/xml-commons-dom-ranges-1.0.b2.jar:${retouche/javacimpl.dir}/modules/ext/javac-impl.jar - -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java b/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java -index 8a60126a7266..3e8b08e4e7a2 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/GoToSupport.java -@@ -408,7 +408,7 @@ public static Context resolveContext(CompilationInfo controller, Document doc, i - boolean insideImportStmt = false; - TreePath path = controller.getTreeUtilities().pathFor(exactOffset); - -- if (token[0] != null && token[0].id() == JavaTokenId.JAVADOC_COMMENT) { -+ if (token[0] != null && (token[0].id() == JavaTokenId.JAVADOC_COMMENT || token[0].id() == JavaTokenId.JAVADOC_COMMENT_LINE_RUN)) { - el = JavadocImports.findReferencedElement(controller, offset); - } else { - path = adjustPathForModuleName(path); -@@ -662,7 +662,7 @@ public void run() { - - Token t = ts.token(); - -- if (JavaTokenId.JAVADOC_COMMENT == t.id()) { -+ if (JavaTokenId.JAVADOC_COMMENT == t.id() || JavaTokenId.JAVADOC_COMMENT_LINE_RUN == t.id()) { - // javadoc hyperlinking (references + param names) - TokenSequence jdts = ts.embedded(JavadocTokenId.language()); - if (JavadocImports.isInsideReference(jdts, offset) || JavadocImports.isInsideParamName(jdts, offset)) { -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java -index cd61d9094104..a68dc91894fa 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionCollector.java -@@ -1319,6 +1319,7 @@ private static TokenSequence findLastNonWhitespaceToken(TokenSequen - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - default: - return ts; -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionItem.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionItem.java -index 733ba9ad3226..47fbd2803f85 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionItem.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionItem.java -@@ -4617,6 +4617,7 @@ private static TokenSequence findLastNonWhitespaceToken(TokenSequen - case LINE_COMMENT: - case BLOCK_COMMENT: - case JAVADOC_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - break; - default: - return ts; -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java b/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java -index 5ac389c224c5..adefaee33d02 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaKit.java -@@ -458,6 +458,7 @@ public void insert(MutableContext context) throws BadLocationException { - if (isJavadocTouched) { - blockCommentComplete(doc, dotPos, context); - } -+ TypingCompletion.javadocLineRunCompletion(context); - } - } - -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java -index 5f2172b49d88..0682f52f5f6f 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java -@@ -563,6 +563,21 @@ private static boolean isClosedBlockComment(CharSequence txt, int pos) { - return false; - } - -+ static boolean javadocLineRunCompletion(TypedBreakInterceptor.MutableContext context) { -+ TokenSequence ts = javaTokenSequence(context, false); -+ if (ts == null) { -+ return false; -+ } -+ int dotPosition = context.getCaretOffset(); -+ ts.move(dotPosition); -+ if (!((ts.moveNext() || ts.movePrevious()) && ts.token().id() == JavaTokenId.JAVADOC_COMMENT_LINE_RUN)) { -+ return false; -+ } -+ context.setText("\n///", -1, 4, 0, 4); -+ -+ return false; -+ } -+ - private static boolean isAtRowEnd(CharSequence txt, int pos) { - int length = txt.length(); - for (int i = pos; i < length; i++) { -diff --git a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java -index da31e094c582..6ccb51a51e3a 100644 ---- a/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java -+++ b/java/java.editor/src/org/netbeans/modules/editor/java/Utilities.java -@@ -288,6 +288,7 @@ public static boolean isJavaContext(final Document doc, final int offset, final - case INVALID_COMMENT_END: - case JAVADOC_COMMENT: - case LINE_COMMENT: -+ case JAVADOC_COMMENT_LINE_RUN: - case BLOCK_COMMENT: - return false; - case STRING_LITERAL: -diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionTask.java b/java/java.editor/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionTask.java -index eac6a5607c25..c328d4ae418d 100644 ---- a/java/java.editor/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionTask.java -+++ b/java/java.editor/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionTask.java -@@ -64,6 +64,7 @@ - import javax.swing.text.Document; - import org.netbeans.api.annotations.common.NonNull; - import org.netbeans.api.annotations.common.NullAllowed; -+import org.netbeans.api.java.lexer.JavaTokenId; - import org.netbeans.api.java.lexer.JavadocTokenId; - import org.netbeans.api.java.source.ClassIndex; - import org.netbeans.api.java.source.ClasspathInfo; -@@ -84,6 +85,7 @@ - import org.netbeans.modules.parsing.api.Source; - import org.netbeans.modules.parsing.api.UserTask; - import org.netbeans.modules.parsing.spi.Parser; -+import org.openide.util.Pair; - - public class JavadocCompletionTask extends UserTask { - -@@ -188,16 +190,20 @@ private void analyzeContext(JavadocContext jdctx) { - return; - } - jdts.move(this.caretOffset); -+ JavadocTokenId javadocId; - if (!jdts.moveNext() && !jdts.movePrevious()) { - // XXX solve /***/ - // provide block tags, inline tags, html -- return; -- } -- if (this.caretOffset - jdts.offset() == 0) { -- // if position in token == 0 resolve CC according to previous token -- jdts.movePrevious(); -+ // XXX: for Markdown, continuing -+ javadocId = JavadocTokenId.OTHER_TEXT; -+ } else { -+ if (this.caretOffset - jdts.offset() == 0) { -+ // if position in token == 0 resolve CC according to previous token -+ jdts.movePrevious(); -+ } -+ javadocId = jdts.token().id(); - } -- switch (jdts.token().id()) { -+ switch (javadocId) { - case TAG: - resolveTagToken(jdctx); - break; -@@ -265,7 +271,9 @@ void resolveInlineTag(DocTreePath tag, JavadocContext jdctx) { - - private int skipWhitespacesBackwards(final JavadocContext jdctx, final int offset) { - if (jdctx.jdts.move(offset) == 0 || !jdctx.jdts.moveNext()) { -- jdctx.jdts.movePrevious(); -+ if (!jdctx.jdts.movePrevious()) { -+ return offset; -+ } - } - do { - Token t = jdctx.jdts.token(); -@@ -415,13 +423,13 @@ private void insideSeeTag(DocTreePath tag, JavadocContext jdctx) { - int pos = caretOffset - jdts.offset(); - CharSequence cs = jdts.token().text(); - cs = pos < cs.length() ? cs.subSequence(0, pos) : cs; -- if (JavadocCompletionUtils.isWhiteSpace(cs) || JavadocCompletionUtils.isLineBreak(jdts.token(), pos)) { -+ if (JavadocCompletionUtils.isWhiteSpace(cs) || JavadocCompletionUtils.isLineBreak(jdts, pos)) { - noPrefix = true; - } else { - // broken syntax - return; - } -- } else if (!(JavadocCompletionUtils.isWhiteSpace(jdts.token()) || JavadocCompletionUtils.isLineBreak(jdts.token()))) { -+ } else if (!(JavadocCompletionUtils.isWhiteSpace(jdts.token()) || JavadocCompletionUtils.isLineBreak(jdts))) { - // not java reference - return; - } else if (jdts.moveNext()) { -@@ -519,7 +527,7 @@ private void insideParamTag(DocTreePath tag, JavadocContext jdctx) { - int pos = caretOffset - jdts.offset(); - CharSequence cs = jdts.token().text(); - cs = pos < cs.length() ? cs.subSequence(0, pos) : cs; -- if (JavadocCompletionUtils.isWhiteSpace(cs) || JavadocCompletionUtils.isLineBreak(jdts.token(), pos)) { -+ if (JavadocCompletionUtils.isWhiteSpace(cs) || JavadocCompletionUtils.isLineBreak(jdts, pos)) { - // none prefix - anchorOffset = caretOffset; - completeParamName(tag, "", caretOffset, jdctx); // NOI18N -@@ -1226,11 +1234,10 @@ private boolean startsWith(String theString, String prefix) { - - void resolveOtherText(JavadocContext jdctx, TokenSequence jdts) { - Token token = jdts.token(); -- assert token != null; -- assert token.id() == JavadocTokenId.OTHER_TEXT; -- CharSequence text = token.text(); -- int pos = caretOffset - jdts.offset(); -- DocTreePath tag = getTag(jdctx, caretOffset); -+ assert token == null || token.id() == JavadocTokenId.OTHER_TEXT; -+ CharSequence text = token == null ? "" : token.text(); -+ int pos = token == null ? 0 : caretOffset - jdts.offset(); -+ DocTreePath tag = token == null ? null : getTag(jdctx, caretOffset); - - if (pos > 0 && pos <= text.length() && text.charAt(pos - 1) == '{') { - if (tag != null && !JavadocCompletionUtils.isBlockTag(tag)) { -@@ -1244,10 +1251,10 @@ void resolveOtherText(JavadocContext jdctx, TokenSequence jdts) - } - if (tag != null) { - insideTag(tag, jdctx); -- if (JavadocCompletionUtils.isBlockTag(tag) && JavadocCompletionUtils.isLineBreak(token, pos)) { -+ if (JavadocCompletionUtils.isBlockTag(tag) && JavadocCompletionUtils.isLineBreak(jdts, pos)) { - resolveBlockTag(null, jdctx); - } -- } else if (JavadocCompletionUtils.isLineBreak(token, pos)) { -+ } else if (JavadocCompletionUtils.isLineBreak(jdts, pos)) { - resolveBlockTag(null, jdctx); - } - } -@@ -1336,6 +1343,7 @@ private static class JavadocContext { - private DocCommentTree comment; - private DocSourcePositions positions; - private TokenSequence jdts; -+ private TokenSequence javats; - private Document doc; - private ReferencesCount count; - private TreePath javadocFor; -diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java -index 8deac6817b8f..a506190feb74 100644 ---- a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java -+++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/GoToSupportTest.java -@@ -1145,6 +1145,71 @@ public void testBindingVarToolTip() throws Exception { - assertEquals("java.lang.String str", tooltip); - } - -+ public void testJavadoc() throws Exception { -+ final boolean[] wasCalled = new boolean[1]; -+ final String code = """ -+ package test; -+ /** -+ * @see Obj|ect -+ */ -+ public class Test { -+ } -+ """; -+ -+ performTest(code, new UiUtilsCaller() { -+ @Override public boolean open(FileObject fo, int pos) { -+ fail("Should not be called."); -+ return true; -+ } -+ -+ @Override public void beep(boolean goToSource, boolean goToJavadoc) { -+ fail("Should not be called."); -+ } -+ @Override public boolean open(ClasspathInfo info, ElementHandle el, String fileName) { -+ assertEquals("java.lang.Object", el.getBinaryName()); -+ wasCalled[0] = true; -+ return true; -+ } -+ @Override public void warnCannotOpen(String displayName) { -+ fail("Should not be called."); -+ } -+ }, false, false); -+ -+ assertTrue(wasCalled[0]); -+ } -+ -+ public void testMarkdownJavadoc() throws Exception { -+ final boolean[] wasCalled = new boolean[1]; -+ this.sourceLevel = "23"; -+ final String code = """ -+ package test; -+ ///@see Obj|ect -+ public class Test { -+ } -+ """; -+ -+ performTest(code, new UiUtilsCaller() { -+ @Override public boolean open(FileObject fo, int pos) { -+ fail("Should not be called."); -+ return true; -+ } -+ -+ @Override public void beep(boolean goToSource, boolean goToJavadoc) { -+ fail("Should not be called."); -+ } -+ @Override public boolean open(ClasspathInfo info, ElementHandle el, String fileName) { -+ assertEquals("java.lang.Object", el.getBinaryName()); -+ wasCalled[0] = true; -+ return true; -+ } -+ @Override public void warnCannotOpen(String displayName) { -+ fail("Should not be called."); -+ } -+ }, false, false); -+ -+ assertTrue(wasCalled[0]); -+ } -+ - private String sourceLevel = "1.5"; - private FileObject source; - -diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java -index a0713d608f6c..99efb7f02484 100644 ---- a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java -+++ b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java -@@ -1419,6 +1419,22 @@ public void testX() throws Exception { - ctx.assertDocumentTextEquals("{"); - } - -+ public void testJavadocLineRun() { -+ Context ctx = new Context(new JavaKit(), -+ """ -+ class Test { -+ ///| -+ } -+ """); -+ ctx.typeChar('\n'); -+ ctx.assertDocumentTextEquals(""" -+ class Test { -+ /// -+ ///| -+ } -+ """); -+ } -+ - private boolean isInsideString(String code) throws BadLocationException { - int pos = code.indexOf('|'); - -diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQueryTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQueryTest.java -index 8bf90d619fab..48f00daca355 100644 ---- a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQueryTest.java -+++ b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/javadoc/JavadocCompletionQueryTest.java -@@ -23,10 +23,14 @@ - import java.util.Arrays; - import java.util.Collections; - import java.util.List; -+import javax.swing.event.ChangeListener; - import org.netbeans.junit.NbTestSuite; - import org.netbeans.spi.editor.completion.CompletionItem; - import org.netbeans.spi.editor.completion.CompletionProvider; - import org.netbeans.modules.java.editor.base.javadoc.JavadocTestSupport; -+import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2; -+import org.openide.filesystems.FileObject; -+import org.openide.util.lookup.ServiceProvider; - - /** - * -@@ -492,7 +496,7 @@ public void testValue2() throws Exception { - "package p;\n" + - "class Clazz {\n" + - " /**\n" + -- " * {@value Mat|\n" + -+ " * {@value Math|\n" + - " */\n" + - " Clazz() {\n" + - " }\n" + -@@ -601,8 +605,244 @@ public void testSummaryCompletionForMethod() throws Exception { - "}\n"; - performCompletionTest(code, "@summary:"); - } -- -- -+ -+ public void testBlockTagsCompletionInMarkdown() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ /// | -+ /// -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testBlockTagsCompletionInMarkdown2() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ ///| -+ /// -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testBlockTagsCompletionInMarkdown3() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ ///|\s -+ /// -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testBlockTagsCompletionInMarkdownStart() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///| -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testSeeMarkdown1() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ /// @see CharSequence#le| -+ /// -+ Clazz() { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "public abstract int length()"); -+ } -+ -+ public void testSeeMarkdown2() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ /// @see | -+ /// -+ Clazz() { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, null, "String", "Clazz"); -+ } -+ -+ public void testSeeMarkdown3() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///@param i i -+ ///@see | -+ /// -+ Clazz(int i) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, null, "String", "Clazz"); -+ } -+ -+ public void testParamMarkdown() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /// -+ /// @param | -+ /// -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "p1:", "p2:"); -+ } -+ -+ public void testJavadocOldStart1() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /**| */ -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testJavadocOldStart2() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /**@s| */ -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@see:", "@serialData:", "@since:"); -+ } -+ -+ public void testJavadocOldStart3() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /**@param | */ -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "p1:", "p2:"); -+ } -+ -+ public void testJavadocOldStart4() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ /**@see | */ -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, null, "String", "Clazz"); -+ } -+ -+ public void testJavadocMarkdownStart1() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///| -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@deprecated:", "@exception:", "@hidden:", "@param:", "@return:", "@see:", "@serialData:", "@since:", "@throws:"); -+ } -+ -+ public void testJavadocMarkdownStart2() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///@s| -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "@see:", "@serialData:", "@since:"); -+ } -+ -+ public void testJavadocMarkdownStart3() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///@param | -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, "p1:", "p2:"); -+ } -+ -+ public void testJavadocMarkdownStart4() throws Exception { -+ String code = -+ """ -+ package p; -+ class Clazz { -+ ///@see | -+ void method(int p1, int p2) { -+ } -+ } -+ """; -+ -+ performCompletionTest(code, null, "String", "Clazz"); -+ } - - private static String stripHTML(String from) { - StringBuilder result = new StringBuilder(); -@@ -647,4 +887,30 @@ private void performCompletionTest(String code, String... golden) throws Excepti - assertEquals(goldenList, resultStrings); - } - } -+ -+ @Override -+ protected Object[] additionalServices() { -+ return new Object[] { -+ new SourceLevelQueryImplementation2() { -+ -+ @Override -+ public Result getSourceLevel(FileObject javaFile) { -+ return new Result() { -+ @Override -+ public String getSourceLevel() { -+ return "23"; -+ } -+ -+ @Override -+ public void addChangeListener(ChangeListener listener) { -+ } -+ -+ @Override -+ public void removeChangeListener(ChangeListener listener) { -+ } -+ }; -+ } -+ } -+ }; -+ } - } -diff --git a/java/java.lexer/nbproject/project.properties b/java/java.lexer/nbproject/project.properties -index 4ea9ce2e2612..36e48fd27c57 100644 ---- a/java/java.lexer/nbproject/project.properties -+++ b/java/java.lexer/nbproject/project.properties -@@ -17,7 +17,7 @@ - - is.autoload=true - javac.compilerargs=-Xlint:unchecked --javac.source=1.8 -+javac.release=17 - javadoc.title=Java Lexer API - javadoc.apichanges=${basedir}/apichanges.xml - -diff --git a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java -index 17602a5e400a..25738a8da1ae 100644 ---- a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java -+++ b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java -@@ -193,6 +193,7 @@ public enum JavaTokenId implements TokenId { - LINE_COMMENT(null, "comment"), // Token includes ending new-line - BLOCK_COMMENT(null, "comment"), - JAVADOC_COMMENT(null, "comment"), -+ JAVADOC_COMMENT_LINE_RUN(null, "comment"), // A run of "markdown" javadoc comments, includes ending new-line - - // Errors - INVALID_COMMENT_END("*/", "error"), -@@ -262,6 +263,9 @@ protected LanguageEmbedding embedding( - case JAVADOC_COMMENT: - return LanguageEmbedding.create(JavadocTokenId.language(), 3, - (token.partType() == PartType.COMPLETE) ? 2 : 0); -+ case JAVADOC_COMMENT_LINE_RUN: -+ return LanguageEmbedding.create(JavadocTokenId.language(), 3, -+ (token.partType() == PartType.COMPLETE) ? 1 : 0); - case STRING_LITERAL: - return LanguageEmbedding.create(JavaStringTokenId.language(), 1, - (token.partType() == PartType.COMPLETE) ? 1 : 0); -diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java -index 49c32619b467..438b8b84ffb3 100644 ---- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java -+++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java -@@ -321,6 +321,13 @@ public Token nextToken() { - case '/': - switch (nextChar()) { - case '/': // in single-line comment -+ switch (nextChar()) { -+ case '/': return finishJavadocLineRun(); -+ case '\r': consumeNewline(); -+ case '\n': -+ case EOF: -+ return token(JavaTokenId.LINE_COMMENT); -+ } - while (true) - switch (nextChar()) { - case '\r': consumeNewline(); -@@ -1428,6 +1435,34 @@ private Token finishFloatExponent() { - return token(JavaTokenId.DOUBLE_LITERAL); - } - } -+ -+ private Token finishJavadocLineRun() { -+ while (true) { -+ //finish current line: -+ LINE: while (true) { -+ switch (nextChar()) { -+ case '\r': consumeNewline(); -+ case '\n': break LINE; -+ case EOF: -+ return token(JavaTokenId.JAVADOC_COMMENT_LINE_RUN); -+ } -+ } -+ -+ //at the next line, if it starts with "///", include it in the run, -+ //otherwise finish the run: -+ int mark = input.readLength(); -+ int c; -+ -+ while (Character.isWhitespace(c = nextChar()) && c != '\r' && c != '\n' && c != EOF) -+ ; -+ -+ if (c != '/' || nextChar() != '/' || nextChar() != '/') { -+ input.backup(input.readLengthEOF()- mark); -+ -+ return token(JavaTokenId.JAVADOC_COMMENT_LINE_RUN); -+ } -+ } -+ } - - private Token token(JavaTokenId id) { - return token(id, PartType.COMPLETE); -diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavadocLexer.java b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavadocLexer.java -index fa7189b48331..c6ab507fee3f 100644 ---- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavadocLexer.java -+++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavadocLexer.java -@@ -194,6 +194,20 @@ private Token otherText(int ch) { - leftbr = false; - newline = false; - break; -+ case '/': -+ //TODO: check comment type? -+ if (newline) { -+ if (input.read() == '/') { -+ if (input.read() == '/') { -+ break; -+ } else { -+ input.backup(1); -+ } -+ } else { -+ input.backup(1); -+ } -+ newline = false; //for fall-through: -+ } - case '*': - if (newline) { - break; -diff --git a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java -index 6402fc5c348f..bf4e0b71a8c2 100644 ---- a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java -+++ b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java -@@ -812,4 +812,83 @@ public void testTemplates2() { - assertFalse(ts.moveNext()); - } - -+ public void testMarkdown1() { -+ String text = """ -+ ///test -+ ///@see second line -+ ///third -+ -+ ///another run -+ ///another line -+ -+ """; -+ InputAttributes attr = new InputAttributes(); -+ TokenHierarchy hi = TokenHierarchy.create(text, false, JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr); -+ TokenSequence ts = hi.tokenSequence(); -+ -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///test\n" + -+ "///@see second line\n" + -+ "///third\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///another run\n" + -+ "///another line\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\n"); -+ assertFalse(ts.moveNext()); -+ } -+ -+ public void testMarkdown2() { -+ String text = """ -+ ///test -+ ///@see second line -+ ///third -+ -+ ///another run -+ ///another line -+ """; -+ InputAttributes attr = new InputAttributes(); -+ TokenHierarchy hi = TokenHierarchy.create(text, false, JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr); -+ TokenSequence ts = hi.tokenSequence(); -+ -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///test\n" + -+ "///@see second line\n" + -+ "///third\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///another run\n" + -+ "///another line\n"); -+ assertFalse(ts.moveNext()); -+ } -+ -+ public void testMarkdown3() { -+ String text = """ -+ ///test -+ ///@see second line -+ ///third -+ -+ ///another run -+ ///another line"""; -+ InputAttributes attr = new InputAttributes(); -+ TokenHierarchy hi = TokenHierarchy.create(text, false, JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr); -+ TokenSequence ts = hi.tokenSequence(); -+ -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///test\n" + -+ "///@see second line\n" + -+ "///third\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, "\n"); -+ LexerTestUtilities.assertNextTokenEquals(ts, -+ JavaTokenId.JAVADOC_COMMENT_LINE_RUN, -+ "///another run\n" + -+ "///another line"); -+ assertFalse(ts.moveNext()); -+ } -+ - } -diff --git a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavadocLexerTest.java b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavadocLexerTest.java -index 72668f24a651..c0859ba2f826 100644 ---- a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavadocLexerTest.java -+++ b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavadocLexerTest.java -@@ -143,6 +143,20 @@ public void test233097b() { - LexerTestUtilities.assertNextTokenEquals(ts, JavadocTokenId.OTHER_TEXT, "}"); - } - -+ public void testMarkdown() { -+ String text = "///@see\n/// @see"; -+ -+ TokenHierarchy hi = TokenHierarchy.create(text, JavadocTokenId.language()); -+ TokenSequence ts = hi.tokenSequence(); -+ -+ LexerTestUtilities.assertNextTokenEquals(ts, JavadocTokenId.OTHER_TEXT, "///"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavadocTokenId.TAG, "@see"); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavadocTokenId.OTHER_TEXT, "\n/// "); -+ LexerTestUtilities.assertNextTokenEquals(ts, JavadocTokenId.TAG, "@see"); -+ -+ assertFalse(ts.moveNext()); -+ } -+ - // public void testModification1() throws Exception { - // PlainDocument doc = new PlainDocument(); - // doc.putProperty(Language.class, JavadocTokenId.language()); -diff --git a/java/java.lsp.server/licenseinfo.xml b/java/java.lsp.server/licenseinfo.xml -index fc390b64bbc9..001c83187ebd 100644 ---- a/java/java.lsp.server/licenseinfo.xml -+++ b/java/java.lsp.server/licenseinfo.xml -@@ -50,4 +50,9 @@ - - - -+ -+ vscode/language-configuration.json -+ -+ -+ - -diff --git a/java/java.lsp.server/vscode/language-configuration.json b/java/java.lsp.server/vscode/language-configuration.json -new file mode 100644 -index 000000000000..c6b69e53360e ---- /dev/null -+++ b/java/java.lsp.server/vscode/language-configuration.json -@@ -0,0 +1,111 @@ -+{ -+ "comments": { -+ "lineComment": "//", -+ "blockComment": [ "/*", "*/" ] -+ }, -+ "brackets": [ -+ ["{", "}"], -+ ["[", "]"], -+ ["(", ")"] -+ ], -+ "autoClosingPairs": [ -+ ["{", "}"], -+ ["[", "]"], -+ ["(", ")"], -+ { "open": "\"", "close": "\"", "notIn": ["string"] }, -+ { "open": "'", "close": "'", "notIn": ["string"] }, -+ { "open": "/**", "close": " */", "notIn": ["string"] } -+ ], -+ "surroundingPairs": [ -+ ["{", "}"], -+ ["[", "]"], -+ ["(", ")"], -+ ["\"", "\""], -+ ["'", "'"], -+ ["<", ">"] -+ ], -+ "folding": { -+ "markers": { -+ "start": "^\\s*//\\s*(?:(?:#?region\\b)|(?:))" -+ } -+ }, -+ "onEnterRules": [ -+ { -+ // e.g. /** | */ -+ "beforeText": { -+ "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$" -+ }, -+ "afterText": { -+ "pattern": "^\\s*\\*/$" -+ }, -+ "action": { -+ "indent": "indentOutdent", -+ "appendText": " * " -+ } -+ }, -+ { -+ // e.g. /** ...| -+ "beforeText": { -+ "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$" -+ }, -+ "action": { -+ "indent": "none", -+ "appendText": " * " -+ } -+ }, -+ { -+ // e.g. * ...| -+ "beforeText": { -+ "pattern": "^(\\t|[ ])*[ ]\\*([ ]([^\\*]|\\*(?!/))*)?$" -+ }, -+ "previousLineText": { -+ "pattern": "(?=^(\\s*(/\\*\\*|\\*)).*)(?=(?!(\\s*\\*/)))" -+ }, -+ "action": { -+ "indent": "none", -+ "appendText": "* " -+ } -+ }, -+ { -+ // e.g. */| -+ "beforeText": { -+ "pattern": "^(\\t|[ ])*[ ]\\*/\\s*$" -+ }, -+ "action": { -+ "indent": "none", -+ "removeText": 1 -+ } -+ }, -+ { -+ // e.g. *-----*/| -+ "beforeText": { -+ "pattern": "^(\\t|[ ])*[ ]\\*[^/]*\\*/\\s*$" -+ }, -+ "action": { -+ "indent": "none", -+ "removeText": 1 -+ } -+ }, -+ { -+ "beforeText": { -+ "pattern": "^\\s*(\\bcase\\s.+:|\\bdefault:)$" -+ }, -+ "afterText": { -+ "pattern": "^(?!\\s*(\\bcase\\b|\\bdefault\\b))" -+ }, -+ "action": { -+ "indent": "indent" -+ } -+ }, -+ { -+ "beforeText": { -+ "pattern": "^\\s*///.*$" -+ }, -+ "action": { -+ "indent": "none", -+ "appendText": "///" -+ } -+ } -+ ] -+} -diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json -index cad97381ef73..60795163b16a 100644 ---- a/java/java.lsp.server/vscode/package.json -+++ b/java/java.lsp.server/vscode/package.json -@@ -35,6 +35,18 @@ - "main": "./out/extension.js", - "contributes": { - "languages": [ -+ { -+ "id": "java", -+ "extensions": [ -+ ".java", -+ ".jav" -+ ], -+ "aliases": [ -+ "Java", -+ "java" -+ ], -+ "configuration": "./language-configuration.json" -+ }, - { - "id": "javascript", - "mimetypes": [ -diff --git a/java/java.lsp.server/vscode/syntaxes/java.tmLanguage.json b/java/java.lsp.server/vscode/syntaxes/java.tmLanguage.json -index 1357aff68d5f..d990bf88fd93 100644 ---- a/java/java.lsp.server/vscode/syntaxes/java.tmLanguage.json -+++ b/java/java.lsp.server/vscode/syntaxes/java.tmLanguage.json -@@ -655,6 +655,63 @@ - } - } - ] -+ }, -+ { -+ "begin": "^\\s*(///)", -+ "beginCaptures": { -+ "1": { -+ "name": "punctuation.definition.comment.java" -+ } -+ }, -+ "end": "\n", -+ "endCaptures": { -+ "0": { -+ "name": "punctuation.definition.comment.java" -+ } -+ }, -+ "name": "comment.block.javadoc.markdown.java", -+ "patterns": [ -+ { -+ "match": "@(author|deprecated|return|see|serial|since|version)\\b", -+ "name": "keyword.other.documentation.javadoc.java" -+ }, -+ { -+ "match": "(@param)\\s+(\\S+)", -+ "captures": { -+ "1": { -+ "name": "keyword.other.documentation.javadoc.java" -+ }, -+ "2": { -+ "name": "variable.parameter.java" -+ } -+ } -+ }, -+ { -+ "match": "(@(?:exception|throws))\\s+(\\S+)", -+ "captures": { -+ "1": { -+ "name": "keyword.other.documentation.javadoc.java" -+ }, -+ "2": { -+ "name": "entity.name.type.class.java" -+ } -+ } -+ }, -+ { -+ "match": "{(@link)\\s+(\\S+)?#([\\w$]+\\s*\\([^\\(\\)]*\\)).*?}", -+ "captures": { -+ "1": { -+ "name": "keyword.other.documentation.javadoc.java" -+ }, -+ "2": { -+ "name": "entity.name.type.class.java" -+ }, -+ "3": { -+ "name": "variable.parameter.java" -+ } -+ } -+ } -+ ] - } - ] - }, -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -index a7453c44778e..bca4cbd46ae0 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -@@ -1302,7 +1302,11 @@ public int[] findNameSpan(DocCommentTree docTree, ReferenceTree ref) { - - tokenSequence.move(pos); - -- if (!tokenSequence.moveNext() || tokenSequence.token().id() != JavaTokenId.JAVADOC_COMMENT) return null; -+ if (!tokenSequence.moveNext() || -+ (tokenSequence.token().id() != JavaTokenId.JAVADOC_COMMENT && -+ tokenSequence.token().id() != JavaTokenId.JAVADOC_COMMENT_LINE_RUN)) { -+ return null; -+ } - - TokenSequence jdocTS = tokenSequence.embedded(JavadocTokenId.language()); - -diff --git a/java/java.sourceui/nbproject/project.xml b/java/java.sourceui/nbproject/project.xml -index 9ac80a3c0929..f1bb6375971b 100644 ---- a/java/java.sourceui/nbproject/project.xml -+++ b/java/java.sourceui/nbproject/project.xml -@@ -86,6 +86,14 @@ - - - -+ -+ org.netbeans.libs.flexmark -+ -+ -+ -+ 1.18 -+ -+ - - org.netbeans.libs.javacapi - -diff --git a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java -index fdabe504448e..832e599852c2 100644 ---- a/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java -+++ b/java/java.sourceui/src/org/netbeans/api/java/source/ui/ElementJavadoc.java -@@ -32,6 +32,7 @@ - import com.sun.source.doctree.LinkTree; - import com.sun.source.doctree.LiteralTree; - import com.sun.source.doctree.ParamTree; -+import com.sun.source.doctree.RawTextTree; - import com.sun.source.doctree.ReferenceTree; - import com.sun.source.doctree.ReturnTree; - import com.sun.source.doctree.SeeTree; -@@ -119,6 +120,11 @@ - import com.sun.source.tree.ImportTree; - import com.sun.source.tree.Tree; - import com.sun.source.util.JavacTask; -+import com.vladsch.flexmark.ext.tables.TablesExtension; -+import com.vladsch.flexmark.html.HtmlRenderer; -+import com.vladsch.flexmark.parser.Parser; -+import com.vladsch.flexmark.util.data.DataHolder; -+import com.vladsch.flexmark.util.data.MutableDataSet; - import javax.lang.model.element.RecordComponentElement; - import org.netbeans.api.java.queries.SourceLevelQuery; - import org.netbeans.api.java.queries.SourceLevelQuery.Profile; -@@ -1275,7 +1281,7 @@ private String noJavadocFound() { - private StringBuilder inlineTags(List tags, TreePath docPath, DocCommentTree doc, DocTrees trees, CharSequence inherited) { - StringBuilder sb = new StringBuilder(); - Integer snippetCount=0; -- for (DocTree tag : tags) { -+ for (DocTree tag : resolveMarkdown(trees, tags)) { - switch (tag.getKind()) { - case REFERENCE: - ReferenceTree refTag = (ReferenceTree)tag; -@@ -1287,6 +1293,9 @@ private StringBuilder inlineTags(List tags, TreePath docPath, - break; - case LINK: - linkTag = (LinkTree)tag; -+ if (linkTag.getReference() == null) { -+ break; -+ } - sb.append(""); //NOI18N - appendReference(sb, linkTag.getReference(), linkTag.getLabel(), docPath, doc, trees); - sb.append(""); //NOI18N -@@ -1395,6 +1404,53 @@ private StringBuilder inlineTags(List tags, TreePath docPath, - return sb; - } - -+ private static final char REPLACEMENT = '\uFFFD'; -+ private List resolveMarkdown(DocTrees trees, List tags) { -+ if (tags.stream().noneMatch(t -> t.getKind() == DocTree.Kind.MARKDOWN)) { -+ return tags; -+ } -+ -+ StringBuilder markdownSource = new StringBuilder(); -+ List replacements = new ArrayList<>(); -+ -+ for (DocTree t : tags) { -+ if (t.getKind() == DocTree.Kind.MARKDOWN) { -+ markdownSource.append(((RawTextTree) t).getContent()); -+ } else { -+ markdownSource.append(REPLACEMENT); -+ replacements.add(t); -+ } -+ } -+ -+ TablesExtension tablesExtension = TablesExtension.create(); -+ -+ Parser.Builder parserBuilder = Parser.builder(); -+ tablesExtension.extend(parserBuilder); -+ -+ HtmlRenderer.Builder rendererBuilder = HtmlRenderer.builder(); -+ tablesExtension.extend(rendererBuilder, "HTML"); -+ -+ String html = rendererBuilder.build() -+ .render(parserBuilder.build() -+ .parse(markdownSource.toString())); -+ -+ if (html.startsWith("

")) { -+ html = html.substring("

".length()); -+ } -+ html = html.replace("

", ""); -+ List result = new ArrayList<>(); -+ String[] parts = html.split(Pattern.quote("" + REPLACEMENT)); -+ -+ result.add(trees.getDocTreeFactory().newTextTree(parts[0])); -+ -+ for (int i = 1; i < parts.length; i++) { -+ result.add(replacements.get(i - 1)); -+ result.add(trees.getDocTreeFactory().newTextTree(parts[i])); -+ } -+ -+ return result; -+ } -+ - private void processDocSnippet(StringBuilder sb, SnippetTree javadocSnippet, Integer snippetCount, TreePath docPath,DocCommentTree doc, DocTrees trees) { - sb.append("
"); //NOI18N - sb.append("
" //NOI18N -diff --git a/java/java.sourceui/test/unit/src/org/netbeans/api/java/source/ui/ElementJavadocTest.java b/java/java.sourceui/test/unit/src/org/netbeans/api/java/source/ui/ElementJavadocTest.java -new file mode 100644 -index 000000000000..13bee62039d3 ---- /dev/null -+++ b/java/java.sourceui/test/unit/src/org/netbeans/api/java/source/ui/ElementJavadocTest.java -@@ -0,0 +1,164 @@ -+/* -+ * Licensed to the Apache Software Foundation (ASF) under one -+ * or more contributor license agreements. See the NOTICE file -+ * distributed with this work for additional information -+ * regarding copyright ownership. The ASF licenses this file -+ * to you under the Apache License, Version 2.0 (the -+ * "License"); you may not use this file except in compliance -+ * with the License. You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, -+ * software distributed under the License is distributed on an -+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -+ * KIND, either express or implied. See the License for the -+ * specific language governing permissions and limitations -+ * under the License. -+ */ -+package org.netbeans.api.java.source.ui; -+ -+import com.sun.source.util.TreePath; -+import java.io.File; -+import java.util.ArrayList; -+import java.util.List; -+import javax.lang.model.element.Element; -+import javax.swing.text.Document; -+import org.netbeans.api.java.lexer.JavaTokenId; -+import org.netbeans.api.java.source.CompilationInfo; -+import org.netbeans.api.java.source.JavaSource; -+import org.netbeans.api.java.source.JavaSource.Phase; -+import org.netbeans.api.java.source.SourceUtilsTestUtil; -+import org.netbeans.api.java.source.TestUtilities; -+import org.netbeans.api.lexer.Language; -+import org.netbeans.junit.NbTestCase; -+import org.netbeans.modules.java.JavaDataLoader; -+import org.openide.cookies.EditorCookie; -+import org.openide.filesystems.FileObject; -+import org.openide.filesystems.FileUtil; -+import org.openide.loaders.DataObject; -+ -+public class ElementJavadocTest extends NbTestCase { -+ -+ private static final String CARET_MARK = ""; -+ -+ public ElementJavadocTest(String testName) { -+ super(testName); -+ } -+ -+ private void prepareTest(String fileName, String code) throws Exception { -+ int pos = code.indexOf(CARET_MARK); -+ -+ if (pos == (-1)) { -+ throw new AssertionError("Does not have caret position!"); -+ } -+ -+ code = code.substring(0, pos) + code.substring(pos + CARET_MARK.length()); -+ -+ List extras = new ArrayList<>(); -+ extras.add(JavaDataLoader.class); -+ SourceUtilsTestUtil.prepareTest(new String[] { -+ "org/netbeans/modules/java/platform/resources/layer.xml", -+ "org/netbeans/modules/java/j2seplatform/resources/layer.xml" -+ }, -+ extras.toArray(new Object[0]) -+ ); -+ -+ clearWorkDir(); -+ -+ FileUtil.refreshAll(); -+ -+ FileObject workFO = FileUtil.toFileObject(getWorkDir()); -+ -+ assertNotNull(workFO); -+ -+ sourceRoot = workFO.createFolder("src"); -+ -+ FileObject buildRoot = workFO.createFolder("build"); -+ FileObject cache = workFO.createFolder("cache"); -+ -+ FileObject data = FileUtil.createData(sourceRoot, fileName); -+ File dataFile = FileUtil.toFile(data); -+ -+ assertNotNull(dataFile); -+ -+ TestUtilities.copyStringToFile(dataFile, code); -+ -+ SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache, new FileObject[0]); -+ -+ DataObject od = DataObject.find(data); -+ EditorCookie ec = od.getCookie(EditorCookie.class); -+ -+ assertNotNull(ec); -+ -+ doc = ec.openDocument(); -+ doc.putProperty(Language.class, JavaTokenId.language()); -+ -+ JavaSource js = JavaSource.forFileObject(data); -+ -+ assertNotNull(js); -+ -+ info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED); -+ -+ assertNotNull(info); -+ -+ selectedPath = info.getTreeUtilities().pathFor(pos); -+ selectedElement = info.getTrees().getElement(selectedPath); -+ -+ assertNotNull(selectedElement); -+ } -+ -+ private FileObject sourceRoot; -+ private CompilationInfo info; -+ private Document doc; -+ private TreePath selectedPath; -+ private Element selectedElement; -+ -+ protected void performTest(String fileName, String code, int pos, String format, String golden) throws Exception { -+ prepareTest(fileName, code); -+ -+ TreePath path = info.getTreeUtilities().pathFor(pos); -+ -+ assertEquals(golden, ElementHeaders.getHeader(path, info, format)); -+ } -+ -+ public void testMarkdownTables() throws Exception { -+ prepareTest("test/Test.java", -+ "///| header1 | header2 |\n" + -+ "///|---------|---------|\n" + -+ "///| cr11 | cr12 |\n" + -+ "///| cr21 | cr22 |\n" + -+ "public class Test {\n" + -+ "}\n"); -+ -+ String actualJavadoc = ElementJavadoc.create(info, selectedElement).getText(); -+ String expectedJavadoc = "
public class Test
extends Object

\n" + -+ "\n" + -+ "\n" + -+ "\n" + -+ "\n" + -+ "\n" + -+ "\n" + -+ "\n" + -+ "
header1header2
cr11cr12
cr21cr22
\n" + -+ "

"; -+ -+ assertEquals(expectedJavadoc, actualJavadoc); -+ } -+ -+ public void testLinkNoRef() throws Exception { -+ prepareTest("test/Test.java", -+ "///Hello!\n" + -+ "///{@link }\n" + -+ "public class Test {\n" + -+ "}\n"); -+ -+ String actualJavadoc = ElementJavadoc.create(info, selectedElement).getText(); -+ String expectedJavadoc = "

public class Test
extends Object

Hello!\n" + -+ "\n" + -+ "

"; -+ -+ assertEquals(expectedJavadoc, actualJavadoc); -+ } -+ -+} diff --git a/patches/7641.diff b/patches/7641.diff deleted file mode 100644 index 676c1327..00000000 --- a/patches/7641.diff +++ /dev/null @@ -1,492 +0,0 @@ -diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java -index f1239136427f..0727cbe743be 100644 ---- a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java -+++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java -@@ -4776,6 +4776,28 @@ public class Reformatter implements ReformatTask { - } - } - -+ private enum JavadocReformattingState { -+ INITIAL_TEXT, -+ AFTER_PARAM_TAG, -+ PARAM_DESCRIPTION, -+ RETURN_DESCRIPTION, -+ AFTER_THROWS_TAG, -+ EXCEPTION_DESCRIPTION, -+ AFTER_PRE_TAG, -+ AFTER_OTHER_TAG -+ } -+ -+ private enum JavadocReformattingActionType { -+ NONE, -+ ADD_BLANK_LINE, -+ ADD_NEW_LINE, -+ ALIGN_PARAMS, -+ ALIGN_RETURN, -+ ALIGN_EXCEPTIONS, -+ NO_FORMAT, -+ FORMAT -+ } -+ - private void reformatComment() { - if (tokens.token().id() != BLOCK_COMMENT && tokens.token().id() != JAVADOC_COMMENT) - return; -@@ -4788,15 +4810,14 @@ public class Reformatter implements ReformatTask { - return; - } - } -- String text = tokens.token().text().toString(); -- int offset = tokens.offset(); -- LinkedList> marks = new LinkedList>(); -+ final String text = tokens.token().text().toString(); -+ final int offset = tokens.offset(); -+ LinkedList> marks = new LinkedList<>(); - int maxParamNameLength = 0; - int maxExcNameLength = 0; - int initTextEndOffset = Integer.MAX_VALUE; - if (javadocTokens != null) { -- int state = 0; // 0 - initial text, 1 - after param tag, 2 - param description, 3 - return description, -- // 4 - after throws tag, 5 - exception description, 6 - after pre tag, 7 - after other tag -+ JavadocReformattingState state = JavadocReformattingState.INITIAL_TEXT; - int currWSOffset = -1; - int lastWSOffset = -1; - int identStart = -1; -@@ -4806,105 +4827,97 @@ public class Reformatter implements ReformatTask { - boolean insideTag = false; - int nestedParenCnt = 0; - StringBuilder cseq = null; -- Pair toAdd = null; -- Pair nlAdd = null; -+ Pair marker = null; -+ Pair nlAdd = null; - while (javadocTokens.moveNext()) { - switch (javadocTokens.token().id()) { - case TAG: -- toAdd = null; -+ marker = null; - nlAdd = null; - String tokenText = javadocTokens.token().text().toString(); -- int newState; -- if (JDOC_PARAM_TAG.equalsIgnoreCase(tokenText)) { -- newState = 1; -- } else if (JDOC_RETURN_TAG.equalsIgnoreCase(tokenText)) { -- newState = 3; -- } else if (JDOC_THROWS_TAG.equalsIgnoreCase(tokenText) -- || JDOC_EXCEPTION_TAG.equalsIgnoreCase(tokenText)) { -- newState = 4; -- } else if (JDOC_LINK_TAG.equalsIgnoreCase(tokenText) -- || JDOC_LINKPLAIN_TAG.equalsIgnoreCase(tokenText) -- || JDOC_CODE_TAG.equalsIgnoreCase(tokenText) -- || JDOC_SNIPPET_TAG.equalsIgnoreCase(tokenText) -- || JDOC_DOCROOT_TAG.equalsIgnoreCase(tokenText) -- || JDOC_INHERITDOC_TAG.equalsIgnoreCase(tokenText) -- || JDOC_VALUE_TAG.equalsIgnoreCase(tokenText) -- || JDOC_SUMMARY_TAG.equalsIgnoreCase(tokenText) -- || JDOC_LITERAL_TAG.equalsIgnoreCase(tokenText)) { -+ JavadocReformattingState newState; -+ if (hasInlineTagPrefix(text, tokenText, javadocTokens.offset() - offset)) { - insideTag = true; -- addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, 5), marks, state); -+ addMark(Pair.of(currWSOffset, JavadocReformattingActionType.NO_FORMAT), marks, state); - lastWSOffset = currWSOffset = -1; - break; -+ } else if (JDOC_PARAM_TAG.equalsIgnoreCase(tokenText)) { -+ newState = JavadocReformattingState.AFTER_PARAM_TAG; -+ } else if (JDOC_RETURN_TAG.equalsIgnoreCase(tokenText)) { -+ newState = JavadocReformattingState.RETURN_DESCRIPTION; -+ } else if (JDOC_THROWS_TAG.equalsIgnoreCase(tokenText) -+ || JDOC_EXCEPTION_TAG.equalsIgnoreCase(tokenText)) { -+ newState = JavadocReformattingState.AFTER_THROWS_TAG; - } else { - if (insideTag) - break; -- newState = 7; -+ newState = JavadocReformattingState.AFTER_OTHER_TAG; - } -- if (lastWSOffset < initTextEndOffset && newState > 0) { -+ if (lastWSOffset < initTextEndOffset && (newState != JavadocReformattingState.INITIAL_TEXT)) { - initTextEndOffset = lastWSOffset; - } - if (currWSOffset >= 0 && afterText) { -- addMark(Pair.of(currWSOffset, state == 0 && cs.blankLineAfterJavadocDescription() -- || state == 2 && newState != 1 && cs.blankLineAfterJavadocParameterDescriptions() -- || state == 3 && cs.blankLineAfterJavadocReturnTag() ? 0 : 1), marks, state); -+ addMark(Pair.of(currWSOffset, state == JavadocReformattingState.INITIAL_TEXT && cs.blankLineAfterJavadocDescription() -+ || state == JavadocReformattingState.PARAM_DESCRIPTION && newState != JavadocReformattingState.AFTER_PARAM_TAG && cs.blankLineAfterJavadocParameterDescriptions() -+ || state == JavadocReformattingState.RETURN_DESCRIPTION && cs.blankLineAfterJavadocReturnTag() ? JavadocReformattingActionType.ADD_BLANK_LINE : JavadocReformattingActionType.ADD_NEW_LINE), marks, state); - } - state = newState; -- if (state == 3 && cs.alignJavadocReturnDescription()) { -- toAdd = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, 3); -+ if (state == JavadocReformattingState.RETURN_DESCRIPTION && cs.alignJavadocReturnDescription()) { -+ marker = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, JavadocReformattingActionType.ALIGN_RETURN); - } - lastWSOffset = currWSOffset = -1; - break; - case IDENT: -- if (toAdd != null) { -- addMark(toAdd, marks, state); -- toAdd = null; -+ if (marker != null) { -+ addMark(marker, marks, state); -+ marker = null; - } - nlAdd = null; -- if (identStart < 0 && (state == 1 || state == 4)) -+ if (identStart < 0 && (state == JavadocReformattingState.AFTER_PARAM_TAG || state == JavadocReformattingState.AFTER_THROWS_TAG)) - identStart = javadocTokens.offset() - offset; - lastWSOffset = currWSOffset = -1; - afterText = true; - break; - case HTML_TAG: -- if (toAdd != null) { -- addMark(toAdd, marks, state); -+ if (marker != null) { -+ addMark(marker, marks, state); - } - nlAdd = null; - tokenText = javadocTokens.token().text().toString(); - if (tokenText.endsWith(">")) { //NOI18N - if (P_TAG.equalsIgnoreCase(tokenText) || END_P_TAG.equalsIgnoreCase(tokenText)) { -- if (currWSOffset >= 0 && currWSOffset > lastAddedNLOffset && (toAdd == null || toAdd.first() < currWSOffset)) { -- addMark(Pair.of(currWSOffset, 1), marks, state); -+ if (currWSOffset >= 0 && currWSOffset > lastAddedNLOffset && (marker == null || marker.first() < currWSOffset)) { -+ addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state); - } - lastAddedNLOffset = javadocTokens.offset() + javadocTokens.token().length() - offset; -- addMark(Pair.of(lastAddedNLOffset, 1), marks, state); -+ addMark(Pair.of(lastAddedNLOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state); - afterText = false; - } else if (PRE_TAG.equalsIgnoreCase(tokenText)) { -- if (currWSOffset >= 0 && state == 0 && (toAdd == null || toAdd.first() < currWSOffset)) { -- addMark(Pair.of(currWSOffset, 1), marks, state); -+ if (currWSOffset >= 0 && state == JavadocReformattingState.INITIAL_TEXT && (marker == null || marker.first() < currWSOffset)) { -+ addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state); - } -- addMark(Pair.of(javadocTokens.offset() - offset, 5), marks, state); -- state = 6; -+ addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state); -+ state = JavadocReformattingState.AFTER_PRE_TAG; - } else if (CODE_TAG.equalsIgnoreCase(tokenText)) { -- addMark(Pair.of(javadocTokens.offset() - offset, 5), marks, state); -+ addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state); - } else if (PRE_END_TAG.equalsIgnoreCase(tokenText)) { -- state = 0; -- addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, 6), marks, state); -+ state = JavadocReformattingState.INITIAL_TEXT; -+ addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, JavadocReformattingActionType.FORMAT), marks, state); - } else if (CODE_END_TAG.equalsIgnoreCase(tokenText)) { -- addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, 6), marks, state); -+ addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, JavadocReformattingActionType.FORMAT), marks, state); - } else { - if (currWSOffset >= 0 && lastNLOffset >= currWSOffset -- && lastAddedNLOffset < currWSOffset && (toAdd == null || toAdd.first() < currWSOffset)) { -- addMark(Pair.of(currWSOffset, 1), marks, state); -+ && lastAddedNLOffset < currWSOffset && (marker == null || marker.first() < currWSOffset)) { -+ addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state); - } -- addMark(Pair.of(javadocTokens.offset() - offset, 5), marks, state); -- addMark(Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset - 1, 6), marks, state); -- nlAdd = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, 1); -+ addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state); -+ addMark(Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset - 1, JavadocReformattingActionType.FORMAT), marks, state); -+ nlAdd = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, JavadocReformattingActionType.ADD_NEW_LINE); - } - } else { - cseq = new StringBuilder(tokenText); - } -- toAdd = null; -+ marker = null; - lastWSOffset = currWSOffset = -1; - break; - case OTHER_TEXT: -@@ -4937,9 +4950,9 @@ public class Reformatter implements ReformatTask { - } else { - nlFollows = false; - if (c != '*') { -- if (toAdd != null) { -- addMark(toAdd, marks, state); -- toAdd = null; -+ if (marker != null) { -+ addMark(marker, marks, state); -+ marker = null; - } else { - addNow = true; - } -@@ -4965,7 +4978,7 @@ public class Reformatter implements ReformatTask { - } - } - if (nlFollows && nlAdd != null) { -- toAdd = nlAdd; -+ marker = nlAdd; - } - nlAdd = null; - if (identStart >= 0) { -@@ -4976,52 +4989,52 @@ public class Reformatter implements ReformatTask { - break; - } - } -- if (state == 1) { -+ if (state == JavadocReformattingState.AFTER_PARAM_TAG) { - if (len > maxParamNameLength) - maxParamNameLength = len; - if (cs.alignJavadocParameterDescriptions()) -- toAdd = Pair.of(identStart + len, 2); -- state = 2; -- } else if (state == 4) { -+ marker = Pair.of(identStart + len, JavadocReformattingActionType.ALIGN_PARAMS); -+ state = JavadocReformattingState.PARAM_DESCRIPTION; -+ } else if (state == JavadocReformattingState.AFTER_THROWS_TAG) { - if (len > maxExcNameLength) - maxExcNameLength = len; - if (cs.alignJavadocExceptionDescriptions()) -- toAdd = Pair.of(identStart + len, 4); -- state = 5; -+ marker = Pair.of(identStart + len, JavadocReformattingActionType.ALIGN_EXCEPTIONS); -+ state = JavadocReformattingState.EXCEPTION_DESCRIPTION; - } -- if (addNow && toAdd != null) { -- addMark(toAdd, marks, state); -- toAdd = null; -+ if (addNow && marker != null) { -+ addMark(marker, marks, state); -+ marker = null; - } - identStart = -1; - } - if (insideTagEndOffset >= 0) { -- addMark(Pair.of(insideTagEndOffset, 6), marks, state); -+ addMark(Pair.of(insideTagEndOffset, JavadocReformattingActionType.FORMAT), marks, state); - } - cseq = null; - break; - default: -- if (toAdd != null) { -- addMark(toAdd, marks, state); -- toAdd = null; -+ if (marker != null) { -+ addMark(marker, marks, state); -+ marker = null; - } - nlAdd = null; - } - } - } -- int checkOffset, actionType; // 0 - add blank line, 1 - add newline, 2 - align params, 3 - align return, -- // 4 - align exceptions, 5 - no format, 6 - format -- Iterator> it = marks.iterator(); -- if (it.hasNext()) { -- Pair next = it.next(); -- checkOffset = next.first(); -+ int markedOffset; -+ JavadocReformattingActionType actionType; -+ Iterator> marksIterator = marks.iterator(); -+ if (marksIterator.hasNext()) { -+ Pair next = marksIterator.next(); -+ markedOffset = next.first(); - actionType = next.second(); - } else { -- checkOffset = Integer.MAX_VALUE; -- actionType = -1; -+ markedOffset = Integer.MAX_VALUE; -+ actionType = JavadocReformattingActionType.NONE; - } -- String indentString = getIndent(); -- String lineStartString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR + SPACE : indentString + SPACE; -+ final String indentString = getIndent(); -+ final String lineStartString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR + SPACE : indentString + SPACE; - String blankLineString; - int currNWSPos = -1; - int lastNWSPos = -1; -@@ -5100,16 +5113,16 @@ public class Reformatter implements ReformatTask { - } - firstLine = false; - } -- if (i >= checkOffset && actionType == 5) { -+ if (i >= markedOffset && actionType == JavadocReformattingActionType.NO_FORMAT) { - noFormat = true; - align = -1; -- if (it.hasNext()) { -- Pair next = it.next(); -- checkOffset = next.first(); -+ if (marksIterator.hasNext()) { -+ Pair next = marksIterator.next(); -+ markedOffset = next.first(); - actionType = next.second(); - } else { -- checkOffset = Integer.MAX_VALUE; -- actionType = -1; -+ markedOffset = Integer.MAX_VALUE; -+ actionType = JavadocReformattingActionType.NONE; - } - } - } else { -@@ -5123,23 +5136,23 @@ public class Reformatter implements ReformatTask { - if (currNWSPos < 0) { - currNWSPos = i; - } -- if (i >= checkOffset) { -+ if (i >= markedOffset) { - noFormat = false; - switch (actionType) { -- case 0: -+ case ADD_BLANK_LINE: - pendingDiff = new Diff(currWSPos >= 0 ? offset + currWSPos : offset + i, offset + i, NEWLINE + blankLineString + NEWLINE); - lastNewLinePos = i - 1; - preserveNewLines = true; - align = -1; - break; -- case 1: -+ case ADD_NEW_LINE: - pendingDiff = new Diff(currWSPos >= 0 ? offset + currWSPos : offset + i, offset + i, NEWLINE); - lastNewLinePos = i - 1; - preserveNewLines = true; - align = -1; - break; -- case 2: -- col += (maxParamNameLength + lastNWSPos- currWSPos); -+ case ALIGN_PARAMS: -+ col += (maxParamNameLength + lastNWSPos - currWSPos); - align = col; - currWSPos = -1; - if (lastNewLinePos < 0) { -@@ -5151,11 +5164,11 @@ public class Reformatter implements ReformatTask { - } - } - break; -- case 3: -+ case ALIGN_RETURN: - align = col; - break; -- case 4: -- col += (maxExcNameLength + lastNWSPos- currWSPos); -+ case ALIGN_EXCEPTIONS: -+ col += (maxExcNameLength + lastNWSPos - currWSPos); - align = col; - currWSPos = -1; - if (lastNewLinePos < 0) { -@@ -5167,22 +5180,22 @@ public class Reformatter implements ReformatTask { - } - } - break; -- case 5: -+ case NO_FORMAT: - noFormat = true; - if (currWSPos > 0) - lastWSPos = currWSPos; - break; -- case 6: -+ case FORMAT: - preserveNewLines = true; - break; - } -- if (it.hasNext()) { -- Pair next = it.next(); -- checkOffset = next.first(); -+ if (marksIterator.hasNext()) { -+ Pair next = marksIterator.next(); -+ markedOffset = next.first(); - actionType = next.second(); - } else { -- checkOffset = Integer.MAX_VALUE; -- actionType = -1; -+ markedOffset = Integer.MAX_VALUE; -+ actionType = JavadocReformattingActionType.NONE; - } - } - } -@@ -5287,16 +5300,16 @@ public class Reformatter implements ReformatTask { - lastNewLinePos = -1; - break; - } else { -- if (i >= checkOffset && actionType == 6) { -+ if (i >= markedOffset && actionType == JavadocReformattingActionType.FORMAT) { - noFormat = false; - preserveNewLines = true; -- if (it.hasNext()) { -- Pair next = it.next(); -- checkOffset = next.first(); -+ if (marksIterator.hasNext()) { -+ Pair next = marksIterator.next(); -+ markedOffset = next.first(); - actionType = next.second(); - } else { -- checkOffset = Integer.MAX_VALUE; -- actionType = -1; -+ markedOffset = Integer.MAX_VALUE; -+ actionType = JavadocReformattingActionType.NONE; - } - } - if (!cs.addLeadingStarInComment()) { -@@ -5411,8 +5424,17 @@ public class Reformatter implements ReformatTask { - } - } - -- private void addMark(Pair mark, List> marks, int state) { -- if (state != 6) { -+ /** -+ * -+ * @see for more info on inline tags check documentation here. -+ * @return returns true if has inline tag prefix like "{+@tagname" -+ */ -+ private static boolean hasInlineTagPrefix(String commentsText, String tokenText ,int tagTokenStartOffset) { -+ return commentsText.startsWith("{"+tokenText, tagTokenStartOffset-1); -+ } -+ -+ private void addMark(Pair mark, List> marks, JavadocReformattingState state) { -+ if (state != JavadocReformattingState.AFTER_PRE_TAG) { - marks.add(mark); - } - } -diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java -index c11be84ffc76..be95039cc4d9 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java -@@ -5201,6 +5201,47 @@ public class FormatingTest extends NbTestCase { - + "}\n"; - reformat(doc, content, golden); - -+ content = "package hierbas.del.litoral;\n" + -+ "\n" + -+ "public class Test{\n" + -+ "/**{@return foo bar method} */ String bar() { \n" + -+ " return null; \n" + -+ " }\n" + -+ "}"; -+ golden ="package hierbas.del.litoral;\n" + -+ "\n" + -+ "public class Test {\n" + -+ "\n" + -+ " /**\n" + -+ " * {@return foo bar method}\n" + -+ " */\n" + -+ " String bar() {\n" + -+ " return null;\n" + -+ " }\n" + -+ "}\n"; -+ reformat(doc, content, golden); -+ -+ content ="package hierbas.del.litoral;\n" + -+ "\n" + -+ "public class Test{\n" + -+ "/** bar method description {@return foo bar method} */ String bar() { \n" + -+ " return null; \n" + -+ " }\n" + -+ "}"; -+ golden ="package hierbas.del.litoral;\n" + -+ "\n" + -+ "public class Test {\n" + -+ "\n" + -+ " /**\n" + -+ " * bar method description\n" + -+ " * {@return foo bar method}\n" + -+ " */\n" + -+ " String bar() {\n" + -+ " return null;\n" + -+ " }\n" + -+ "}\n"; -+ reformat(doc, content, golden); -+ - content = - "package hierbas.del.litoral;\n" - + "\n" diff --git a/patches/7654.diff b/patches/7654.diff deleted file mode 100644 index dee812c8..00000000 --- a/patches/7654.diff +++ /dev/null @@ -1,379 +0,0 @@ -diff --git a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -index 78fdd4caa3..f8869882aa 100644 ---- a/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -+++ b/java/java.completion/src/org/netbeans/modules/java/completion/BaseTask.java -@@ -260,6 +260,8 @@ abstract class BaseTask extends UserTask { - && (ts.token().id() == JavaTokenId.IDENTIFIER - || ts.token().id().primaryCategory().startsWith("keyword") || //NOI18N - ts.token().id().primaryCategory().startsWith("string") || //NOI18N -+ ts.token().id().primaryCategory().equals("number") || //NOI18N -+ ts.token().id().primaryCategory().equals("character") || //NOI18N - ts.token().id().primaryCategory().equals("literal"))) { //NOI18N - offset++; - } -@@ -279,6 +281,10 @@ abstract class BaseTask extends UserTask { - treePath = treePath.getParentPath(); - } - } else { -+ TreePath newClassPath = findNewClassForConstructorName(path); -+ if (newClassPath != null) { -+ path = newClassPath; -+ } - if (JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) { - LinkedList reversePath = new LinkedList<>(); - TreePath treePath = path; -@@ -299,6 +305,34 @@ abstract class BaseTask extends UserTask { - return new Env(offset, prefix, controller, path, controller.getTrees().getSourcePositions(), null); - } - -+ private TreePath findNewClassForConstructorName(TreePath tp) { -+ if (tp == null) { -+ return null; -+ } -+ -+ TreePath parentPath = tp.getParentPath(); -+ -+ while (parentPath != null) { -+ boolean goUp = false; -+ goUp = goUp || (parentPath.getLeaf().getKind() == Kind.PARAMETERIZED_TYPE && -+ ((ParameterizedTypeTree) parentPath.getLeaf()).getType() == tp.getLeaf()); -+ goUp = goUp || (parentPath.getLeaf().getKind() == Kind.ANNOTATED_TYPE && -+ ((AnnotatedTypeTree) parentPath.getLeaf()).getUnderlyingType() == tp.getLeaf()); -+ if (goUp) { -+ tp = parentPath; -+ parentPath = parentPath.getParentPath(); -+ } else { -+ break; -+ } -+ } -+ -+ if (parentPath != null && parentPath.getLeaf().getKind() == Kind.NEW_CLASS && ((NewClassTree) parentPath.getLeaf()).getIdentifier() == tp.getLeaf()) { -+ return parentPath; -+ } -+ -+ return null; -+ } -+ - private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath path, TreePath pPath, TreePath gpPath, int offset, String prefix, boolean upToOffset) throws IOException { - Tree tree = path != null ? path.getLeaf() : null; - Tree parent = pPath != null ? pPath.getLeaf() : null; -diff --git a/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java -new file mode 100644 -index 0000000000..2d85997e34 ---- /dev/null -+++ b/java/java.completion/test/unit/src/org/netbeans/modules/java/completion/JavaDocumentationTaskTest.java -@@ -0,0 +1,247 @@ -+/* -+ * Licensed to the Apache Software Foundation (ASF) under one -+ * or more contributor license agreements. See the NOTICE file -+ * distributed with this work for additional information -+ * regarding copyright ownership. The ASF licenses this file -+ * to you under the Apache License, Version 2.0 (the -+ * "License"); you may not use this file except in compliance -+ * with the License. You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, -+ * software distributed under the License is distributed on an -+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -+ * KIND, either express or implied. See the License for the -+ * specific language governing permissions and limitations -+ * under the License. -+ */ -+ -+package org.netbeans.modules.java.completion; -+ -+import java.io.File; -+import java.io.FileWriter; -+import java.io.IOException; -+import java.io.Writer; -+import java.util.*; -+import java.util.concurrent.Callable; -+ -+import javax.lang.model.element.*; -+import javax.lang.model.type.ArrayType; -+import javax.lang.model.type.DeclaredType; -+import javax.lang.model.type.ExecutableType; -+import javax.lang.model.type.TypeKind; -+import javax.lang.model.type.TypeMirror; -+import javax.lang.model.util.Elements; -+import javax.swing.text.Document; -+ -+import org.netbeans.api.java.lexer.JavaTokenId; -+import org.netbeans.api.java.source.*; -+import org.netbeans.api.java.source.support.ReferencesCount; -+import org.netbeans.api.lexer.Language; -+import org.netbeans.modules.parsing.api.ParserManager; -+import org.netbeans.modules.parsing.api.Source; -+import org.openide.LifecycleManager; -+import org.openide.cookies.EditorCookie; -+import org.openide.filesystems.FileObject; -+import org.openide.filesystems.FileUtil; -+import org.openide.loaders.DataObject; -+import org.openide.util.lookup.ServiceProvider; -+import org.openide.xml.EntityCatalog; -+import org.xml.sax.InputSource; -+import org.xml.sax.SAXException; -+ -+/** -+ * -+ * @author Dusan Balek, Jan Lahoda -+ */ -+public class JavaDocumentationTaskTest extends CompletionTestBaseBase { -+ -+ public JavaDocumentationTaskTest(String testName) { -+ super(testName, "org/netbeans/modules/java/completion/JavaDocumentationTaskTest"); -+ } -+ -+ public void testConstructor() throws Exception { -+ performTest("import java.util.*;\n" + -+ "public class Test {\n" + -+ " List l = new Array|List();\n" + -+ "}\n", -+ "", -+ "11", -+ "[java.util.ArrayList, , ()V]"); -+ } -+ -+ public void testConstructorDiamond() throws Exception { -+ performTest("import java.util.*;\n" + -+ "public class Test {\n" + -+ " List l = new Array|List<>();\n" + -+ "}\n", -+ "", -+ "11", -+ "[java.util.ArrayList, , ()V]"); -+ } -+ -+ public void testConstructorTypeParams1() throws Exception { -+ performTest("import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new Array|List();\n"+ -+ "}\n", -+ "", -+ "11", -+ "[java.util.ArrayList, , ()V]"); -+ } -+ -+ public void testConstructorTypeParams2() throws Exception { -+ performTest("import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new ArrayList();\n"+ -+ "}\n", -+ "", -+ "11", -+ "[java.lang.String]"); -+ } -+ -+ public void testConstructorAnnotation1() throws Exception { -+ performTest("import java.lang.annotation.ElementType;\n"+ -+ "import java.lang.annotation.Target;\n"+ -+ "import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new @Ann Array|List();\n"+ -+ "}\n"+ -+ "@Target(ElementType.TYPE_USE)\n"+ -+ "@interface Ann {}\n", -+ "", -+ "11", -+ "[java.util.ArrayList, , ()V]"); -+ } -+ -+ public void testConstructorAnnotation2() throws Exception { -+ performTest("import java.lang.annotation.ElementType;\n"+ -+ "import java.lang.annotation.Target;\n"+ -+ "import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new @An|n ArrayList();\n"+ -+ "}\n"+ -+ "@Target(ElementType.TYPE_USE)\n"+ -+ "@interface Ann {}\n", -+ "", -+ "11", -+ "[Ann]"); -+ } -+ -+ public void testConstructorAnnotationTypeParams1() throws Exception { -+ performTest("import java.lang.annotation.ElementType;\n"+ -+ "import java.lang.annotation.Target;\n"+ -+ "import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new @Ann Array|List();\n"+ -+ "}\n"+ -+ "@Target(ElementType.TYPE_USE)\n"+ -+ "@interface Ann {}\n", -+ "", -+ "11", -+ "[java.util.ArrayList, , ()V]"); -+ } -+ -+ public void testConstructorAnnotationTypeParams2() throws Exception { -+ performTest("import java.lang.annotation.ElementType;\n"+ -+ "import java.lang.annotation.Target;\n"+ -+ "import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new @An|n ArrayList();\n"+ -+ "}\n"+ -+ "@Target(ElementType.TYPE_USE)\n"+ -+ "@interface Ann {}\n", -+ "", -+ "11", -+ "[Ann]"); -+ } -+ -+ public void testConstructorAnnotationTypeParams3() throws Exception { -+ performTest("import java.lang.annotation.ElementType;\n"+ -+ "import java.lang.annotation.Target;\n"+ -+ "import java.util.*;\n"+ -+ "public class Test {\n"+ -+ " List l = new @Ann ArrayList();\n"+ -+ "}\n"+ -+ "@Target(ElementType.TYPE_USE)\n"+ -+ "@interface Ann {}\n", -+ "", -+ "11", -+ "[java.lang.String]"); -+ } -+ -+ public void testConstructorIntegerArgument() throws Exception { -+ performTest("public class Test {\n" + -+ "/**\n"+ -+ "This is constructor level Javadoc\n"+ -+ "**/\n"+ -+ "Test(int i){}\n"+ -+ " public static void main(String[] args) {\n"+ -+ " Test t = new Test(|10000);\n" + -+ " }\n" + -+ "}\n", -+ "", -+ "11", -+ null); -+ } -+ -+ public void testConstructorCharacterArgument() throws Exception { -+ performTest("public class Test {\n" + -+ "/**\n"+ -+ "This is constructor level Javadoc\n"+ -+ "**/\n"+ -+ "Test(char c){}\n"+ -+ " public static void main(String[] args) {\n"+ -+ " Test t = new Test(|'x');\n" + -+ " }\n" + -+ "}\n", -+ "", -+ "11", -+ null); -+ } -+ -+ protected void performTest(String source, String textToInsert, String sourceLevel, String expected) throws Exception { -+ this.sourceLevel.set(sourceLevel); -+ int caretPos = source.indexOf("|"); -+ assertTrue(caretPos != (-1)); -+ String code = source.substring(0, caretPos) + source.substring(caretPos + 1); -+ File testSource = new File(getWorkDir(), "test/Test.java"); -+ testSource.getParentFile().mkdirs(); -+ try (Writer w = new FileWriter(testSource)) { -+ w.write(code); -+ } -+ FileObject testSourceFO = FileUtil.toFileObject(testSource); -+ assertNotNull(testSourceFO); -+ DataObject testSourceDO = DataObject.find(testSourceFO); -+ assertNotNull(testSourceDO); -+ EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); -+ assertNotNull(ec); -+ final Document doc = ec.openDocument(); -+ assertNotNull(doc); -+ doc.putProperty(Language.class, JavaTokenId.language()); -+ doc.putProperty("mimeType", "text/x-java"); -+ int textToInsertLength = textToInsert != null ? textToInsert.length() : 0; -+ if (textToInsertLength > 0) { -+ doc.insertString(caretPos, textToInsert, null); -+ } -+ Source s = Source.create(doc); -+ JavaDocumentationTask task = JavaDocumentationTask.create(caretPos + textToInsertLength, null, new StringFactory(), null); -+ ParserManager.parse(Collections.singletonList(s), task); -+ String documentation = task.getDocumentation(); -+ -+ assertEquals(expected, documentation); -+ -+ LifecycleManager.getDefault().saveAll(); -+ } -+ -+ private static class StringFactory implements JavaDocumentationTask.DocumentationFactory { -+ -+ @Override -+ public String create(CompilationInfo compilationInfo, Element element, Callable cancel) { -+ return Arrays.toString(SourceUtils.getJVMSignature(ElementHandle.create(element))); -+ } -+ -+ } -+ -+} -diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -index 4fce71a094..684f5db0a2 100644 ---- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -@@ -1362,11 +1362,15 @@ public class ServerTest extends NbTestCase { - File src = new File(getWorkDir(), "Test.java"); - src.getParentFile().mkdirs(); - String code = "/**\n" + -- " * This is a test class with Javadoc.\n" + -+ " * This is a class level Javadoc.\n" + - " */\n" + - "public class Test {\n" + -- " public static void main(String[] args) {\n" + -- " Test t = new Test();\n" + -+ "/**\n"+ -+ "This is constructor level Javadoc\n"+ -+ "**/\n"+ -+ "Test(int i){}\n"+ -+ " public static void main(String[] args) {\n"+ -+ " Test t = new Test(10000);\n" + - " }\n" + - "}\n"; - try (Writer w = new FileWriter(src)) { -@@ -1401,18 +1405,35 @@ public class ServerTest extends NbTestCase { - InitializeResult result = server.initialize(new InitializeParams()).get(); - assertTrue(result.getCapabilities().getHoverProvider().isLeft() && result.getCapabilities().getHoverProvider().getLeft()); - server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code))); -- Hover hover = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(5, 10))).get(); -- assertNotNull(hover); -- assertTrue(hover.getContents().isRight()); -- MarkupContent content = hover.getContents().getRight(); -- assertNotNull(content); -- assertEquals(content.getKind(), "markdown"); -- assertEquals(content.getValue(), "```\n" + -+ Hover hoverClass = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 10))).get(); -+ Hover hoverConstructor = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 23))).get(); -+ Hover hoverIntegerArgument = server.getTextDocumentService().hover(new HoverParams(new TextDocumentIdentifier(toURI(src)), new Position(9, 26))).get(); -+ assertNotNull(hoverClass); -+ assertNotNull(hoverConstructor); -+ assertNull(hoverIntegerArgument); -+ assertTrue(hoverConstructor.getContents().isRight()); -+ assertTrue(hoverClass.getContents().isRight()); -+ MarkupContent classContent = hoverClass.getContents().getRight(); -+ MarkupContent constructorContent = hoverConstructor.getContents().getRight(); -+ assertNotNull(classContent); -+ assertNotNull(constructorContent); -+ assertEquals(classContent.getKind(), "markdown"); -+ assertEquals(constructorContent.getKind(), "markdown"); -+ assertEquals(classContent.getValue(), "```\n" + - "public class Test\n" + - "extends Object\n" + - "```\n" + - "\n" + -- "This is a test class with Javadoc.\n" + -+ "This is a class level Javadoc.\n" + -+ "\n"); -+ assertEquals(constructorContent.getValue(), -+ "**Test**\n"+ -+ "\n"+ -+ "```\n" + -+ "Test(int i)\n" + -+ "```\n" + -+ "\n" + -+ "This is constructor level Javadoc\n" + - "\n"); - } - diff --git a/patches/7670.diff b/patches/7670.diff deleted file mode 100644 index 486c231c..00000000 --- a/patches/7670.diff +++ /dev/null @@ -1,2037 +0,0 @@ -diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java -index 0901d96e3fd8..60255382e069 100644 ---- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java -+++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/Utilities.java -@@ -268,16 +268,24 @@ private static Token findIdentifierSpanImpl(CompilationInfo info, T - - if (class2Kind.get(MethodTree.class).contains(leaf.getKind())) { - MethodTree method = (MethodTree) leaf; -+ TreePath parentPath = decl.getParentPath(); - List rightTrees = new ArrayList(); - -- rightTrees.addAll(method.getParameters()); -+ boolean ignoreParameters = parentPath.getLeaf().getKind() == Kind.RECORD && -+ !method.getParameters().isEmpty() && -+ info.getTreeUtilities().isSynthetic(new TreePath(decl, method.getParameters().get(0))); -+ -+ if (!ignoreParameters) { -+ rightTrees.addAll(method.getParameters()); -+ } -+ - rightTrees.addAll(method.getThrows()); - rightTrees.add(method.getBody()); - - Name name = method.getName(); - - if (method.getReturnType() == null) -- name = ((ClassTree) decl.getParentPath().getLeaf()).getSimpleName(); -+ name = ((ClassTree) parentPath.getLeaf()).getSimpleName(); - - return findIdentifierSpanImpl(info, leaf, method.getReturnType(), rightTrees, name.toString(), info.getCompilationUnit(), info.getTrees().getSourcePositions()); - } -diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java -index 29b188e84bab..205680824678 100644 ---- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java -+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java -@@ -349,6 +349,36 @@ public void testMatchBindings() throws Exception { - "[MARK_OCCURRENCES], 3:30-3:33"); - } - -+ public void testRecordCompactConstructors1() throws Exception { -+ performTest("MatchBindings.java", -+ "public record MatchBindings(String compact) {\n" + -+ " public MatchBindings {\n" + -+ " }\n" + -+ " private static MatchBindings create() {\n" + -+ " return new MatchBindings(null);\n" + -+ " }\n" + -+ "}\n", -+ 1, -+ 20, -+ "[MARK_OCCURRENCES], 1:11-1:24", -+ "[MARK_OCCURRENCES], 4:19-4:32"); -+ } -+ -+ public void testRecordCompactConstructors2() throws Exception { -+ performTest("MatchBindings.java", -+ "public record MatchBindings(String compact) {\n" + -+ " public MatchBindings {\n" + -+ " }\n" + -+ " private static MatchBindings create() {\n" + -+ " return new MatchBindings(null);\n" + -+ " }\n" + -+ "}\n", -+ 4, -+ 20, -+ "[MARK_OCCURRENCES], 1:11-1:24", -+ "[MARK_OCCURRENCES], 4:19-4:32"); -+ } -+ - //Support for exotic identifiers has been removed 6999438 - public void REMOVEDtestExoticIdentifiers1() throws Exception { - performTest("ExoticIdentifier", 3, 43); -diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformer.java b/java/java.editor/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformer.java -index 5e775e157aea..2622a86c9a33 100644 ---- a/java/java.editor/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformer.java -+++ b/java/java.editor/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformer.java -@@ -451,6 +451,9 @@ private static boolean allowInstantRename(CompilationInfo info, Element e, Eleme - return false; - } - } -+ if (info.getElementUtilities().getLinkedRecordElements(e).size() > 1) { -+ return false; -+ } - if (org.netbeans.modules.java.editor.base.semantic.Utilities.isPrivateElement(e)) { - return true; - } -diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenameActionTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenameActionTest.java -index fa1439d916c7..ebe1fcedad9e 100644 ---- a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenameActionTest.java -+++ b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenameActionTest.java -@@ -297,6 +297,16 @@ public void testIsInaccessibleOutsideOuterClassForAnnTypeMethodOfPrivateNestedCl - validateChangePoints(changePoints, 87, 93); - } - -+ public void testNoInstanceRenameForRecordComponents() throws Exception { -+ sourceLevel = "17"; -+ -+ boolean[] wasResolved = new boolean[1]; -+ Collection changePoints = performTest("package test; public class Test { private record Rec(String component) { } }", 120 - 55, wasResolved); -+ -+ assertNull(changePoints); -+ assertTrue(wasResolved[0]); -+ } -+ - private void validateChangePoints(Collection changePoints, int... origs) { - Set awaited = new HashSet(); - -@@ -345,6 +355,7 @@ public String toString() { - } - - private FileObject source; -+ private String sourceLevel; - - private Collection performTest(String sourceCode, final int offset, boolean[] wasResolved) throws Exception { - FileObject root = makeScratchDir(this); -@@ -358,7 +369,11 @@ private Collection performTest(String sourceCode, final int offset, boole - writeIntoFile(source, sourceCode); - - SourceUtilsTestUtil.prepareTest(sourceDir, buildDir, cacheDir, new FileObject[0]); -- -+ -+ if (sourceLevel != null) { -+ SourceUtilsTestUtil.setSourceLevel(sourceDir, sourceLevel); -+ } -+ - DataObject od = DataObject.find(source); - EditorCookie ec = od.getCookie(EditorCookie.class); - Document doc = ec.openDocument(); -diff --git a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformerTest.java b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformerTest.java -index 4930bfaa9194..cf7697002067 100644 ---- a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformerTest.java -+++ b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/rename/InstantRenamePerformerTest.java -@@ -56,7 +56,9 @@ - * @author lahvac - */ - public class InstantRenamePerformerTest extends NbTestCase { -- -+ -+ private String sourceLevel; -+ - public InstantRenamePerformerTest(String testName) { - super(testName); - } -@@ -193,6 +195,13 @@ public void testPatternBinding() throws Exception { - performTest("package test; public class Test { public void test(Object o) {boolean b = o instanceof String s|tr && str.isEmpty(); } }", 117 - 22, ke, "package test; public class Test { public void test(Object o) {boolean b = o instanceof String satr && satr.isEmpty(); } }", true); - } - -+ public void testRecordWithCompactConstructor1() throws Exception { -+ sourceLevel = "17"; -+ -+ KeyEvent ke = new KeyEvent(new JFrame(), KeyEvent.KEY_TYPED, 0, 0, KeyEvent.VK_UNDEFINED, 'e'); -+ performTest("package test; public class Test { private record R|c(String str) { public Rc {} } }", 72 - 22, ke, - 1, "package test; public class Test { private record Rec(String str) { public Rec {} } }", true); -+ } -+ - private void performTest(String sourceCode, int offset, KeyEvent ke, String golden, boolean stillInRename) throws Exception { - performTest(sourceCode, offset, ke, -1, golden, stillInRename); - } -@@ -217,6 +226,9 @@ private void performTest(String sourceCode, int offset, KeyEvent[] kes, int sele - TestUtilities.copyStringToFile(source, sourceCode.replaceFirst(Pattern.quote("|"), "")); - - SourceUtilsTestUtil.prepareTest(sourceDir, buildDir, cacheDir, new FileObject[0]); -+ if (sourceLevel != null) { -+ SourceUtilsTestUtil.setSourceLevel(sourceDir, sourceLevel); -+ } - SourceUtilsTestUtil.compileRecursively(sourceDir); - - DataObject od = DataObject.find(source); -diff --git a/java/java.source.base/apichanges.xml b/java/java.source.base/apichanges.xml -index 8b5551495cf2..820ac01a8ab9 100644 ---- a/java/java.source.base/apichanges.xml -+++ b/java/java.source.base/apichanges.xml -@@ -25,6 +25,18 @@ - Java Source API - - -+ -+ -+

Adding TreeMaker.RecordComponent -+ -+ -+ -+ -+ -+ Adding TreeMaker.RecordComponent and ElementUtilities.getLinkedRecordElements. -+ -+ -+ - - - Adding TreeMaker.StringTemplate -diff --git a/java/java.source.base/nbproject/project.properties b/java/java.source.base/nbproject/project.properties -index 170637154f..7d9fff6702 100644 ---- a/java/java.source.base/nbproject/project.properties -+++ b/java/java.source.base/nbproject/project.properties -@@ -18,12 +18,12 @@ - #javac.compilerargs=-Xlint:unchecked - nbroot=../.. - is.autoload=true --javac.source=1.8 -+javac.release=17 - javadoc.name=Java Source Base - javadoc.title=Java Source Base - javadoc.arch=${basedir}/arch.xml - javadoc.apichanges=${basedir}/apichanges.xml --spec.version.base=2.68.0 -+spec.version.base=2.70.0 - test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar - test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\ - ${o.n.core.dir}/lib/boot.jar:\ -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/ElementHandle.java b/java/java.source.base/src/org/netbeans/api/java/source/ElementHandle.java -index c17c623259a9..076e41c446ae 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/ElementHandle.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/ElementHandle.java -@@ -235,7 +235,7 @@ private T resolveImpl (final ModuleElement module, final JavacTaskImpl jt) { - } - case PARAMETER: - { -- assert signatures.length == 3; -+ assert signatures.length == 4; - final Element type = getTypeElementByBinaryName (module, signatures[0], jt); - if (type instanceof TypeElement) { - final List members = type.getEnclosedElements(); -@@ -526,7 +526,12 @@ public static ElementHandle createModuleElementHandle( - ElementKind eek = ee.getKind(); - if (eek == ElementKind.METHOD || eek == ElementKind.CONSTRUCTOR) { - assert ee instanceof ExecutableElement; -- String[] _sigs = ClassFileUtil.createExecutableDescriptor((ExecutableElement)ee); -+ ExecutableElement eel = (ExecutableElement)ee; -+ if (!eel.getParameters().contains(element)) { -+ //may be e.g. a lambda parameter: -+ throw new IllegalArgumentException("Not a parameter for a method or a constructor."); -+ } -+ String[] _sigs = ClassFileUtil.createExecutableDescriptor(eel); - signatures = new String[_sigs.length + 1]; - System.arraycopy(_sigs, 0, signatures, 0, _sigs.length); - signatures[_sigs.length] = element.getSimpleName().toString(); -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java -index 11001a9037d6..2a178ca9507e 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java -@@ -60,6 +60,7 @@ - import java.util.ListIterator; - import java.util.Map; - import java.util.Set; -+import java.util.function.Supplier; - - import javax.lang.model.element.Element; - import javax.lang.model.element.ElementKind; -@@ -928,7 +929,143 @@ public ExecutableElement getDescriptorElement(TypeElement origin) { - } - return null; - } -- -+ -+ /** -+ * Find all elements that are linked record elements for the given input. Will -+ * return the record component element, field, accessor method, and canonical constructor -+ * parameters. -+ * -+ * This method can be called on any {@code Element}, and will return a collection -+ * with a single entry if the provided element is not a record element. -+ * -+ * @param forElement for which the linked elements should be found -+ * @return a collection containing the provided element, plus any additional elements -+ * that are linked to it by the Java record specification -+ * @since 2.70 -+ */ -+ public Collection getLinkedRecordElements(Element forElement) { -+ Parameters.notNull("forElement", forElement); -+ -+ TypeElement record = null; -+ Name componentName = null; -+ -+ switch (forElement.getKind()) { -+ case FIELD -> { -+ Element enclosing = forElement.getEnclosingElement(); -+ if (enclosing.getKind() == ElementKind.RECORD) { -+ record = (TypeElement) enclosing; -+ componentName = forElement.getSimpleName(); -+ } -+ } -+ case PARAMETER -> { -+ Element enclosing = forElement.getEnclosingElement(); -+ if (enclosing.getKind() == ElementKind.CONSTRUCTOR) { -+ Element enclosingType = enclosing.getEnclosingElement(); -+ if (enclosingType.getKind() == ElementKind.RECORD) { -+ TypeElement recordType = (TypeElement) enclosingType; -+ ExecutableElement constructor = recordCanonicalConstructor(recordType); -+ if (constructor != null && constructor.equals(enclosing)) { -+ int idx = constructor.getParameters().indexOf(forElement); -+ if (idx >= 0 && idx < recordType.getRecordComponents().size()) { -+ RecordComponentElement component = recordType.getRecordComponents().get(idx); -+ if (component.getSimpleName().equals(forElement.getSimpleName())) { -+ record = recordType; -+ componentName = component.getSimpleName(); -+ } -+ } -+ } -+ } -+ } -+ } -+ case METHOD -> { -+ Element enclosing = forElement.getEnclosingElement(); -+ ExecutableElement method = (ExecutableElement) forElement; -+ if (method.getParameters().isEmpty() && enclosing.getKind() == ElementKind.RECORD) { -+ TypeElement recordType = (TypeElement) enclosing; -+ for (RecordComponentElement component : recordType.getRecordComponents()) { -+ if (forElement.equals(component.getAccessor())) { -+ record = recordType; -+ componentName = component.getSimpleName(); -+ } -+ } -+ } -+ } -+ case RECORD_COMPONENT -> { -+ record = (TypeElement) forElement.getEnclosingElement(); -+ componentName = forElement.getSimpleName(); -+ } -+ } -+ -+ if (record == null) { -+ return Collections.singleton(forElement); -+ } -+ -+ RecordComponentElement component = null; -+ int componentIdx = 0; -+ -+ for (RecordComponentElement c : record.getRecordComponents()) { -+ if (c.getSimpleName().equals(componentName)) { -+ component = c; -+ break; -+ } -+ componentIdx++; -+ } -+ -+ if (component == null) { -+ //erroneous state(?), ignore: -+ return Collections.singleton(forElement); -+ } -+ -+ Set result = new HashSet<>(); -+ -+ result.add(component); -+ result.add(component.getAccessor()); -+ -+ for (Element el : record.getEnclosedElements()) { -+ if (el.getKind() == ElementKind.FIELD && el.getSimpleName().equals(componentName)) { -+ result.add(el); -+ break; -+ } -+ } -+ -+ ExecutableElement canonicalConstructor = recordCanonicalConstructor(record); -+ if (canonicalConstructor != null && componentIdx < canonicalConstructor.getParameters().size()) { -+ result.add(canonicalConstructor.getParameters().get(componentIdx)); -+ } -+ -+ return result; -+ } -+ -+ private ExecutableElement recordCanonicalConstructor(TypeElement recordType) { -+ Supplier fallback = -+ () -> { -+ List recordComponents = recordType.getRecordComponents(); -+ for (ExecutableElement c : ElementFilter.constructorsIn(recordType.getEnclosedElements())) { -+ if (recordComponents.size() == c.getParameters().size()) { -+ Iterator componentIt = recordComponents.iterator(); -+ Iterator parameterIt = c.getParameters().iterator(); -+ boolean componentMatches = true; -+ -+ while (componentIt.hasNext() && parameterIt.hasNext() && componentMatches) { -+ TypeMirror componentType = componentIt.next().asType(); -+ TypeMirror parameterType = parameterIt.next().asType(); -+ -+ componentMatches &= info.getTypes().isSameType(componentType, parameterType); -+ } -+ if (componentMatches) { -+ return c; -+ } -+ } -+ } -+ return null; -+ }; -+ return ElementFilter.constructorsIn(recordType.getEnclosedElements()) -+ .stream() -+ .filter(info.getElements()::isCanonicalConstructor) -+ .findAny() -+ .orElseGet(fallback); -+ } -+ - // private implementation -------------------------------------------------- - - private static final Set NOT_OVERRIDABLE = EnumSet.of(Modifier.STATIC, Modifier.FINAL, Modifier.PRIVATE); -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/TreeMaker.java b/java/java.source.base/src/org/netbeans/api/java/source/TreeMaker.java -index 6b8b05e16e79..4f7d8beb50c9 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/TreeMaker.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/TreeMaker.java -@@ -1277,6 +1277,21 @@ public VariableTree Variable(ModifiersTree modifiers, - return delegate.Variable(modifiers, name, type, initializer); - } - -+ /** -+ * Creates a new VariableTree for a record component. -+ * -+ * @param modifiers the modifiers of this record component. -+ * @param name the name of the record component. -+ * @param type the type of this record component. -+ * @see com.sun.source.tree.VariableTree -+ * @since 2.70 -+ */ -+ public VariableTree RecordComponent(ModifiersTree modifiers, -+ CharSequence name, -+ Tree type) { -+ return delegate.RecordComponent(modifiers, name, type); -+ } -+ - /** - * Creates a new BindingPatternTree. - * @deprecated -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/TreePathHandle.java b/java/java.source.base/src/org/netbeans/api/java/source/TreePathHandle.java -index 286427f834cd..14b097f0afb8 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/TreePathHandle.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/TreePathHandle.java -@@ -41,6 +41,7 @@ - - import javax.lang.model.element.Element; - import javax.lang.model.element.ElementKind; -+import javax.lang.model.element.ExecutableElement; - import javax.lang.model.element.Modifier; - import javax.lang.model.element.Name; - import javax.lang.model.element.TypeElement; -@@ -322,6 +323,14 @@ private static boolean isSupported(Element el) { - case RECORD: - //TODO: record component - return true; -+ case PARAMETER: -+ //only method and constructor parameters supported (not lambda): -+ if (el.getEnclosingElement().getKind() == ElementKind.METHOD || -+ el.getEnclosingElement().getKind() == ElementKind.CONSTRUCTOR) { -+ return ((ExecutableElement) el.getEnclosingElement()).getParameters().contains(el); -+ } else { -+ return false; -+ } - default: - return false; - } -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -index a7453c44778e..737c3d6ad0d6 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/TreeUtilities.java -@@ -185,8 +185,8 @@ public boolean isExpressionStatement(ExpressionTree tree) { - } - - /**Returns whether or not the given tree is synthetic - generated by the parser. -- * Please note that this method does not check trees transitively - a child of a syntetic tree -- * may be considered non-syntetic. -+ * Please note that this method does not check trees transitively - a child of a synthetic tree -+ * may be considered non-synthetic. - * - * @return true if the given tree is synthetic, false otherwise - * @throws NullPointerException if the given tree is null -@@ -210,6 +210,16 @@ public boolean isSynthetic(TreePath path) throws NullPointerException { - return true; - } - } -+ if (path.getLeaf().getKind() == Kind.VARIABLE && -+ path.getParentPath() != null && -+ path.getParentPath().getLeaf().getKind() == Kind.METHOD && -+ path.getParentPath().getParentPath() != null && -+ path.getParentPath().getParentPath().getLeaf().getKind() == Kind.RECORD) { -+ JCMethodDecl m = (JCMethodDecl) path.getParentPath().getLeaf(); -+ if ((m.mods.flags & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 && m.getParameters().contains(path.getLeaf())) { -+ return true; -+ } -+ } - - path = path.getParentPath(); - } -diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java b/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java -index aed7625d6e78..d28e43c61956 100644 ---- a/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java -+++ b/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java -@@ -925,6 +925,15 @@ public VariableTree Variable(ModifiersTree modifiers, - (JCExpression)type, (JCExpression)initializer); - } - -+ public VariableTree RecordComponent(ModifiersTree modifiers, -+ CharSequence name, -+ Tree type) { -+ JCModifiers augmentedModifiers = (JCModifiers) Modifiers(modifiers.getFlags(), modifiers.getAnnotations()); -+ -+ augmentedModifiers.flags |= Flags.RECORD; -+ -+ return Variable(augmentedModifiers, name, type, null); -+ } - public Tree BindingPattern(CharSequence name, - Tree type) { - try { -diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java -index 08527547a62a..6a561506eaa0 100644 ---- a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java -+++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java -@@ -193,7 +193,6 @@ public class CasualDiff { - private final Names names; - private final TreeMaker make; - private static final Logger LOG = Logger.getLogger(CasualDiff.class.getName()); -- public static final int GENERATED_MEMBER = 1<<24; - - private Map diffInfo = new HashMap<>(); - private final Map tree2Tag; -@@ -1008,6 +1007,47 @@ protected int diffClassDef(JCClassDecl oldT, JCClassDecl newT, int[] bounds) { - // it can be > (GT) or >> (SHIFT) - insertHint = tokenSequence.offset() + tokenSequence.token().length(); - } -+ //TODO: class to record and vice versa! -+ if (oldT.getKind() == Kind.RECORD && newT.getKind() == Kind.RECORD) { -+ ComponentsAndOtherMembers oldParts = splitOutRecordComponents(filteredOldTDefs); -+ ComponentsAndOtherMembers newParts = splitOutRecordComponents(filteredNewTDefs); -+ int posHint; -+ if (oldParts.components().isEmpty()) { -+ // compute the position. Find the parameters closing ')', its -+ // start position is important for us. This is used when -+ // there was not any parameter in original tree. -+ int startOffset = oldT.pos; -+ -+ moveFwdToToken(tokenSequence, startOffset, JavaTokenId.RPAREN); -+ posHint = tokenSequence.offset(); -+ } else { -+ // take the position of the first old parameter -+ posHint = oldParts.components.iterator().next().getStartPosition(); -+ } -+ if (!listsMatch(oldParts.components, newParts.components)) { -+ copyTo(localPointer, posHint); -+ int old = printer.setPrec(TreeInfo.noPrec); -+ parameterPrint = true; -+ JCClassDecl oldEnclClass = printer.enclClass; -+ printer.enclClass = null; -+ localPointer = diffParameterList(oldParts.components, newParts.components, null, posHint, Measure.MEMBER); -+ printer.enclClass = oldEnclClass; -+ parameterPrint = false; -+ printer.setPrec(old); -+ } -+ //make sure the ')' is printed: -+ moveFwdToToken(tokenSequence, oldParts.components.isEmpty() ? posHint : endPos(oldParts.components.get(oldParts.components.size() - 1)), JavaTokenId.RPAREN); -+ tokenSequence.moveNext(); -+ posHint = tokenSequence.offset(); -+ if (localPointer < posHint) -+ copyTo(localPointer, localPointer = posHint); -+ filteredOldTDefs = oldParts.defs; -+ filteredNewTDefs = newParts.defs; -+ tokenSequence.move(localPointer); -+ moveToSrcRelevant(tokenSequence, Direction.FORWARD); -+ // it can be > (GT) or >> (SHIFT) -+ insertHint = tokenSequence.offset() + tokenSequence.token().length(); -+ } - switch (getChangeKind(oldT.extending, newT.extending)) { - case NOCHANGE: - insertHint = oldT.extending != null ? endPos(oldT.extending) : insertHint; -@@ -1119,6 +1159,25 @@ protected int diffClassDef(JCClassDecl oldT, JCClassDecl newT, int[] bounds) { - return bounds[1]; - } - -+ private ComponentsAndOtherMembers splitOutRecordComponents(List defs) { -+ ListBuffer components = new ListBuffer<>(); -+ ListBuffer filteredDefs = new ListBuffer<>(); -+ -+ for (JCTree t : defs) { -+ if (t.getKind() == Kind.VARIABLE && -+ (((JCVariableDecl) t).mods.flags & RECORD) != 0) { -+ components.add(t); -+ } else { -+ filteredDefs.add(t); -+ } -+ } -+ -+ return new ComponentsAndOtherMembers(components.toList(), -+ filteredDefs.toList()); -+ } -+ -+ record ComponentsAndOtherMembers(List components, List defs) {} -+ - /** - * When the enumeration contains just methods, it is necessary to preced them with single ;. If a constant is - * inserted, it must be inserted first; and the semicolon should be removed. This method will attempt to remove entire -@@ -4026,11 +4085,7 @@ else if (Kind.VARIABLE == tree.getKind()) { - // collect enum constants, make a field group from them - // and set the flag. - enumConstants.add(var); -- } // filter syntetic member variable, i.e. variable which are in -- // the tree, but not available in the source. -- else if ((var.mods.flags & GENERATED_MEMBER) != 0) -- continue; -- else { -+ } else { - if (!fieldGroup.isEmpty()) { - int oldPos = getOldPos(fieldGroup.get(0)); - -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementHandleTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementHandleTest.java -index 92dcfdb519e4..f3c1cf42735c 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementHandleTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementHandleTest.java -@@ -20,6 +20,7 @@ - package org.netbeans.api.java.source; - - import com.sun.source.tree.NewClassTree; -+import com.sun.source.tree.VariableTree; - import com.sun.source.util.TreePath; - import com.sun.source.util.TreePathScanner; - import com.sun.tools.javac.model.JavacElements; -@@ -39,6 +40,7 @@ - import java.util.Map; - import java.util.Set; - import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicInteger; - import javax.lang.model.element.Element; - import javax.lang.model.element.ElementKind; - import javax.lang.model.element.ExecutableElement; -@@ -678,6 +680,80 @@ public void testHandleClassBasedCompilations() throws Exception { - SourceLevelQueryImpl.getDefault().setSourceLevel(jlObject, null); - } - -+ public void testMethodParameter1() throws Exception { -+ try (PrintWriter out = new PrintWriter ( new OutputStreamWriter (data.getOutputStream()))) { -+ out.println(""" -+ public class Test { -+ public Test(int cParam) {} -+ public void test(int mParam) { -+ FI fi = lParam -> {}; -+ } -+ interface FI { -+ public void test(int x) {} -+ } -+ } -+ """); -+ } -+ final JavaSource js = JavaSource.create(ClasspathInfo.create(ClassPathProviderImpl.getDefault().findClassPath(data,ClassPath.BOOT), ClassPathProviderImpl.getDefault().findClassPath(data, ClassPath.COMPILE), null), data); -+ assertNotNull(js); -+ AtomicInteger testCount = new AtomicInteger(); -+ -+ js.runUserActionTask(new Task() { -+ public void run(CompilationController parameter) throws Exception { -+ parameter.toPhase(JavaSource.Phase.RESOLVED); -+ new TreePathScanner() { -+ @Override -+ public Void visitVariable(VariableTree node, Void p) { -+ if (node.getName().toString().endsWith("Param")) { -+ Element el = parameter.getTrees().getElement(getCurrentPath()); -+ if (el.getSimpleName().contentEquals("lParam")) { -+ try { -+ ElementHandle.create(el); -+ fail("Expected exception didn't happen!"); -+ } catch (IllegalArgumentException ex) { -+ //OK -+ } -+ } else { -+ assertEquals(el, ElementHandle.create(el).resolve(parameter)); -+ } -+ testCount.incrementAndGet(); -+ } -+ return super.visitVariable(node, p); -+ } -+ }.scan(parameter.getCompilationUnit(), null); -+ } -+ }, true); -+ -+ assertEquals(3, testCount.get()); -+ } -+ -+ public void testMethodParameter2() throws Exception { -+ ClassPath systemClasses = BootClassPathUtil.getModuleBootPath(); -+ ClassPath bcp = BootClassPathUtil.getBootClassPath(); -+ FileObject jlObject = bcp.findResource("java/lang/String.class"); -+ assertNotNull(jlObject); -+ ClasspathInfo cpInfo = new ClasspathInfo.Builder(bcp) -+ .setModuleBootPath(systemClasses) -+ .build(); -+ JavaSource js = JavaSource.create(cpInfo, jlObject); -+ assertNotNull(js); -+ SourceLevelQueryImpl.getDefault().setSourceLevel(jlObject, "11"); -+ js.runUserActionTask(cc -> { -+ cc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED); -+ TypeElement tl = cc.getTopLevelElements().get(0); -+ for (Element el : tl.getEnclosedElements()) { -+ if (el.getKind() != ElementKind.METHOD && -+ el.getKind() != ElementKind.CONSTRUCTOR) { -+ continue; -+ } -+ for (VariableElement parameter : ((ExecutableElement) el).getParameters()) { -+ assertEquals(parameter, ElementHandle.create(parameter).resolve(cc)); -+ } -+ } -+ }, true); -+ SourceLevelQueryImpl.getDefault().setSourceLevel(jlObject, null); -+ } -+ - private Element[] getStringElements (Element stringElement) { - List members = ((TypeElement)stringElement).getEnclosedElements(); - Element[] result = new Element[3]; -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementUtilitiesTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementUtilitiesTest.java -index 40205da17ee9..745d01003d17 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementUtilitiesTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/ElementUtilitiesTest.java -@@ -31,12 +31,15 @@ - import java.util.HashSet; - import java.util.List; - import java.util.Set; -+import java.util.TreeSet; -+import java.util.stream.Collectors; - import javax.lang.model.element.Element; - import javax.lang.model.element.ElementKind; - import javax.lang.model.element.ExecutableElement; - import javax.lang.model.element.TypeElement; - import javax.lang.model.type.TypeKind; - import javax.lang.model.type.TypeMirror; -+import javax.lang.model.util.ElementFilter; - import org.netbeans.api.java.source.JavaSourceTest.SourceLevelQueryImpl; - import org.netbeans.junit.NbTestCase; - import org.openide.filesystems.FileObject; -@@ -599,4 +602,206 @@ public void testGetGlobalTypes() throws Exception { - }, true); - } - -+ public void testGetLinkedRecordElements1() throws Exception { -+ prepareTest(); -+ SourceUtilsTestUtil.setSourceLevel(testFO, "17"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(testFO), -+ """ -+ package test; -+ public record R(String component) {} -+ """ -+ ); -+ SourceLevelQueryImpl.sourceLevel = "17"; -+ -+ JavaSource javaSource = JavaSource.forFileObject(testFO); -+ javaSource.runUserActionTask((CompilationController controller) -> { -+ controller.toPhase(JavaSource.Phase.RESOLVED); -+ -+ TypeElement record = controller.getTopLevelElements().get(0); -+ ElementUtilities utils = controller.getElementUtilities(); -+ Collection linked = utils.getLinkedRecordElements(record.getRecordComponents().get(0)); -+ Set linkedEncoded = linked.stream() -+ .map(Element::getKind) -+ .map(ElementKind::name) -+ .collect(Collectors.toCollection(TreeSet::new)); -+ assertEquals(new TreeSet<>(Arrays.asList("FIELD", "METHOD", "PARAMETER", "RECORD_COMPONENT")), -+ linkedEncoded); -+ -+ for (Element linkedElement : linked) { -+ if (!linked.equals(utils.getLinkedRecordElements(linkedElement))) { -+ utils.getLinkedRecordElements(linkedElement); -+ } -+ assertEquals(linked, utils.getLinkedRecordElements(linkedElement)); -+ } -+ }, true); -+ } -+ -+ public void testGetLinkedRecordElements2() throws Exception { -+ prepareTest(); -+ SourceUtilsTestUtil.setSourceLevel(testFO, "17"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(testFO), -+ """ -+ package test; -+ public record R(String component) { -+ public R { -+ this.component = component; -+ } -+ public String component() { -+ return component; -+ } -+ } -+ """ -+ ); -+ SourceLevelQueryImpl.sourceLevel = "17"; -+ -+ JavaSource javaSource = JavaSource.forFileObject(testFO); -+ javaSource.runUserActionTask((CompilationController controller) -> { -+ controller.toPhase(JavaSource.Phase.RESOLVED); -+ -+ TypeElement record = controller.getTopLevelElements().get(0); -+ ElementUtilities utils = controller.getElementUtilities(); -+ Collection linked = utils.getLinkedRecordElements(record.getRecordComponents().get(0)); -+ Set linkedEncoded = linked.stream() -+ .map(Element::getKind) -+ .map(ElementKind::name) -+ .collect(Collectors.toCollection(TreeSet::new)); -+ assertEquals(new TreeSet<>(Arrays.asList("FIELD", "METHOD", "PARAMETER", "RECORD_COMPONENT")), -+ linkedEncoded); -+ -+ for (Element linkedElement : linked) { -+ if (!linked.equals(utils.getLinkedRecordElements(linkedElement))) { -+ utils.getLinkedRecordElements(linkedElement); -+ } -+ assertEquals(linked, utils.getLinkedRecordElements(linkedElement)); -+ } -+ }, true); -+ } -+ -+ public void testGetLinkedRecordElements3() throws Exception { -+ prepareTest(); -+ SourceUtilsTestUtil.setSourceLevel(testFO, "17"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(testFO), -+ """ -+ package test; -+ public record R(String component) { -+ public R(String component) { -+ this.component = component; -+ } -+ public String component() { -+ return component; -+ } -+ } -+ """ -+ ); -+ SourceLevelQueryImpl.sourceLevel = "17"; -+ -+ JavaSource javaSource = JavaSource.forFileObject(testFO); -+ javaSource.runUserActionTask((CompilationController controller) -> { -+ controller.toPhase(JavaSource.Phase.RESOLVED); -+ -+ TypeElement record = controller.getTopLevelElements().get(0); -+ ElementUtilities utils = controller.getElementUtilities(); -+ Collection linked = utils.getLinkedRecordElements(record.getRecordComponents().get(0)); -+ Set linkedEncoded = linked.stream() -+ .map(Element::getKind) -+ .map(ElementKind::name) -+ .collect(Collectors.toCollection(TreeSet::new)); -+ assertEquals(new TreeSet<>(Arrays.asList("FIELD", "METHOD", "PARAMETER", "RECORD_COMPONENT")), -+ linkedEncoded); -+ -+ for (Element linkedElement : linked) { -+ if (!linked.equals(utils.getLinkedRecordElements(linkedElement))) { -+ utils.getLinkedRecordElements(linkedElement); -+ } -+ assertEquals(linked, utils.getLinkedRecordElements(linkedElement)); -+ } -+ }, true); -+ } -+ -+ public void testGetLinkedRecordElements4() throws Exception { -+ prepareTest(); -+ SourceUtilsTestUtil.setSourceLevel(testFO, "17"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(testFO), -+ """ -+ package test; -+ public record R(String component) { -+ public R(String anotherName) { //error -+ this.component = anotherName; -+ } -+ public String component() { -+ return component; -+ } -+ } -+ """ -+ ); -+ SourceLevelQueryImpl.sourceLevel = "17"; -+ -+ JavaSource javaSource = JavaSource.forFileObject(testFO); -+ javaSource.runUserActionTask((CompilationController controller) -> { -+ controller.toPhase(JavaSource.Phase.RESOLVED); -+ -+ TypeElement record = controller.getTopLevelElements().get(0); -+ Element brokenParameter = ElementFilter.constructorsIn(record.getEnclosedElements()).get(0).getParameters().get(0); -+ ElementUtilities utils = controller.getElementUtilities(); -+ Collection linked = utils.getLinkedRecordElements(brokenParameter); -+ Set linkedEncoded = linked.stream() -+ .map(Element::getKind) -+ .map(ElementKind::name) -+ .collect(Collectors.toCollection(TreeSet::new)); -+ assertEquals(new TreeSet<>(Arrays.asList("PARAMETER")), -+ linkedEncoded); -+ }, true); -+ } -+ -+ public void testGetLinkedRecordElements5() throws Exception { -+ prepareTest(); -+ SourceUtilsTestUtil.setSourceLevel(sourceRoot, "17"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(testFO), -+ """ -+ package test; -+ public record R(String component) { -+ public R { -+ this.component = component; -+ } -+ public String component() { -+ return component; -+ } -+ } -+ """ -+ ); -+ FileObject useFO = FileUtil.createData(sourceRoot, "test/Use.java"); -+ TestUtilities.copyStringToFile(FileUtil.toFile(useFO), -+ """ -+ package test; -+ public class Use {} -+ """ -+ ); -+ SourceLevelQueryImpl.sourceLevel = "17"; -+ -+ SourceUtilsTestUtil.compileRecursively(sourceRoot); -+ -+ JavaSource javaSource = JavaSource.forFileObject(useFO); -+ javaSource.runUserActionTask((CompilationController controller) -> { -+ controller.toPhase(JavaSource.Phase.RESOLVED); -+ -+ TypeElement record = controller.getElements().getTypeElement("test.R"); -+ Element component = record.getRecordComponents().get(0); -+ ElementUtilities utils = controller.getElementUtilities(); -+ Collection linked = utils.getLinkedRecordElements(component); -+ Set linkedEncoded = linked.stream() -+ .map(Element::getKind) -+ .map(ElementKind::name) -+ .collect(Collectors.toCollection(TreeSet::new)); -+ assertEquals(new TreeSet<>(Arrays.asList("FIELD", "METHOD", "PARAMETER", "RECORD_COMPONENT")), -+ linkedEncoded); -+ -+ for (Element linkedElement : linked) { -+ if (!linked.equals(utils.getLinkedRecordElements(linkedElement))) { -+ utils.getLinkedRecordElements(linkedElement); -+ } -+ assertEquals(linked, utils.getLinkedRecordElements(linkedElement)); -+ } -+ }, true); -+ } -+ - } -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TestUtilities.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TestUtilities.java -index c85365e643c2..21b1039a262b 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TestUtilities.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TestUtilities.java -@@ -304,4 +304,15 @@ public static Path getJRTFS() throws IOException { - return null; - } - -+ public static TestInput splitCodeAndPos(String input) { -+ int pos = input.indexOf('|'); -+ -+ if (pos == (-1)) { -+ throw new IllegalArgumentException("Does not specify a caret position: " + input); -+ } -+ -+ return new TestInput(input.substring(0, pos) + input.substring(pos + 1), pos); -+ } -+ -+ public record TestInput(String code, int pos) {} - } -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java -index 67a769ca0b8b..14b7657f89ab 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/TreeUtilitiesTest.java -@@ -18,6 +18,7 @@ - */ - package org.netbeans.api.java.source; - -+import com.sun.source.tree.AnnotationTree; - import com.sun.source.tree.AssignmentTree; - import com.sun.source.tree.BlockTree; - import com.sun.source.tree.ClassTree; -@@ -53,6 +54,7 @@ - import org.netbeans.api.java.classpath.ClassPath; - import org.netbeans.api.java.source.Comment.Style; - import org.netbeans.api.java.source.JavaSource.Phase; -+import org.netbeans.api.java.source.TestUtilities.TestInput; - import org.netbeans.junit.NbTestCase; - import org.netbeans.spi.java.classpath.support.ClassPathSupport; - import org.openide.filesystems.FileObject; -@@ -146,6 +148,54 @@ public void testIsSyntheticNewClassExtends() throws Exception { - assertFalse(info.getTreeUtilities().isSynthetic(new TreePath(tp, nct.getIdentifier()))); - } - -+ public void testIsSyntheticCompactConstructorParams() throws Exception { -+ TestInput input = TestUtilities.splitCodeAndPos(""" -+ package t; -+ public record R(String component) { -+ public R| { -+ } -+ } -+ """); -+ prepareTest("Test", input.code()); -+ -+ TreePath tp = info.getTreeUtilities().pathFor(input.pos()); -+ MethodTree mt = (MethodTree) tp.getLeaf(); -+ -+ assertTrue(info.getTreeUtilities().isSynthetic(new TreePath(tp, mt.getParameters().get(0)))); -+ } -+ -+ public void testIsNotSyntheticExplicitConstructorParams() throws Exception { -+ TestInput input = TestUtilities.splitCodeAndPos(""" -+ package t; -+ public record R(String component) { -+ public R|(String component) { -+ } -+ } -+ """); -+ prepareTest("Test", input.code()); -+ -+ TreePath tp = info.getTreeUtilities().pathFor(input.pos()); -+ MethodTree mt = (MethodTree) tp.getLeaf(); -+ -+ assertFalse(info.getTreeUtilities().isSynthetic(new TreePath(tp, mt.getParameters().get(0)))); -+ } -+ -+ public void testIsNotSyntheticImplicitValueAttributeAssignment() throws Exception { -+ TestInput input = TestUtilities.splitCodeAndPos(""" -+ package t; -+ @An|n(1) -+ public @interface Ann { -+ public int value(); -+ } -+ """); -+ prepareTest("Test", input.code()); -+ -+ TreePath tp = info.getTreeUtilities().pathFor(input.pos()); -+ AnnotationTree at = (AnnotationTree) tp.getParentPath().getLeaf(); -+ -+ assertFalse(info.getTreeUtilities().isSynthetic(new TreePath(tp, at.getArguments().get(0)))); -+ } -+ - public void testIsSyntheticNewClassImplements() throws Exception { - prepareTest("Test", "package test; import java.io.*; public class Test { void t() { new Serializable() { }; } }"); - -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/RecordTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/RecordTest.java -new file mode 100644 -index 000000000000..bc33aa888e5d ---- /dev/null -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/RecordTest.java -@@ -0,0 +1,250 @@ -+/* -+ * Licensed to the Apache Software Foundation (ASF) under one -+ * or more contributor license agreements. See the NOTICE file -+ * distributed with this work for additional information -+ * regarding copyright ownership. The ASF licenses this file -+ * to you under the Apache License, Version 2.0 (the -+ * "License"); you may not use this file except in compliance -+ * with the License. You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, -+ * software distributed under the License is distributed on an -+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -+ * KIND, either express or implied. See the License for the -+ * specific language governing permissions and limitations -+ * under the License. -+ */ -+package org.netbeans.api.java.source.gen; -+ -+import java.io.*; -+import com.sun.source.tree.*; -+import com.sun.source.tree.Tree.Kind; -+import java.util.EnumSet; -+import javax.lang.model.element.Modifier; -+import org.netbeans.api.java.source.*; -+import static org.netbeans.api.java.source.JavaSource.*; -+import org.netbeans.junit.NbTestSuite; -+ -+public class RecordTest extends GeneratorTestMDRCompat { -+ -+ private String sourceLevel; -+ -+ public RecordTest(String testName) { -+ super(testName); -+ } -+ -+ public static NbTestSuite suite() { -+ NbTestSuite suite = new NbTestSuite(); -+ suite.addTestSuite(RecordTest.class); -+ return suite; -+ } -+ -+ public void testRenameComponent() throws Exception { -+ testFile = new File(getWorkDir(), "Test.java"); -+ TestUtilities.copyStringToFile(testFile, -+ """ -+ package hierbas.del.litoral; -+ public record R(String component) {} -+ """); -+ String golden = -+ """ -+ package hierbas.del.litoral; -+ public record R(String newName) {} -+ """; -+ -+ JavaSource src = getJavaSource(testFile); -+ Task task = new Task() { -+ -+ public void run(WorkingCopy workingCopy) throws IOException { -+ workingCopy.toPhase(Phase.RESOLVED); -+ CompilationUnitTree cut = workingCopy.getCompilationUnit(); -+ TreeMaker make = workingCopy.getTreeMaker(); -+ -+ Tree recordDecl = cut.getTypeDecls().get(0); -+ assertEquals(Kind.RECORD, recordDecl.getKind()); -+ ClassTree classTree = (ClassTree) recordDecl; -+ for (Tree m : classTree.getMembers()) { -+ if (m.getKind() == Kind.VARIABLE) { -+ workingCopy.rewrite(m, make.setLabel(m, "newName")); -+ } -+ } -+ } -+ -+ }; -+ src.runModificationTask(task).commit(); -+ String res = TestUtilities.copyFileToString(testFile); -+ //System.err.println(res); -+ assertEquals(golden, res); -+ } -+ -+ public void testAddFirstComponent() throws Exception { -+ testFile = new File(getWorkDir(), "Test.java"); -+ TestUtilities.copyStringToFile(testFile, -+ """ -+ package hierbas.del.litoral; -+ public record R() {} -+ """); -+ String golden = -+ """ -+ package hierbas.del.litoral; -+ public record R(String component) {} -+ """; -+ -+ JavaSource src = getJavaSource(testFile); -+ Task task = new Task() { -+ -+ public void run(WorkingCopy workingCopy) throws IOException { -+ workingCopy.toPhase(Phase.RESOLVED); -+ CompilationUnitTree cut = workingCopy.getCompilationUnit(); -+ TreeMaker make = workingCopy.getTreeMaker(); -+ -+ Tree recordDecl = cut.getTypeDecls().get(0); -+ assertEquals(Kind.RECORD, recordDecl.getKind()); -+ ClassTree classTree = (ClassTree) recordDecl; -+ VariableTree newComponent = make.RecordComponent(make.Modifiers(EnumSet.noneOf(Modifier.class)), -+ "component", -+ make.Type("java.lang.String")); -+ ClassTree newClassTree = make.addClassMember(classTree, newComponent); -+ workingCopy.rewrite(classTree, newClassTree); -+ } -+ -+ }; -+ src.runModificationTask(task).commit(); -+ String res = TestUtilities.copyFileToString(testFile); -+ //System.err.println(res); -+ assertEquals(golden, res); -+ } -+ -+ public void testAddSecondComponent() throws Exception { -+ testFile = new File(getWorkDir(), "Test.java"); -+ TestUtilities.copyStringToFile(testFile, -+ """ -+ package hierbas.del.litoral; -+ public record R(String existing) {} -+ """); -+ String golden = -+ """ -+ package hierbas.del.litoral; -+ public record R(String existing, String component) {} -+ """; -+ -+ JavaSource src = getJavaSource(testFile); -+ Task task = new Task() { -+ -+ public void run(WorkingCopy workingCopy) throws IOException { -+ workingCopy.toPhase(Phase.RESOLVED); -+ CompilationUnitTree cut = workingCopy.getCompilationUnit(); -+ TreeMaker make = workingCopy.getTreeMaker(); -+ -+ Tree recordDecl = cut.getTypeDecls().get(0); -+ assertEquals(Kind.RECORD, recordDecl.getKind()); -+ ClassTree classTree = (ClassTree) recordDecl; -+ VariableTree newComponent = make.RecordComponent(make.Modifiers(EnumSet.noneOf(Modifier.class)), -+ "component", -+ make.Type("java.lang.String")); -+ ClassTree newClassTree = make.addClassMember(classTree, newComponent); -+ workingCopy.rewrite(classTree, newClassTree); -+ } -+ -+ }; -+ src.runModificationTask(task).commit(); -+ String res = TestUtilities.copyFileToString(testFile); -+ //System.err.println(res); -+ assertEquals(golden, res); -+ } -+ -+ public void testRemoveLastComponent() throws Exception { -+ testFile = new File(getWorkDir(), "Test.java"); -+ TestUtilities.copyStringToFile(testFile, -+ """ -+ package hierbas.del.litoral; -+ public record R(String component) {} -+ """); -+ String golden = -+ """ -+ package hierbas.del.litoral; -+ public record R() {} -+ """; -+ -+ JavaSource src = getJavaSource(testFile); -+ Task task = new Task() { -+ -+ public void run(WorkingCopy workingCopy) throws IOException { -+ workingCopy.toPhase(Phase.RESOLVED); -+ CompilationUnitTree cut = workingCopy.getCompilationUnit(); -+ TreeMaker make = workingCopy.getTreeMaker(); -+ -+ Tree recordDecl = cut.getTypeDecls().get(0); -+ assertEquals(Kind.RECORD, recordDecl.getKind()); -+ ClassTree classTree = (ClassTree) recordDecl; -+ for (Tree m : classTree.getMembers()) { -+ if (m.getKind() == Kind.VARIABLE) { -+ workingCopy.rewrite(classTree, make.removeClassMember(classTree, m)); -+ break; -+ } -+ } -+ } -+ -+ }; -+ src.runModificationTask(task).commit(); -+ String res = TestUtilities.copyFileToString(testFile); -+ //System.err.println(res); -+ assertEquals(golden, res); -+ } -+ -+ public void testRemoveComponent() throws Exception { -+ testFile = new File(getWorkDir(), "Test.java"); -+ TestUtilities.copyStringToFile(testFile, -+ """ -+ package hierbas.del.litoral; -+ public record R(String first, String component) {} -+ """); -+ String golden = -+ """ -+ package hierbas.del.litoral; -+ public record R(String first) {} -+ """; -+ -+ JavaSource src = getJavaSource(testFile); -+ Task task = new Task() { -+ -+ public void run(WorkingCopy workingCopy) throws IOException { -+ workingCopy.toPhase(Phase.RESOLVED); -+ CompilationUnitTree cut = workingCopy.getCompilationUnit(); -+ TreeMaker make = workingCopy.getTreeMaker(); -+ -+ Tree recordDecl = cut.getTypeDecls().get(0); -+ assertEquals(Kind.RECORD, recordDecl.getKind()); -+ ClassTree classTree = (ClassTree) recordDecl; -+ for (Tree m : classTree.getMembers()) { -+ if (m.getKind() == Kind.VARIABLE && -+ ((VariableTree) m).getName().contentEquals("component")) { -+ workingCopy.rewrite(classTree, make.removeClassMember(classTree, m)); -+ break; -+ } -+ } -+ } -+ -+ }; -+ src.runModificationTask(task).commit(); -+ String res = TestUtilities.copyFileToString(testFile); -+ //System.err.println(res); -+ assertEquals(golden, res); -+ } -+ -+ String getGoldenPckg() { -+ return ""; -+ } -+ -+ String getSourcePckg() { -+ return ""; -+ } -+ -+ @Override -+ String getSourceLevel() { -+ return sourceLevel; -+ } -+ -+} -diff --git a/java/refactoring.java/nbproject/project.properties b/java/refactoring.java/nbproject/project.properties -index 482f48c8d29e..5f57bb0404c3 100644 ---- a/java/refactoring.java/nbproject/project.properties -+++ b/java/refactoring.java/nbproject/project.properties -@@ -14,7 +14,7 @@ - # KIND, either express or implied. See the License for the - # specific language governing permissions and limitations - # under the License. --javac.source=1.8 -+javac.release=17 - javadoc.arch=${basedir}/arch.xml - javadoc.apichanges=${basedir}/apichanges.xml - -diff --git a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaPluginUtils.java b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaPluginUtils.java -index 8804024eb0b5..5377f15eb677 100644 ---- a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaPluginUtils.java -+++ b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/JavaPluginUtils.java -@@ -332,69 +332,11 @@ public static boolean hasSetter(CompilationInfo info, TypeElement typeElement, V - return false; - } - -- /** -- * Works as TreeUtilities.isSynthetic, but treats implicit annotation parameter (value) as -- * non-synthetic. See defect #270036 -- */ - public static boolean isSyntheticPath(CompilationInfo ci, TreePath path) { - TreeUtilities tu = ci.getTreeUtilities(); -- if (path == null) -- throw new NullPointerException(); -- -- while (path != null) { -- SYNT: if (isSynthetic(ci, path.getCompilationUnit(), path.getLeaf())) { -- if (path.getLeaf().getKind() == Tree.Kind.ASSIGNMENT && -- path.getParentPath() != null && path.getParentPath().getLeaf().getKind() == Tree.Kind.ANNOTATION) { -- AssignmentTree aTree = (AssignmentTree)path.getLeaf(); -- if (aTree.getVariable().getKind() == Tree.Kind.IDENTIFIER && -- ((IdentifierTree)aTree.getVariable()).getName().contentEquals("value")) { // implicit value is not synthetic -- break SYNT; -- } -- } -- return true; -- } -- -- path = path.getParentPath(); -- } -- -- return false; -+ return tu.isSynthetic(path); - } - -- // -- static boolean isSynthetic(CompilationInfo info, CompilationUnitTree cut, Tree leaf) throws NullPointerException { -- JCTree tree = (JCTree) leaf; -- -- if (tree.pos == (-1)) -- return true; -- -- if (leaf.getKind() == Kind.METHOD) { -- //check for synthetic constructor: -- return (((JCTree.JCMethodDecl)leaf).mods.flags & Flags.GENERATEDCONSTR) != 0L; -- } -- -- //check for synthetic superconstructor call: -- if (leaf.getKind() == Kind.EXPRESSION_STATEMENT) { -- ExpressionStatementTree est = (ExpressionStatementTree) leaf; -- -- if (est.getExpression().getKind() == Kind.METHOD_INVOCATION) { -- MethodInvocationTree mit = (MethodInvocationTree) est.getExpression(); -- -- if (mit.getMethodSelect().getKind() == Kind.IDENTIFIER) { -- IdentifierTree it = (IdentifierTree) mit.getMethodSelect(); -- -- if ("super".equals(it.getName().toString())) { -- SourcePositions sp = info.getTrees().getSourcePositions(); -- -- return sp.getEndPosition(cut, leaf) == (-1); -- } -- } -- } -- } -- -- return false; -- } -- // -- - // - public static final String DEFAULT_NAME = "par"; // NOI18N - public static String makeNameUnique(CompilationInfo info, Scope s, String name) { -diff --git a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameRefactoringPlugin.java b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameRefactoringPlugin.java -index 9c50d4175347..8378dc3b3198 100644 ---- a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameRefactoringPlugin.java -+++ b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameRefactoringPlugin.java -@@ -54,6 +54,7 @@ - public class RenameRefactoringPlugin extends JavaRefactoringPlugin { - - private Set> allMethods = new HashSet>(); -+ private Set recordLinkedDeclarations = new HashSet<>(); - private boolean doCheckName = true; - private Integer overriddenByMethodsCount = null; - private Integer overridesMethodsCount = null; -@@ -422,36 +423,42 @@ public void run(CompilationController info) throws Exception { - : treePathHandle.resolveElement(info); - ElementKind kind = el.getKind(); - ElementHandle enclosingType; -- if (el instanceof TypeElement) { -+ if (kind.isClass() || kind.isInterface()) { - enclosingType = ElementHandle.create((TypeElement)el); - } else { - enclosingType = ElementHandle.create(info.getElementUtilities().enclosingTypeElement(el)); - } - set.add(SourceUtils.getFile(el, info.getClasspathInfo())); -- if (el.getModifiers().contains(Modifier.PRIVATE)) { -- if (kind == ElementKind.METHOD) { -- //add all references of overriding methods -- allMethods.add(ElementHandle.create((ExecutableElement)el)); -+ for (Element linked : info.getElementUtilities().getLinkedRecordElements(el)) { -+ ElementKind linkedKind = linked.getKind(); -+ if (!el.equals(linked)) { -+ recordLinkedDeclarations.add(TreePathHandle.create(linked, info)); - } -- } else { -- if (kind.isField()) { -- set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.FIELD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); -- } else if (el instanceof TypeElement) { -- set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES, ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE))); -- } else if (kind == ElementKind.METHOD) { -- //add all references of overriding methods -- allMethods.add(ElementHandle.create((ExecutableElement)el)); -- for (ExecutableElement e:JavaRefactoringUtils.getOverridingMethods((ExecutableElement)el, info, cancelRequested)) { -- addMethods(e, set, info, idx); -+ if (linked.getModifiers().contains(Modifier.PRIVATE)) { -+ if (linkedKind == ElementKind.METHOD) { -+ //add all references of overriding methods -+ allMethods.add(ElementHandle.create((ExecutableElement)linked)); - } -- //add all references of overriden methods -- for (ExecutableElement ov: JavaRefactoringUtils.getOverriddenMethods((ExecutableElement)el, info)) { -- addMethods(ov, set, info, idx); -- for (ExecutableElement e:JavaRefactoringUtils.getOverridingMethods( ov,info, cancelRequested)) { -+ } else { -+ if (linkedKind.isField()) { -+ set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.FIELD_REFERENCES), EnumSet.of(ClassIndex.SearchScope.SOURCE))); -+ } else if (linked instanceof TypeElement) { -+ set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.TYPE_REFERENCES, ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.of(ClassIndex.SearchScope.SOURCE))); -+ } else if (linkedKind == ElementKind.METHOD) { -+ //add all references of overriding methods -+ allMethods.add(ElementHandle.create((ExecutableElement)linked)); -+ for (ExecutableElement e:JavaRefactoringUtils.getOverridingMethods((ExecutableElement)linked, info, cancelRequested)) { - addMethods(e, set, info, idx); - } -+ //add all references of overriden methods -+ for (ExecutableElement ov: JavaRefactoringUtils.getOverriddenMethods((ExecutableElement)linked, info)) { -+ addMethods(ov, set, info, idx); -+ for (ExecutableElement e:JavaRefactoringUtils.getOverridingMethods( ov,info, cancelRequested)) { -+ addMethods(e, set, info, idx); -+ } -+ } -+ set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); //????? - } -- set.addAll(idx.getResources(enclosingType, EnumSet.of(ClassIndex.SearchKind.METHOD_REFERENCES),EnumSet.of(ClassIndex.SearchScope.SOURCE))); //????? - } - } - } -@@ -623,7 +630,7 @@ public Problem prepare(RefactoringElementsBag elements) { - } - Set a = getRelevantFiles(); - fireProgressListenerStart(AbstractRefactoring.PREPARE, a.size()); -- TransformTask transform = new TransformTask(new RenameTransformer(treePathHandle, docTreePathHandle, refactoring, allMethods, refactoring.isSearchInComments()), treePathHandle != null && treePathHandle.getKind() == Tree.Kind.LABELED_STATEMENT ? null : treePathHandle); -+ TransformTask transform = new TransformTask(new RenameTransformer(treePathHandle, docTreePathHandle, refactoring, allMethods, recordLinkedDeclarations, refactoring.isSearchInComments()), treePathHandle != null && treePathHandle.getKind() == Tree.Kind.LABELED_STATEMENT ? null : treePathHandle); - Problem problem = createAndAddElements(a, transform, elements, refactoring,getClasspathInfo(refactoring)); - fireProgressListenerStop(); - return problem; -diff --git a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameTransformer.java b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameTransformer.java -index a27dd2972623..c833058dbcb1 100644 ---- a/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameTransformer.java -+++ b/java/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RenameTransformer.java -@@ -59,6 +59,7 @@ - public class RenameTransformer extends RefactoringVisitor { - - private final Set> allMethods; -+ private final Set recordLinkedDeclarations; - private final TreePathHandle handle; - private final DocTreePathHandle docHandle; - private final String newName; -@@ -68,13 +69,14 @@ public class RenameTransformer extends RefactoringVisitor { - private Map imports; - private List newImports; - -- public RenameTransformer(TreePathHandle handle, DocTreePathHandle docHandle, RenameRefactoring refactoring, Set> am, boolean renameInComments) { -+ public RenameTransformer(TreePathHandle handle, DocTreePathHandle docHandle, RenameRefactoring refactoring, Set> am, Set recordLinkedDeclarations, boolean renameInComments) { - super(true); - this.handle = handle; - this.docHandle = docHandle; - this.refactoring = refactoring; - this.newName = refactoring.getNewName(); - this.allMethods = am; -+ this.recordLinkedDeclarations = recordLinkedDeclarations; - this.renameInComments = renameInComments; - } - -@@ -197,6 +199,17 @@ private void renameUsageIfMatch(final TreePath path, Tree tree, Element elementT - if (JavaPluginUtils.isSyntheticPath(workingCopy, path) || (handle != null && handle.getKind() == Tree.Kind.LABELED_STATEMENT)) { - return; - } -+ doRenameUsageIfMatch(getCurrentPath(), tree, elementToFind); -+ for (TreePathHandle h : recordLinkedDeclarations) { -+ Element linked = h.resolveElement(workingCopy); -+ -+ if (linked != null) { -+ doRenameUsageIfMatch(getCurrentPath(), tree, linked); -+ } -+ } -+ } -+ -+ private void doRenameUsageIfMatch(final TreePath path, Tree tree, Element elementToFind) { - TreePath elementPath = path; - Trees trees = workingCopy.getTrees(); - Element el = workingCopy.getTrees().getElement(elementPath); -@@ -391,14 +404,17 @@ public Tree visitClass(ClassTree tree, final Element p) { - Element el = workingCopy.getTrees().getElement(currentPath); - if (el != null && el.getEnclosedElements().contains(p)) { - Trees trees = workingCopy.getTrees(); -- Scope scope = trees.getScope(trees.getPath(p)); -- shadowed = workingCopy.getElementUtilities().getLocalMembersAndVars(scope, new ElementUtilities.ElementAcceptor() { -+ TreePath pPath = trees.getPath(p); -+ if (pPath != null) { //may be null for synthetic record accessors -+ Scope scope = trees.getScope(pPath); -+ shadowed = workingCopy.getElementUtilities().getLocalMembersAndVars(scope, new ElementUtilities.ElementAcceptor() { - -- @Override -- public boolean accept(Element element, TypeMirror type) { -- return !element.equals(p) && element.getKind() == p.getKind() && element.getSimpleName().contentEquals(newName); -- } -- }); -+ @Override -+ public boolean accept(Element element, TypeMirror type) { -+ return !element.equals(p) && element.getKind() == p.getKind() && element.getSimpleName().contentEquals(newName); -+ } -+ }); -+ } - } - Tree value = super.visitClass(tree, p); - shadowed = null; -@@ -421,6 +437,19 @@ private void renameDeclIfMatch(TreePath path, Tree tree, Element elementToFind) - if (JavaPluginUtils.isSyntheticPath(workingCopy, path) || (handle != null && handle.getKind() == Tree.Kind.LABELED_STATEMENT)) { - return; - } -+ -+ doRenameDeclIfMatch(path, tree, elementToFind); -+ -+ for (TreePathHandle h : recordLinkedDeclarations) { -+ Element linked = h.resolveElement(workingCopy); -+ -+ if (linked != null) { -+ doRenameDeclIfMatch(getCurrentPath(), tree, linked); -+ } -+ } -+ } -+ -+ private void doRenameDeclIfMatch(TreePath path, Tree tree, Element elementToFind) { - Element el = workingCopy.getTrees().getElement(path); - if (el==null) { - return; -diff --git a/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameRecordTest.java b/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameRecordTest.java -new file mode 100644 -index 000000000000..43fbba7faa72 ---- /dev/null -+++ b/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameRecordTest.java -@@ -0,0 +1,418 @@ -+/* -+ * Licensed to the Apache Software Foundation (ASF) under one -+ * or more contributor license agreements. See the NOTICE file -+ * distributed with this work for additional information -+ * regarding copyright ownership. The ASF licenses this file -+ * to you under the Apache License, Version 2.0 (the -+ * "License"); you may not use this file except in compliance -+ * with the License. You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, -+ * software distributed under the License is distributed on an -+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -+ * KIND, either express or implied. See the License for the -+ * specific language governing permissions and limitations -+ * under the License. -+ */ -+package org.netbeans.modules.refactoring.java.test; -+ -+import com.sun.source.tree.CompilationUnitTree; -+import com.sun.source.util.TreePath; -+import java.util.Arrays; -+import java.util.LinkedList; -+import java.util.List; -+import org.netbeans.api.java.source.CompilationController; -+import org.netbeans.api.java.source.JavaSource; -+import org.netbeans.api.java.source.Task; -+import org.netbeans.api.java.source.TestUtilities; -+import org.netbeans.api.java.source.TestUtilities.TestInput; -+import org.netbeans.api.java.source.TreePathHandle; -+import org.netbeans.modules.refactoring.api.Problem; -+import org.netbeans.modules.refactoring.api.RefactoringSession; -+import org.netbeans.modules.refactoring.api.RenameRefactoring; -+import org.netbeans.modules.refactoring.java.ui.JavaRenameProperties; -+import org.openide.filesystems.FileObject; -+import org.openide.util.lookup.Lookups; -+ -+public class RenameRecordTest extends RefactoringTestBase { -+ -+ public RenameRecordTest(String name) { -+ super(name, "17"); -+ } -+ -+ public void testRenameComponent1() throws Exception { -+ String testCode = """ -+ package test; -+ public record Test(int compo|nent) {} -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(testCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", splitCode.code()), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.component(); -+ } -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Test.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) {} -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ -+ } -+ -+ public void testRenameComponent2() throws Exception { -+ String testCode = """ -+ package test; -+ public record Test(int compo|nent) { -+ public Test(int component) { -+ component = -1; -+ } -+ public int component() { -+ return component; -+ } -+ public int hashCode() { -+ return component; -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(testCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", splitCode.code()), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.component(); -+ } -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Test.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) { -+ public Test(int newName) { -+ newName = -1; -+ } -+ public int newName() { -+ return newName; -+ } -+ public int hashCode() { -+ return newName; -+ } -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ -+ } -+ -+ public void testRenameComponent3() throws Exception { -+ String testCode = """ -+ package test; -+ public record Test(int compo|nent) { -+ public Test { -+ component = -1; -+ } -+ public int component() { -+ return component; -+ } -+ public int hashCode() { -+ return component; -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(testCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", splitCode.code()), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.component(); -+ } -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Test.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) { -+ public Test { -+ newName = -1; -+ } -+ public int newName() { -+ return newName; -+ } -+ public int hashCode() { -+ return newName; -+ } -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ -+ } -+ -+ public void testRenameComponentStartFromAccessor1() throws Exception { -+ String useCode = """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.com|ponent(); -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(useCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", -+ """ -+ package test; -+ public record Test(int component) { -+ public Test { -+ component = -1; -+ } -+ public int component() { -+ return component; -+ } -+ public int hashCode() { -+ return component; -+ } -+ } -+ """), -+ new File("Use.java", splitCode.code())); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Use.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) { -+ public Test { -+ newName = -1; -+ } -+ public int newName() { -+ return newName; -+ } -+ public int hashCode() { -+ return newName; -+ } -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ -+ } -+ -+ public void testRenameComponentStartFromAccessor2() throws Exception { -+ String useCode = """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.com|ponent(); -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(useCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", -+ """ -+ package test; -+ public record Test(int component) { -+ } -+ """), -+ new File("Use.java", splitCode.code())); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Use.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) { -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ -+ } -+ -+ public void testRenameComponentStartFromConstructorArg() throws Exception { -+ String testCode = """ -+ package test; -+ public record Test(int component) { -+ public Test { -+ compo|nent = -1; -+ } -+ public int component() { -+ return component; -+ } -+ public int hashCode() { -+ return component; -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(testCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", splitCode.code()), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.component(); -+ } -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Test.java"), splitCode.pos(), "newName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record Test(int newName) { -+ public Test { -+ newName = -1; -+ } -+ public int newName() { -+ return newName; -+ } -+ public int hashCode() { -+ return newName; -+ } -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private void test(Test t) { -+ int i = t.newName(); -+ } -+ } -+ """)); -+ } -+ -+ public void testRenameRecord() throws Exception { -+ String testCode = """ -+ package test; -+ public record Te|st(int component) { -+ public Test { -+ component = ""; -+ } -+ } -+ """; -+ TestInput splitCode = TestUtilities.splitCodeAndPos(testCode); -+ writeFilesAndWaitForScan(src, -+ new File("Test.java", splitCode.code()), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private Test test() { -+ return new Test(0); -+ } -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("Test.java"), splitCode.pos(), "NewName", props, true); -+ verifyContent(src, new File("Test.java", -+ """ -+ package test; -+ public record NewName(int component) { -+ public NewName { -+ component = ""; -+ } -+ } -+ """), -+ new File("Use.java", -+ """ -+ package test; -+ public class Use { -+ private NewName test() { -+ return new NewName(0); -+ } -+ } -+ """)); -+ -+ } -+ private void performRename(FileObject source, final int absPos, final String newname, final JavaRenameProperties props, final boolean searchInComments, Problem... expectedProblems) throws Exception { -+ final RenameRefactoring[] r = new RenameRefactoring[1]; -+ JavaSource.forFileObject(source).runUserActionTask(new Task() { -+ -+ @Override -+ public void run(CompilationController javac) throws Exception { -+ javac.toPhase(JavaSource.Phase.RESOLVED); -+ CompilationUnitTree cut = javac.getCompilationUnit(); -+ -+ TreePath tp = javac.getTreeUtilities().pathFor(absPos); -+ -+ r[0] = new RenameRefactoring(Lookups.singleton(TreePathHandle.create(tp, javac))); -+ r[0].setNewName(newname); -+ r[0].setSearchInComments(searchInComments); -+ if(props != null) { -+ r[0].getContext().add(props); -+ } -+ } -+ }, true); -+ -+ RefactoringSession rs = RefactoringSession.create("Rename"); -+ List problems = new LinkedList<>(); -+ -+ addAllProblems(problems, r[0].preCheck()); -+ if (!problemIsFatal(problems)) { -+ addAllProblems(problems, r[0].prepare(rs)); -+ } -+ if (!problemIsFatal(problems)) { -+ addAllProblems(problems, rs.doRefactoring(true)); -+ } -+ -+ assertProblems(Arrays.asList(expectedProblems), problems); -+ } -+} -diff --git a/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameTest.java b/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameTest.java -index 0c22d6d57808..f2e961fa4af5 100644 ---- a/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameTest.java -+++ b/java/refactoring.java/test/unit/src/org/netbeans/modules/refactoring/java/test/RenameTest.java -@@ -28,6 +28,8 @@ - import org.netbeans.api.java.source.CompilationController; - import org.netbeans.api.java.source.JavaSource; - import org.netbeans.api.java.source.Task; -+import org.netbeans.api.java.source.TestUtilities; -+import org.netbeans.api.java.source.TestUtilities.TestInput; - import org.netbeans.api.java.source.TreePathHandle; - import org.netbeans.modules.refactoring.api.Problem; - import org.netbeans.modules.refactoring.api.RefactoringSession; -@@ -1573,6 +1575,60 @@ public void testRenameBindingVariableType() throws Exception { - - } - -+ public void testRenameClassInAnnotation() throws Exception { -+ TestInput input = TestUtilities.splitCodeAndPos(""" -+ package t; -+ public class T|est { -+ } -+ """); -+ -+ writeFilesAndWaitForScan(src, -+ new File("t/Test.java", input.code()), -+ new File("t/Ann.java", -+ """ -+ package t; -+ @interface Ann { -+ public Class value(); -+ } -+ """), -+ new File("t/Use.java", -+ """ -+ package t; -+ public class Use { -+ @Ann(Test.class) -+ void t1() {} -+ @Ann({Test.class}) -+ void t2() {} -+ } -+ """)); -+ JavaRenameProperties props = new JavaRenameProperties(); -+ performRename(src.getFileObject("t/Test.java"), input.pos(), "NewName", props, true); -+ verifyContent(src, -+ new File("t/Test.java", -+ """ -+ package t; -+ public class NewName { -+ } -+ """), -+ new File("t/Ann.java", -+ """ -+ package t; -+ @interface Ann { -+ public Class value(); -+ } -+ """), -+ new File("t/Use.java", -+ """ -+ package t; -+ public class Use { -+ @Ann(NewName.class) -+ void t1() {} -+ @Ann({NewName.class}) -+ void t2() {} -+ } -+ """)); -+ } -+ - private void performRename(FileObject source, final int position, final int position2, final String newname, final JavaRenameProperties props, final boolean searchInComments, Problem... expectedProblems) throws Exception { - final RenameRefactoring[] r = new RenameRefactoring[1]; - JavaSource.forFileObject(source).runUserActionTask(new Task() { diff --git a/patches/7699.diff b/patches/7699.diff deleted file mode 100644 index b508a11c..00000000 --- a/patches/7699.diff +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java -index aed6e6110c..1c081994d8 100644 ---- a/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java -+++ b/java/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java -@@ -1276,7 +1276,7 @@ public final class GeneratorUtilities { - // check for possible name clashes originating from adding the package imports - Set explicitNamedImports = new HashSet(); - for (Element element : elementsToImport) { -- if (element.getKind().isClass() || element.getKind().isInterface()) { -+ if (element.getEnclosingElement() != pkg && (element.getKind().isClass() || element.getKind().isInterface())) { - for (Symbol sym : importScope.getSymbolsByName((com.sun.tools.javac.util.Name)element.getSimpleName())) { - if (sym.getKind().isClass() || sym.getKind().isInterface()) { - if (sym != element) { -diff --git a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/GeneratorUtilitiesTest.java b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/GeneratorUtilitiesTest.java -index 90d0261c19..3f13dde797 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/GeneratorUtilitiesTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/GeneratorUtilitiesTest.java -@@ -583,6 +583,18 @@ public class GeneratorUtilitiesTest extends NbTestCase { - }, false); - } - -+ public void testAddImports14() throws Exception { -+ performTest("test/Process.java", "package test;\nimport java.util.Collections;\npublic class Process {\npublic static void main(String... args) {\n" + -+ "Collections.singleton(Process.class).forEach(System.out::println);\n}\n}", "1.5", new AddImportsTask("test.Process"), new Validator() { -+ public void validate(CompilationInfo info) { -+ assertEquals(0, info.getDiagnostics().size()); -+ List imports = info.getCompilationUnit().getImports(); -+ assertEquals(1, imports.size()); -+ assertEquals("java.util.Collections", imports.get(0).getQualifiedIdentifier().toString()); -+ } -+ }, false); -+ } -+ - public void testAddImportsIncrementallyWithStatic_JIRA3019() throws Exception { - JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true; - performTest("package test;\npublic class Test { public static final String CONST = null; }\n", "11", new AddImportsTask(true, "test.Test.CONST", "java.util.List"), new Validator() { diff --git a/patches/7709.diff b/patches/7709.diff deleted file mode 100644 index 09a5f36f..00000000 --- a/patches/7709.diff +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java b/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java -index d24c6f5ec9..f2b040204e 100644 ---- a/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java -+++ b/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java -@@ -58,7 +58,8 @@ public class PrepareBundles { - Pattern.compile("license", Pattern.CASE_INSENSITIVE), - Pattern.compile("LICENSE.txt", Pattern.CASE_INSENSITIVE), - Pattern.compile("LICENSE-MIT.txt", Pattern.CASE_INSENSITIVE), -- Pattern.compile("LICENSE.md", Pattern.CASE_INSENSITIVE) -+ Pattern.compile("LICENSE.md", Pattern.CASE_INSENSITIVE), -+ Pattern.compile("LICENSE.markdown", Pattern.CASE_INSENSITIVE) - ); - private static final String nl = "\n"; - -@@ -69,7 +70,12 @@ public class PrepareBundles { - - Path targetDir = Paths.get(args[0]); - Path packagesDir = targetDir.resolve("package"); -- new ProcessBuilder("npm", "install").directory(packagesDir.toFile()).inheritIO().start().waitFor(); -+ String os = System.getProperty("os.name").toLowerCase(); -+ if (os.contains("windows")) { -+ new ProcessBuilder("npm.cmd", "install").directory(packagesDir.toFile()).inheritIO().start().waitFor(); -+ } else{ -+ new ProcessBuilder("npm", "install").directory(packagesDir.toFile()).inheritIO().start().waitFor(); -+ } - Path bundlesDir = targetDir.resolve("bundles"); - Files.createDirectories(bundlesDir); - try (DirectoryStream ds = Files.newDirectoryStream(bundlesDir)) { -@@ -107,6 +113,8 @@ public class PrepareBundles { - if ("@types".equals(module.getFileName().toString())) continue; - if ("@esbuild".equals(module.getFileName().toString())) continue; - if ("@microsoft".equals(module.getFileName().toString())) continue; -+ if ("eastasianwidth".equals(module.getFileName().toString())) continue; -+ if ("isarray".equals(module.getFileName().toString())) continue; - Path packageJson = module.resolve("package.json"); - if (Files.isReadable(packageJson)) { - checkModule(module, sb, tokens2Projects, project2License, bundlesDir, targetDir, externalDir, binariesList); diff --git a/patches/7722.diff b/patches/7722.diff deleted file mode 100644 index 38df2c6c..00000000 --- a/patches/7722.diff +++ /dev/null @@ -1,193 +0,0 @@ -diff --git a/extide/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java b/extide/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java -index 1d7ad89a8714..216291f86fd4 100644 ---- a/extide/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java -+++ b/extide/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java -@@ -25,10 +25,10 @@ - import java.security.InvalidKeyException; - import java.security.Key; - import java.security.NoSuchAlgorithmException; -+import java.security.SecureRandom; - import java.util.Collections; - import java.util.HashSet; - import java.util.List; --import java.util.Random; - import java.util.Set; - import java.util.logging.Level; - import java.util.logging.Logger; -@@ -69,7 +69,7 @@ public class ProjectTrust { - byte[] buf = prefs.getByteArray(KEY_SALT, null); - if (buf == null) { - buf = new byte[16]; -- new Random().nextBytes(buf); -+ new SecureRandom().nextBytes(buf); - prefs.putByteArray(KEY_SALT, buf); - } - salt = buf; -@@ -134,7 +134,7 @@ public void trustProject(Project project, boolean permanently) { - if (permanently && !isTrustedPermanently(project)) { - Path trustFile = getProjectTrustFile(project); - byte[] rnd = new byte[16]; -- new Random().nextBytes(rnd); -+ new SecureRandom().nextBytes(rnd); - String projectId = toHex(rnd); - projectTrust.put(pathId, projectId); - try { -diff --git a/ide/projectapi/arch.xml b/ide/projectapi/arch.xml -index e91502b7570b..81349ae3f7d0 100644 ---- a/ide/projectapi/arch.xml -+++ b/ide/projectapi/arch.xml -@@ -509,8 +509,9 @@ Nothing. -

- -

-- If defined, limits search for a parent project to a certain subtree. The property defines absolute path of a folder -- where upwards search for a project in parent folders is terminated. Queries outside of the root will not find any project. -+ If defined, limits search for a parent project to a certain subtree. The property defines the absolute path of a folder -+ where upwards search for a project in parent folders is terminated. Queries outside the root will not find any project. -+ Multiple folders may be specified when delimited with OS-specific path separators (':' on *nix, ';' on Windows). - Currently used for tests so the tested runtime does not escape the workdir. -

-
-diff --git a/ide/projectapi/src/org/netbeans/modules/projectapi/SimpleFileOwnerQueryImplementation.java b/ide/projectapi/src/org/netbeans/modules/projectapi/SimpleFileOwnerQueryImplementation.java -index 05b887129a52..bf4b435f4dbf 100644 ---- a/ide/projectapi/src/org/netbeans/modules/projectapi/SimpleFileOwnerQueryImplementation.java -+++ b/ide/projectapi/src/org/netbeans/modules/projectapi/SimpleFileOwnerQueryImplementation.java -@@ -19,6 +19,7 @@ - - package org.netbeans.modules.projectapi; - -+import java.io.File; - import java.io.IOException; - import java.lang.ref.Reference; - import java.lang.ref.WeakReference; -@@ -27,10 +28,9 @@ - import java.net.URISyntaxException; - import java.net.URL; - import java.util.ArrayList; --import java.util.Arrays; - import java.util.Collections; - import java.util.HashMap; --import java.util.HashSet; -+import java.util.LinkedHashSet; - import java.util.List; - import java.util.Map; - import java.util.Set; -@@ -45,6 +45,7 @@ - import org.netbeans.api.project.ProjectManager; - import org.netbeans.spi.project.FileOwnerQueryImplementation; - import org.openide.filesystems.FileObject; -+import org.openide.filesystems.FileUtil; - import org.openide.filesystems.URLMapper; - import org.openide.util.BaseUtilities; - import org.openide.util.NbPreferences; -@@ -59,21 +60,19 @@ public class SimpleFileOwnerQueryImplementation implements FileOwnerQueryImpleme - private static final Logger LOG = Logger.getLogger(SimpleFileOwnerQueryImplementation.class.getName()); - private static final URI UNOWNED_URI = URI.create("http:unowned"); - private static final Set forbiddenFolders; -- private static final String projectScanRoot; -+ private static final Set projectScanRoots; - - static { -- Set files = new HashSet(); -- String root = null; -+ Set folders = null; -+ Set roots = null; - try { -- root = System.getProperty("project.limitScanRoot"); // NOI18N -- String forbidden = System.getProperty("project.forbiddenFolders", System.getProperty("versioning.forbiddenFolders", "")); //NOI18N -- files.addAll(Arrays.asList(forbidden.split("\\;"))); //NOI18N -- files.remove(""); //NOI18N -+ roots = separatePaths(System.getProperty("project.limitScanRoot"), File.pathSeparator); //NOI18N -+ folders = separatePaths(System.getProperty("project.forbiddenFolders", System.getProperty("versioning.forbiddenFolders")), ";"); //NOI18N - } catch (Exception e) { - LOG.log(Level.INFO, e.getMessage(), e); - } -- forbiddenFolders = files; -- projectScanRoot = root; -+ forbiddenFolders = folders == null ? Collections.emptySet() : folders; -+ projectScanRoots = roots; - } - - /** Do nothing */ -@@ -113,7 +112,7 @@ public Project getOwner(FileObject f) { - - deserialize(); - while (f != null) { -- if (projectScanRoot != null && !f.getPath().startsWith(projectScanRoot)) { -+ if (projectScanRoots != null && projectScanRoots.stream().noneMatch(f.getPath()::startsWith)) { - break; - } - boolean folder = f.isFolder(); -@@ -137,8 +136,8 @@ public Project getOwner(FileObject f) { - } - folders.add(f); - if (!forbiddenFolders.contains(f.getPath()) && -- !hasRoot(externalOwners.keySet(), f, folder, furi) && -- !hasRoot(deserializedExternalOwners.keySet(), f, folder, furi)) { -+ !hasRoot(externalOwners.keySet(), f, true, furi) && -+ !hasRoot(deserializedExternalOwners.keySet(), f, true, furi)) { - Project p; - try { - p = ProjectManager.getDefault().findProject(f); -@@ -414,6 +413,40 @@ private static URI goUp(URI u) { - assert u.toString().startsWith(nue.toString()) : "not a parent: " + nue + " of " + u; - return nue; - } -+ -+ private static Set separatePaths(String joinedPaths, String pathSeparator) { -+ if (joinedPaths == null || joinedPaths.isEmpty()) -+ return null; -+ -+ Set paths = null; -+ for (String split : joinedPaths.split(pathSeparator)) { -+ if ((split = split.trim()).isEmpty()) continue; -+ -+ // Ensure that variations in terms of ".." or "." or windows drive-letter case differences are removed. -+ // File.getCanonicalFile() will additionally resolve symlinks, which is not required. -+ File file = FileUtil.normalizeFile(new File(split)); -+ -+ // Store FileObject.getPath(); because getOwner() compares these with FileObject.getPath() strings. -+ // This has some peculiarities as compared to File.getAbsolutePath(); such as return "" for File("/"). -+ FileObject fileObject = FileUtil.toFileObject(file); -+ // This conversion may get rid of non-existent paths. -+ if (fileObject == null) continue; -+ -+ String path = fileObject.getPath(); -+ if (path == null || path.isEmpty()) continue; -+ -+ if (paths == null) { -+ paths = Collections.singleton(path); // more performant in usage when only a single element is present. -+ } else { -+ if (paths.size() == 1) { -+ paths = new LinkedHashSet<>(paths); // more performant in iteration -+ } -+ paths.add(path); -+ } -+ } -+ return paths; -+ } -+ - private static final boolean WINDOWS = BaseUtilities.isWindows(); - - } -diff --git a/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java b/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java -index 633ee72340de..3140aba8eafa 100644 ---- a/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java -+++ b/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java -@@ -45,7 +45,6 @@ - import java.util.Collection; - import java.util.Collections; - import java.util.List; --import java.util.Random; - import java.util.logging.Level; - import java.util.logging.Logger; - import org.openide.util.RequestProcessor; -@@ -580,7 +579,7 @@ static Status initialize( - enterState(10, block); - - final byte[] arr = new byte[KEY_LENGTH]; -- new Random().nextBytes(arr); -+ new SecureRandom().nextBytes(arr); - - - final RandomAccessFile os = raf; diff --git a/patches/7724.diff b/patches/7724.diff deleted file mode 100644 index 4b45d216..00000000 --- a/patches/7724.diff +++ /dev/null @@ -1,88 +0,0 @@ -diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -index 212f9ee51f..e3121e03c5 100644 ---- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -@@ -1473,7 +1473,6 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli - refactoring[0] = new RenameRefactoring(Lookups.fixed(lookupContent.toArray(new Object[0]))); - refactoring[0].getContext().add(JavaRefactoringUtils.getClasspathInfoFor(cc.getFileObject())); - refactoring[0].setNewName(params.getNewName()); -- refactoring[0].setSearchInComments(true); //TODO? - } - }, true); - if (cancel.get()) return ; -diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -index 684f5db0a2..b18c7850da 100644 ---- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -@@ -3794,6 +3794,13 @@ public class ServerTest extends NbTestCase { - Set actual = edit.getDocumentChanges().stream().map(this::toString).collect(Collectors.toSet()); - Set expected = new HashSet<>(Arrays.asList("Test2.java:[0:27-0:31=>TestNew, 1:4-1:8=>TestNew, 2:11-2:15=>TestNew]", "Test.java:[0:13-0:17=>TestNew]", "Test.java=>TestNew.java")); - assertEquals(expected, actual); -+ }, -+ cf -> { -+ WorkspaceEdit edit = cf.get(); -+ assertTrue(edit.getChanges().isEmpty()); -+ Set actual = edit.getDocumentChanges().stream().map(this::toString).collect(Collectors.toSet()); -+ Set expected = new HashSet<>(Arrays.asList("Test3.java:[3:14-3:22=>arg, 6:36-6:44=>arg, 7:27-7:35=>arg]")); -+ assertEquals(expected, actual); - }); - } - -@@ -3818,12 +3825,20 @@ public class ServerTest extends NbTestCase { - Set actual = edit.getDocumentChanges().stream().map(this::toString).collect(Collectors.toSet()); - Set expected = new HashSet<>(Arrays.asList("Test2.java:[0:27-0:31=>TestNew, 1:4-1:8=>TestNew, 2:11-2:15=>TestNew]", "Test.java:[0:13-0:17=>TestNew]", "Test.java=>TestNew.java")); - assertEquals(expected, actual); -+ }, -+ cf -> { -+ WorkspaceEdit edit = cf.get(); -+ assertTrue(edit.getChanges().isEmpty()); -+ Set actual = edit.getDocumentChanges().stream().map(this::toString).collect(Collectors.toSet()); -+ Set expected = new HashSet<>(Arrays.asList("Test3.java:[3:14-3:22=>arg, 6:36-6:44=>arg, 7:27-7:35=>arg]")); -+ assertEquals(expected, actual); - }); - } - - private void doTestRename(Consumer settings, - Validator> validateFieldRename, -- Validator> validateClassRename) throws Exception { -+ Validator> validateClassRename, -+ Validator> validateArgumentRename) throws Exception { - File src = new File(getWorkDir(), "Test.java"); - src.getParentFile().mkdirs(); - try (Writer w = new FileWriter(new File(src.getParentFile(), ".test-project"))) {} -@@ -3842,6 +3857,20 @@ public class ServerTest extends NbTestCase { - try (Writer w = new FileWriter(src2)) { - w.write(code2); - } -+ File src3 = new File(getWorkDir(), "Test3.java"); -+ String code3 = "public class Test3 {\n" + -+ " /**\n" + -+ " * They had an argument\n" + -+ " * @param argument\n" + -+ " *\n" + -+ " */\n" + -+ " public static void greet(String argument){\n" + -+ " System.out.println(argument);\n" + -+ " }\n" + -+ "}"; -+ try (Writer w = new FileWriter(src3)) { -+ w.write(code3); -+ } - List[] diags = new List[1]; - CountDownLatch indexingComplete = new CountDownLatch(1); - Launcher serverLauncher = createClientLauncherWithLogging(new LspClient() { -@@ -3899,6 +3928,14 @@ public class ServerTest extends NbTestCase { - - validateClassRename.validate(server.getTextDocumentService().rename(params)); - } -+ server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src3), "java", 0, code3))); -+ { -+ RenameParams params = new RenameParams(new TextDocumentIdentifier(src3.toURI().toString()), -+ new Position(6, 37), -+ "arg"); -+ -+ validateArgumentRename.validate(server.getTextDocumentService().rename(params)); -+ } - } - - public void testMoveClass() throws Exception { diff --git a/patches/7733.diff b/patches/7733.diff deleted file mode 100644 index 4b7646db..00000000 --- a/patches/7733.diff +++ /dev/null @@ -1,614 +0,0 @@ -diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java -index 65e6cd433a03..3312081635cf 100644 ---- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java -+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java -@@ -29,12 +29,15 @@ - import org.openide.filesystems.FileUtil; - import org.openide.util.ChangeSupport; - import org.openide.util.Lookup; -+import org.openide.util.RequestProcessor; - import org.openide.util.WeakListeners; - import org.openide.util.lookup.ServiceProvider; - - @ServiceProvider(service=SingleFileOptionsQueryImplementation.class) - public class AttributeBasedSingleFileOptions implements SingleFileOptionsQueryImplementation { - -+ private static final RequestProcessor WORKER = new RequestProcessor(AttributeBasedSingleFileOptions.class.getName(), 1, false, false); -+ - @Override - public Result optionsFor(FileObject file) { - if (!SingleSourceFileUtil.isSupportedFile(file)) { -@@ -66,6 +69,15 @@ private static final class ResultImpl implements Result { - private final FileChangeListener attributeChanges = new FileChangeAdapter() { - @Override - public void fileAttributeChanged(FileAttributeEvent fe) { -+ if (root != null && registerRoot()) { -+ //propagation of flags from files to the root is usually only -+ //started when the root is indexed. And when the registerRoot -+ //flag is flipped to true on a file in a non-indexed root, -+ //there's no other mechanism to propagate the flag to the root. -+ //So, when the flag is set to true on a file, force the propagation -+ //of the flags for the given root: -+ WORKER.post(() -> SharedRootData.ensureRootRegistered(root)); -+ } - cs.fireChange(); - } - }; -@@ -100,6 +112,14 @@ public URI getWorkDirectory() { - return root != null ? root.toURI() : source.getParent().toURI(); - } - -+ @Override -+ public boolean registerRoot() { -+ Object value = source != null ? source.getAttribute(SingleSourceFileUtil.FILE_REGISTER_ROOT) -+ : root != null ? root.getAttribute(SingleSourceFileUtil.FILE_REGISTER_ROOT) -+ : null; -+ return SingleSourceFileUtil.isTrue(value); -+ } -+ - @Override - public void addChangeListener(ChangeListener listener) { - cs.addChangeListener(listener); -diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java -index 98530378dd60..7f965bee11e2 100644 ---- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java -+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java -@@ -21,10 +21,12 @@ - import java.io.IOException; - import java.util.Enumeration; - import java.util.HashMap; -+import java.util.List; - import java.util.Map; - import java.util.TreeMap; - import java.util.logging.Level; - import java.util.logging.Logger; -+import java.util.stream.Collectors; - import org.netbeans.api.annotations.common.CheckForNull; - import org.netbeans.modules.java.file.launcher.api.SourceLauncher; - import org.openide.filesystems.FileAttributeEvent; -@@ -45,7 +47,13 @@ public class SharedRootData { - private static final Map root2Data = new HashMap<>(); - - public static synchronized void ensureRootRegistered(FileObject root) { -- root2Data.computeIfAbsent(root, r -> new SharedRootData(r)); -+ if (root2Data.get(root) != null) { -+ return ; -+ } -+ -+ SharedRootData data = root2Data.computeIfAbsent(root, r -> new SharedRootData(r)); -+ -+ data.init(); - } - - public static synchronized @CheckForNull SharedRootData getDataForRoot(FileObject root) { -@@ -53,18 +61,18 @@ public static synchronized void ensureRootRegistered(FileObject root) { - } - - private final FileObject root; -- private final Map options = new TreeMap<>(); -+ private final Map properties = new TreeMap<>(); - private final FileChangeListener listener = new FileChangeAdapter() { - @Override - public void fileAttributeChanged(FileAttributeEvent fe) { -- Map newProperties = new HashMap<>(); -+ Map newProperties = new HashMap<>(); - - addPropertiesFor(fe.getFile(), newProperties); - setNewProperties(newProperties); - } - @Override - public void fileDeleted(FileEvent fe) { -- Map newProperties = new HashMap<>(); -+ Map newProperties = new HashMap<>(); - - newProperties.put(FileUtil.getRelativePath(root, fe.getFile()), null); - setNewProperties(newProperties); -@@ -73,9 +81,12 @@ public void fileDeleted(FileEvent fe) { - - private SharedRootData(FileObject root) { - this.root = root; -+ } -+ -+ private void init() { - root.addRecursiveListener(listener); - Enumeration todo = root.getChildren(true); -- Map newProperties = new HashMap<>(); -+ Map newProperties = new HashMap<>(); - while (todo.hasMoreElements()) { - FileObject current = todo.nextElement(); - addPropertiesFor(current, newProperties); -@@ -83,25 +94,32 @@ private SharedRootData(FileObject root) { - setNewProperties(newProperties); - } - -- private void addPropertiesFor(FileObject file, Map newProperties) { -+ private void addPropertiesFor(FileObject file, Map newProperties) { - if (file.isData() && "text/x-java".equals(file.getMIMEType())) { -- newProperties.put(FileUtil.getRelativePath(root, file), (String) file.getAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS)); -+ newProperties.put(FileUtil.getRelativePath(root, file), new FileProperties((String) file.getAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS), -+ SingleSourceFileUtil.isTrue(file.getAttribute(SingleSourceFileUtil.FILE_REGISTER_ROOT)))); - } - } - -- private synchronized void setNewProperties(Map newProperties) { -+ private synchronized void setNewProperties(Map newProperties) { - if (newProperties.isEmpty()) { - return ; - } - for (String key : newProperties.keySet()) { -- String value = newProperties.get(key); -- if (value == null) { -- options.remove(key); -+ FileProperties fileProperties = newProperties.get(key); -+ if (fileProperties == null) { -+ properties.remove(key); - } else { -- options.put(key, value); -+ properties.put(key, fileProperties); - } - } -- String joinedCommandLine = SourceLauncher.joinCommandLines(options.values()); -+ -+ List vmOptions = properties.values() -+ .stream() -+ .map(p -> p.vmOptions) -+ .filter(p -> p != null) -+ .collect(Collectors.toList()); -+ String joinedCommandLine = SourceLauncher.joinCommandLines(vmOptions); - try { - if (!joinedCommandLine.equals(root.getAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS))) { - root.setAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS, joinedCommandLine); -@@ -109,6 +127,21 @@ private synchronized void setNewProperties(Map newProperties) { - } catch (IOException ex) { - LOG.log(Level.INFO, "Failed to set " + SingleSourceFileUtil.FILE_VM_OPTIONS + " for " + root.getPath(), ex); - } -+ Boolean registerRoot = properties.values() -+ .stream() -+ .map(p -> p.registerRoot) -+ .filter(r -> r) -+ .findAny() -+ .isPresent(); -+ try { -+ if (!registerRoot.equals(root.getAttribute(SingleSourceFileUtil.FILE_REGISTER_ROOT))) { -+ root.setAttribute(SingleSourceFileUtil.FILE_REGISTER_ROOT, registerRoot); -+ } -+ } catch (IOException ex) { -+ LOG.log(Level.INFO, "Failed to set " + SingleSourceFileUtil.FILE_REGISTER_ROOT + " for " + root.getPath(), ex); -+ } - } - -+ record FileProperties(String vmOptions, boolean registerRoot) {} -+ - } -diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java -index 0152f195164d..d8fb70bb990a 100644 ---- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java -+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java -@@ -64,6 +64,7 @@ public static int findJavaVersion() throws NumberFormatException { - public static final String FILE_ARGUMENTS = "single_file_run_arguments"; //NOI18N - public static final String FILE_JDK = "single_file_run_jdk"; //NOI18N - public static final String FILE_VM_OPTIONS = "single_file_vm_options"; //NOI18N -+ public static final String FILE_REGISTER_ROOT = "register_root"; //NOI18N - - public static FileObject getJavaFileWithoutProjectFromLookup(Lookup lookup) { - for (DataObject dObj : lookup.lookupAll(DataObject.class)) { -@@ -153,6 +154,10 @@ public static List parseLine(String line, URI workingDirectory) { - return PARSER.doParse(line, workingDirectory); - } - -+ public static boolean isTrue(Object value) { -+ return value instanceof Boolean b && b; -+ } -+ - private static final LineParser PARSER = new LineParser(); - - private static class LineParser extends CompilerOptionsQueryImplementation.Result { -@@ -217,6 +222,10 @@ public URI getWorkDirectory() { - return delegate.getWorkDirectory(); - } - -+ public boolean registerRoot() { -+ return delegate.registerRoot(); -+ } -+ - @Override - public void addChangeListener(ChangeListener listener) { - cs.addChangeListener(listener); -diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java -index 0bfc6bfbc23d..ff0d0ea144b5 100644 ---- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java -+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java -@@ -22,6 +22,7 @@ - import java.beans.PropertyChangeSupport; - import java.io.File; - import java.io.IOException; -+import java.lang.ref.Reference; - import java.net.URL; - import java.util.ArrayList; - import java.util.Arrays; -@@ -90,20 +91,41 @@ public class MultiSourceRootProvider implements ClassPathProvider { - //TODO: the cache will probably be never cleared, as the ClassPath/value refers to the key(?) - private Map file2SourceCP = new WeakHashMap<>(); - private Map root2SourceCP = new WeakHashMap<>(); -+ private Map root2RegistrationRefresh = new WeakHashMap<>(); -+ private final Set registeredRoots = Collections.newSetFromMap(new WeakHashMap<>()); - private Map file2AllPath = new WeakHashMap<>(); - private Map file2ClassPath = new WeakHashMap<>(); - private Map file2ModulePath = new WeakHashMap<>(); - -- static boolean isSupportedFile(FileObject file) { -- return SingleSourceFileUtil.isSingleSourceFile(file) -- // MultiSourceRootProvider assumes it can convert FileObject to -- // java.io.File, so filter here -- && Objects.equals("file", file.toURI().getScheme()); -+ boolean isSupportedFile(FileObject file) { -+ // MultiSourceRootProvider assumes it can convert FileObject to -+ // java.io.File, so filter here -+ if (!Objects.equals("file", file.toURI().getScheme())) { -+ return false; -+ } -+ -+ if (SingleSourceFileUtil.isSingleSourceFile(file)) { -+ return true; -+ } -+ -+ Set registeredRootsCopy; -+ -+ synchronized (registeredRoots) { -+ registeredRootsCopy = registeredRoots; -+ } -+ -+ for (FileObject existingRoot : registeredRootsCopy) { -+ if (file.equals(existingRoot) || FileUtil.isParentOf(existingRoot, file)) { -+ return true; -+ } -+ } -+ -+ return false; - } - - @Override - public ClassPath findClassPath(FileObject file, String type) { -- if (! isSupportedFile(file)) { -+ if (!isSupportedFile(file)) { - return null; - } - switch (type) { -@@ -148,13 +170,17 @@ private ClassPath getSourcePath(FileObject file) { - } - } - -- return root2SourceCP.computeIfAbsent(root, r -> { -- ClassPath srcCP = ClassPathSupport.createClassPath(Arrays.asList(new RootPathResourceImplementation(r))); -- if (registerRoot(r)) { -- GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {srcCP}); -- } -- return srcCP; -+ ClassPath srcCP = root2SourceCP.computeIfAbsent(root, r -> { -+ return ClassPathSupport.createClassPath(Arrays.asList(new RootPathResourceImplementation(r))); - }); -+ -+ ParsedFileOptions options = SingleSourceFileUtil.getOptionsFor(root); -+ -+ if (options != null) { -+ WORKER.post(root2RegistrationRefresh.computeIfAbsent(root, r -> new RegistrationRefresh(srcCP, options, r))); -+ } -+ -+ return srcCP; - } catch (IOException ex) { - LOG.log(Level.FINE, "Failed to read sourcefile " + file, ex); - } -@@ -269,13 +295,6 @@ private ClassPath attributeBasedPath(FileObject file, Map - } - } - -- @Messages({ -- "SETTING_AutoRegisterAsRoot=false" -- }) -- private static boolean registerRoot(FileObject root) { -- return "true".equals(Bundle.SETTING_AutoRegisterAsRoot()); -- } -- - private static final class AttributeBasedClassPathImplementation extends FileChangeAdapter implements ChangeListener, ClassPathImplementation { - private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - private final Task updateDelegatesTask = WORKER.create(this::doUpdateDelegates); -@@ -355,7 +374,10 @@ private void doUpdateDelegates() { - for (File expanded : expandedPaths) { - URL u = FileUtil.urlForArchiveOrDir(expanded); - if (u == null) { -- throw new IllegalArgumentException("Path entry looks to be invalid: " + piece); // NOI18N -+ LOG.log(Level.INFO, -+ "While parsing command line option '{0}' with parameter '{1}', path entry looks to be invalid: '{2}'", -+ new Object[] {currentOption, parsed.get(i + 1), piece}); -+ continue; - } - newURLs.add(u); - newDelegates.add(ClassPathSupport.createResource(u)); -@@ -468,4 +490,43 @@ public void removePropertyChangeListener(PropertyChangeListener listener) { - } - - } -+ -+ private class RegistrationRefresh implements ChangeListener, Runnable { -+ private final ClassPath srcCP; -+ private final ParsedFileOptions options; -+ private final FileObject root; -+ -+ public RegistrationRefresh(ClassPath srcCP, -+ ParsedFileOptions options, -+ FileObject root) { -+ this.srcCP = srcCP; -+ this.options = options; -+ this.root = root; -+ options.addChangeListener(this); -+ } -+ -+ @Override -+ public void run() { -+ GlobalPathRegistry registry = GlobalPathRegistry.getDefault(); -+ if (options.registerRoot()) { -+ synchronized (registeredRoots) { -+ registeredRoots.add(root); -+ } -+ registry.register(ClassPath.SOURCE, new ClassPath[] {srcCP}); -+ } else { -+ synchronized (registeredRoots) { -+ registeredRoots.remove(root); -+ } -+ if (registry.getPaths(ClassPath.SOURCE).contains(srcCP)) { -+ registry.unregister(ClassPath.SOURCE, new ClassPath[] {srcCP}); -+ } -+ } -+ } -+ -+ @Override -+ public void stateChanged(ChangeEvent e) { -+ WORKER.post(this); -+ } -+ } -+ - } -diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/spi/SingleFileOptionsQueryImplementation.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/spi/SingleFileOptionsQueryImplementation.java -index 216706463c3b..cd73cd5e028b 100644 ---- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/spi/SingleFileOptionsQueryImplementation.java -+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/spi/SingleFileOptionsQueryImplementation.java -@@ -28,10 +28,13 @@ public interface SingleFileOptionsQueryImplementation { - public Result optionsFor(FileObject file); - - public interface Result { -- public String getOptions(); -+ public @NonNull String getOptions(); - public default @NonNull URI getWorkDirectory() { - throw new UnsupportedOperationException(); - } -+ public default boolean registerRoot() { -+ return false; -+ } - public void addChangeListener(ChangeListener l); - public void removeChangeListener(ChangeListener l); - } -diff --git a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties b/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/Bundle_registerroots.properties -similarity index 99% -rename from java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties -rename to java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/Bundle_registerroots.properties -index 684c2d3a5fff..d13c21373f31 100644 ---- a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties -+++ b/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/Bundle_registerroots.properties -@@ -14,5 +14,4 @@ - # KIND, either express or implied. See the License for the - # specific language governing permissions and limitations - # under the License. -- - SETTING_AutoRegisterAsRoot=true -diff --git a/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProviderTest.java b/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProviderTest.java -index ff7245d3af48..c89798daad2c 100644 ---- a/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProviderTest.java -+++ b/java/java.file.launcher/test/unit/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProviderTest.java -@@ -19,11 +19,14 @@ - package org.netbeans.modules.java.file.launcher.queries; - - import java.io.File; -+import java.io.FileOutputStream; - import java.io.IOException; -+import java.io.Writer; - import java.net.URI; - import java.nio.file.Files; - import java.util.Arrays; - import java.util.HashSet; -+import java.util.concurrent.atomic.AtomicBoolean; - import java.util.concurrent.atomic.AtomicInteger; - import java.util.concurrent.atomic.AtomicReference; - import javax.swing.event.ChangeListener; -@@ -31,12 +34,15 @@ - import org.netbeans.api.java.classpath.JavaClassPathConstants; - import org.netbeans.api.java.source.TestUtilities; - import org.netbeans.junit.NbTestCase; -+import org.netbeans.modules.java.file.launcher.SingleSourceFileUtil; - import org.netbeans.modules.java.file.launcher.spi.SingleFileOptionsQueryImplementation; - import org.netbeans.modules.java.file.launcher.spi.SingleFileOptionsQueryImplementation.Result; - import org.openide.filesystems.FileObject; - import org.openide.filesystems.FileUtil; - import org.openide.util.ChangeSupport; -+import org.openide.util.Exceptions; - import org.openide.util.Lookup; -+import org.openide.util.NbBundle; - import org.openide.util.lookup.Lookups; - import org.openide.util.lookup.ProxyLookup; - -@@ -254,9 +260,10 @@ public void testMultiSourceRootProviderOnlySupportedForLocalFiles() throws IOExc - supportedFile = Files.createTempFile("dummy", ".java").toFile(); - FileObject realFileSource = FileUtil.createData(supportedFile); - FileObject inMemorySource = FileUtil.createMemoryFileSystem().getRoot().createData("Ahoj.java"); -+ MultiSourceRootProvider provider = new MultiSourceRootProvider(); - -- assertFalse(MultiSourceRootProvider.isSupportedFile(inMemorySource)); -- assertTrue(MultiSourceRootProvider.isSupportedFile(realFileSource)); -+ assertFalse(provider.isSupportedFile(inMemorySource)); -+ assertTrue(provider.isSupportedFile(realFileSource)); - } finally { - if(supportedFile != null && supportedFile.exists()) { - supportedFile.delete(); -@@ -264,6 +271,45 @@ public void testMultiSourceRootProviderOnlySupportedForLocalFiles() throws IOExc - } - } - -+ public void testMultiSourceRootProviderRespondsForKnownFolders() throws IOException { -+ File wd = getWorkDir(); -+ File testDir = new File(wd, "test"); -+ File packDir = new File(testDir, "pack"); -+ File testFile = new File(packDir, "Test.java"); -+ -+ packDir.mkdirs(); -+ -+ try (Writer w = Files.newBufferedWriter(testFile.toPath())) { -+ w.write("package pack;"); -+ } -+ -+ testResult.setOptions(""); -+ testResult.setWorkDirectory(testDir.toURI()); -+ -+ MultiSourceRootProvider provider = new MultiSourceRootProvider(); -+ -+ //before recongizing testDir is a multi-source file root: -+ assertNull(provider.findClassPath(FileUtil.toFileObject(wd), ClassPath.SOURCE)); -+ assertNull(provider.findClassPath(FileUtil.toFileObject(testDir), ClassPath.SOURCE)); -+ assertNull(provider.findClassPath(FileUtil.toFileObject(packDir), ClassPath.SOURCE)); -+ -+ //recognize the source file as a multi-source file: -+ ClassPath cp = provider.findClassPath(FileUtil.toFileObject(testFile), ClassPath.SOURCE); -+ -+ assertNotNull(cp); -+ -+ //check properties: -+ assertNull(provider.findClassPath(FileUtil.toFileObject(wd), ClassPath.SOURCE)); -+ assertNull(provider.findClassPath(FileUtil.toFileObject(testDir), ClassPath.SOURCE)); -+ assertNull(provider.findClassPath(FileUtil.toFileObject(packDir), ClassPath.SOURCE)); -+ -+ testResult.setRegisterRoot(true); -+ -+ assertNull(provider.findClassPath(FileUtil.toFileObject(wd), ClassPath.SOURCE)); -+ assertSame(cp, provider.findClassPath(FileUtil.toFileObject(testDir), ClassPath.SOURCE)); -+ assertSame(cp, provider.findClassPath(FileUtil.toFileObject(packDir), ClassPath.SOURCE)); -+ } -+ - @Override - protected void setUp() throws Exception { - super.setUp(); -@@ -294,6 +340,7 @@ private static class TestResultImpl implements Result { - private final ChangeSupport cs = new ChangeSupport(this); - private final AtomicReference options = new AtomicReference<>(); - private final AtomicReference workdir = new AtomicReference<>(); -+ private final AtomicBoolean registerRoot = new AtomicBoolean(); - - public TestResultImpl() { - } -@@ -318,6 +365,16 @@ public void setWorkDirectory(URI workdir) { - cs.fireChange(); - } - -+ @Override -+ public boolean registerRoot() { -+ return registerRoot.get(); -+ } -+ -+ public void setRegisterRoot(boolean registerRoot) { -+ this.registerRoot.set(registerRoot); -+ cs.fireChange(); -+ } -+ - @Override - public void addChangeListener(ChangeListener l) { - cs.addChangeListener(l); -diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/singlesourcefile/SingleFileOptionsQueryImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/singlesourcefile/SingleFileOptionsQueryImpl.java -index da4898786f11..912078b072d6 100644 ---- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/singlesourcefile/SingleFileOptionsQueryImpl.java -+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/singlesourcefile/SingleFileOptionsQueryImpl.java -@@ -118,7 +118,8 @@ public ResultImpl(Map workspaceFolders2Results, - - @Override - public String getOptions() { -- return workspaceSettings.getOptions(); -+ String options = workspaceSettings.getOptions(); -+ return options != null ? options : ""; - } - - @Override -@@ -129,6 +130,11 @@ public URI getWorkDirectory() { - return workDir.toURI(); - } - -+ @Override -+ public boolean registerRoot() { -+ return true; -+ } -+ - @Override - public void addChangeListener(ChangeListener l) { - cs.addChangeListener(l); -diff --git a/java/java.source/src/org/netbeans/modules/java/Bundle.properties b/java/java.source/src/org/netbeans/modules/java/Bundle.properties -index 74949b6a2eb2..1d3268d9067e 100644 ---- a/java/java.source/src/org/netbeans/modules/java/Bundle.properties -+++ b/java/java.source/src/org/netbeans/modules/java/Bundle.properties -@@ -37,6 +37,8 @@ PROP_JavaNode_singlefile_arguments=Program Arguments - HINT_JavaNode_singlefile_arguments=Arguments passed to the main method while running the file. - PROP_JavaNode_singlefile_options=VM Options - HINT_JavaNode_singlefile_options=VM Options to be considered while running the file. -+PROP_JavaNode_singlefile_registerRoot=Enable Source File Launcher Indexing -+HINT_JavaNode_singlefile_registerRoot=The root corresponding to this file should have source file launcher indexing enabled - PROP_JavaNode_classfile_version=Classfile Version - HINT_JavaNode_classfile_version=The Java API and Language Level of this class file - PROP_JavaNode_compile_classpath=Compile Classpath -diff --git a/java/java.source/src/org/netbeans/modules/java/JavaNode.java b/java/java.source/src/org/netbeans/modules/java/JavaNode.java -index 6dec93234e29..60bfeced4598 100644 ---- a/java/java.source/src/org/netbeans/modules/java/JavaNode.java -+++ b/java/java.source/src/org/netbeans/modules/java/JavaNode.java -@@ -111,6 +111,7 @@ public final class JavaNode extends DataNode implements ChangeListener { - private static final String FILE_ARGUMENTS = "single_file_run_arguments"; //NOI18N - private static final String FILE_JDK = "single_file_run_jdk"; //NOI18N - private static final String FILE_VM_OPTIONS = "single_file_vm_options"; //NOI18N -+ private static final String FILE_REGISTER_ROOT = "register_root"; //NOI18N - - private static final Map IMAGE_CACHE = new ConcurrentHashMap<>(); - private static final boolean ALWAYS_PREFFER_COMPUTED_ICON = Boolean.getBoolean("JavaNode.prefferComputedIcon"); //NOI18N -@@ -242,6 +243,7 @@ protected final Sheet createSheet () { - ss.setName("runFileArguments"); // NOI18N - ss.setDisplayName(getMessage(JavaNode.class, "LBL_JavaNode_without_project_run")); // NOI18N - ss.setShortDescription("Run the file's source code."); -+ ss.put(new JavaFileBooleanAttributeProperty(dObj, FILE_REGISTER_ROOT, "registerRoot", "singlefile_registerRoot")); // NOI18N - ss.put(new RunFileJDKProperty(dObj)); - ss.put(new JavaFileAttributeProperty(dObj, FILE_ARGUMENTS, "runFileArguments", "singlefile_arguments")); // NOI18N - ss.put(new JavaFileAttributeProperty(dObj, FILE_VM_OPTIONS, "runFileVMOptions", "singlefile_options")); // NOI18N -@@ -466,6 +468,33 @@ public Component getCustomEditor() { - - } - -+ // editable file attribute -+ private static final class JavaFileBooleanAttributeProperty extends PropertySupport.ReadWrite { -+ -+ private final String attribute; -+ private final DataObject dObj; -+ -+ public JavaFileBooleanAttributeProperty(DataObject dObj, String attribute, String name, String msgKeyPart) { -+ super(name, Boolean.class, getMessage(JavaNode.class, "PROP_JavaNode_" + msgKeyPart), getMessage(JavaNode.class, "HINT_JavaNode_" + msgKeyPart)); // NOI18N -+ this.dObj = dObj; -+ this.attribute = attribute; -+ } -+ -+ @Override -+ public Boolean getValue() { -+ return dObj.getPrimaryFile().getAttribute(attribute) instanceof Boolean val ? val : false; -+ } -+ -+ @Override -+ public void setValue(Boolean o) { -+ try { -+ dObj.getPrimaryFile().setAttribute(attribute, o); -+ } catch (IOException ex) { -+ LOG.log(Level.WARNING, "Java File does not exist : {0}", dObj.getPrimaryFile().getName()); //NOI18N -+ } -+ } -+ } -+ - // editable file attribute - private static final class JavaFileAttributeProperty extends PropertySupport.ReadWrite { - diff --git a/patches/7750.diff b/patches/7750.diff deleted file mode 100644 index ac35b604..00000000 --- a/patches/7750.diff +++ /dev/null @@ -1,293 +0,0 @@ -diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -index c112b4eb73..ff1fe7f903 100644 ---- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -@@ -44,14 +44,18 @@ import java.net.MalformedURLException; - import java.net.URISyntaxException; - import java.nio.file.Path; - import java.nio.file.Paths; -+import java.util.ArrayDeque; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; - import java.util.Collections; -+import java.util.Comparator; -+import java.util.Deque; - import java.util.EnumMap; - import java.util.EnumSet; - import java.util.HashMap; - import java.util.HashSet; -+import java.util.Iterator; - import java.util.LinkedHashMap; - import java.util.List; - import java.util.Locale; -@@ -1561,12 +1565,13 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli - if (source == null) { - return CompletableFuture.completedFuture(Collections.emptyList()); - } -+ final boolean lineFoldingOnly = client.getNbCodeCapabilities().getClientCapabilities().getTextDocument().getFoldingRange().getLineFoldingOnly() == Boolean.TRUE; - CompletableFuture> result = new CompletableFuture<>(); - try { - source.runUserActionTask(cc -> { - cc.toPhase(JavaSource.Phase.RESOLVED); - Document doc = cc.getSnapshot().getSource().getDocument(true); -- JavaElementFoldVisitor v = new JavaElementFoldVisitor(cc, cc.getCompilationUnit(), cc.getTrees().getSourcePositions(), doc, new FoldCreator() { -+ JavaElementFoldVisitor v = new JavaElementFoldVisitor<>(cc, cc.getCompilationUnit(), cc.getTrees().getSourcePositions(), doc, new FoldCreator() { - @Override - public FoldingRange createImportsFold(int start, int end) { - return createFold(start, end, FoldingRangeKind.Imports); -@@ -1611,7 +1616,10 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli - }); - v.checkInitialFold(); - v.scan(cc.getCompilationUnit(), null); -- result.complete(v.getFolds()); -+ List folds = v.getFolds(); -+ if (lineFoldingOnly) -+ folds = convertToLineOnlyFolds(folds); -+ result.complete(folds); - }, true); - } catch (IOException ex) { - result.completeExceptionally(ex); -@@ -1619,6 +1627,76 @@ public class TextDocumentServiceImpl implements TextDocumentService, LanguageCli - return result; - } - -+ /** -+ * Converts a list of code-folds to a line-only Range form, in place of the -+ * finer-grained form of {@linkplain Position Position-based} (line, column) Ranges. -+ *

-+ * This is needed for LSP clients that do not support the finer grained Range -+ * specification. This is expected to be advertised by the client in -+ * {@code FoldingRangeClientCapabilities.lineFoldingOnly}. -+ * -+ * @implSpec The line-only ranges computed uphold the code-folding invariant that: -+ * a fold does not end at the same point where another fold starts. -+ * -+ * @implNote This is performed in {@code O(n log n) + O(n)} time and {@code O(n)} space for the returned list. -+ * -+ * @param folds List of code-folding ranges computed for a textDocument, -+ * containing fine-grained {@linkplain Position Position-based} -+ * (line, column) ranges. -+ * @return List of code-folding ranges computed for a textDocument, -+ * containing coarse-grained line-only ranges. -+ * -+ * @see -+ * LSP FoldingRangeClientCapabilities -+ */ -+ static List convertToLineOnlyFolds(List folds) { -+ if (folds != null && folds.size() > 1) { -+ // Ensure that the folds are sorted in increasing order of their start position -+ folds = new ArrayList<>(folds); -+ folds.sort(Comparator.comparingInt(FoldingRange::getStartLine) -+ .thenComparing(FoldingRange::getStartCharacter)); -+ // Maintain a stack of enclosing folds -+ Deque enclosingFolds = new ArrayDeque<>(); -+ for (FoldingRange fold : folds) { -+ FoldingRange last; -+ while ((last = enclosingFolds.peek()) != null && -+ (last.getEndLine() < fold.getEndLine() || -+ (last.getEndLine() == fold.getEndLine() && last.getEndCharacter() < fold.getEndCharacter()))) { -+ // The last enclosingFold does not enclose this fold. -+ // Due to sortedness of the folds, last also ends before this fold starts. -+ enclosingFolds.pop(); -+ // If needed, adjust last to end on a line prior to this fold start -+ if (last.getEndLine() == fold.getStartLine()) { -+ last.setEndLine(last.getEndLine() - 1); -+ } -+ last.setEndCharacter(null); // null denotes the end of the line. -+ last.setStartCharacter(null); // null denotes the end of the line. -+ } -+ enclosingFolds.push(fold); -+ } -+ // empty the stack; since each fold completely encloses the next higher one. -+ FoldingRange fold; -+ while ((fold = enclosingFolds.poll()) != null) { -+ fold.setEndCharacter(null); // null denotes the end of the line. -+ fold.setStartCharacter(null); // null denotes the end of the line. -+ } -+ // Remove invalid or duplicate folds -+ Iterator it = folds.iterator(); -+ FoldingRange prev = null; -+ while(it.hasNext()) { -+ FoldingRange next = it.next(); -+ if (next.getEndLine() <= next.getStartLine() || -+ (prev != null && prev.equals(next))) { -+ it.remove(); -+ } else { -+ prev = next; -+ } -+ } -+ } -+ return folds; -+ } -+ -+ - @Override - public void didOpen(DidOpenTextDocumentParams params) { - LOG.log(Level.FINER, "didOpen: {0}", params); -diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImplTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImplTest.java -index 0f2bda50ae..06fd93d3e5 100644 ---- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImplTest.java -+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImplTest.java -@@ -18,14 +18,19 @@ - */ - package org.netbeans.modules.java.lsp.server.protocol; - -+import java.util.Collections; -+import java.util.List; - import java.util.concurrent.atomic.AtomicInteger; - import javax.swing.event.DocumentEvent; - import javax.swing.event.DocumentListener; - import javax.swing.text.BadLocationException; - import javax.swing.text.Document; - import javax.swing.text.PlainDocument; -+import org.eclipse.lsp4j.FoldingRange; - import org.netbeans.junit.NbTestCase; - -+import static org.netbeans.modules.java.lsp.server.protocol.TextDocumentServiceImpl.convertToLineOnlyFolds; -+ - public class TextDocumentServiceImplTest extends NbTestCase { - - public TextDocumentServiceImplTest(String name) { -@@ -117,4 +122,141 @@ public class TextDocumentServiceImplTest extends NbTestCase { - fail(String.valueOf(e)); - } - } -+ -+ public void testConvertToLineOnlyFolds() { -+ assertNull(convertToLineOnlyFolds(null)); -+ assertEquals(0, convertToLineOnlyFolds(Collections.emptyList()).size()); -+ List inputFolds, outputFolds; -+ inputFolds = Collections.singletonList(createRange(10, 20)); -+ assertEquals(inputFolds, convertToLineOnlyFolds(inputFolds)); -+ -+ // test stable sort by start index -+ inputFolds = List.of(createRange(10, 20, 9, 9), createRange(5, 9, 9, 9), createRange(10, 19, 9, 9), createRange(10, 14, 13, 13)); -+ outputFolds = List.of(createRange(5, 9), createRange(10, 20), createRange(10, 19), createRange(10, 14)); -+ assertEquals(outputFolds, convertToLineOnlyFolds(inputFolds)); -+ -+ // test already disjoint folds -+ inputFolds = List.of(createRange(10, 20, 9, 9), createRange(5, 9, 9, 9), createRange(15, 19, 13, 13), createRange(10, 14, 13, 13)); -+ outputFolds = List.of(createRange(5, 9), createRange(10, 20), createRange(10, 14), createRange(15, 19)); -+ assertEquals(outputFolds, convertToLineOnlyFolds(inputFolds)); -+ -+ // test invariant of range.endLine: there exists no otherRange.startLine == range.endLine. -+ inputFolds = List.of(createRange(10, 20, 35, 9), createRange(5, 10, 12, 9), createRange(15, 19, 20, 13), createRange(10, 15, 51, 13)); -+ assertEquals(outputFolds, convertToLineOnlyFolds(inputFolds)); -+ -+ // test a complex example of a full file: -+//import java.util.ArrayList; -+//import java.util.Collection; -+//import java.util.Collections; -+// -+///** -+// * A top-class action performer -+// * -+// * @since 1.1 -+// */ -+//public class TopClass { -+// -+// private final String action; -+// private final int index; -+// -+// /** -+// * @param action Top action to be done -+// */ -+// public TopClass(String action) { -+// this(action, 0); -+// } -+// -+// /** -+// * @param action Top action to be done -+// * @param index Action index -+// */ -+// public TopClass(String action, int index) { -+// this.action = action; -+// this.index = index; -+// } -+// -+// public void doSomethingTopClass(TopClass tc) { -+// // what can we do -+// { -+// if (tc == this) { -+// return; -+// } else if (tc.getClass() == this.getClass()) { -+// } else if (tc.getClass().isAssignableFrom(this.getClass())) { -+// -+// } else { -+// if (true) { -+// switch (tc) { -+// default: { /* this is some comment */ ; } -+// /// some outside default -+// } -+// } else { if (true) { { /* some */ } { /* bad blocks */ } -+// }} -+// /* done */ -+// } -+// } -+// tc.doSomethingTopClass(tc); -+// } -+// -+// public class InnerClass { -+// @Override -+// public String toString() { -+// StringBuilder sb = new StringBuilder(); -+// sb.append("InnerClass{"); -+// sb.append("action=").append(action); -+// sb.append(", index=").append(index); -+// sb.append('}'); -+// return sb.toString(); -+// } -+// } -+//} -+ inputFolds = List.of( -+ createRange(27, 30, 48, 5), -+ createRange(0, 3, 7, 30), -+ createRange(32, 52, 51, 5), -+ createRange(37, 38, 59, 13), -+ createRange(34, 50, 10, 9), -+ createRange(46, 46, 39, 51), -+ createRange(35, 37, 30, 13), -+ createRange(38, 40, 74, 13), -+ createRange(40, 49, 21, 13), -+ createRange(46, 47, 37, 17), -+ createRange(41, 46, 28, 17), -+ createRange(42, 45, 34, 21), -+ createRange(11, 66, 24, 1), -+ createRange(43, 43, 35, 65), -+ createRange(46, 47, 25, 18), -+ createRange(54, 64, 30, 5), -+ createRange(46, 46, 54, 72), -+ createRange(6, 10, 4, 1), -+ createRange(56, 63, 35, 9) -+ ); -+ outputFolds = List.of( -+ createRange(0, 3), -+ createRange(6, 10), -+ createRange(11, 66), -+ createRange(27, 30), -+ createRange(32, 52), -+ createRange(34, 50), -+ createRange(35, 36), -+ createRange(38, 39), -+ createRange(40, 49), -+ createRange(41, 45), -+ createRange(42, 45), -+ createRange(46, 47), -+ createRange(54, 64), -+ createRange(56, 63) -+ ); -+ assertEquals(outputFolds, convertToLineOnlyFolds(inputFolds)); -+ } -+ -+ private static FoldingRange createRange(int startLine, int endLine) { -+ return new FoldingRange(startLine, endLine); -+ } -+ -+ private static FoldingRange createRange(int startLine, int endLine, Integer startColumn, Integer endColumn) { -+ FoldingRange foldingRange = new FoldingRange(startLine, endLine); -+ foldingRange.setStartCharacter(startColumn); -+ foldingRange.setEndCharacter(endColumn); -+ return foldingRange; -+ } - } diff --git a/patches/7910.diff b/patches/7910.diff deleted file mode 100644 index 6a85c4f0..00000000 --- a/patches/7910.diff +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/.gitattributes b/.gitattributes -index b96c7fd985..7c9b72b889 100644 ---- a/.gitattributes -+++ b/.gitattributes -@@ -35,3 +35,7 @@ - - # Define some file types explicitly as being binary. - *.jar binary -+ -+# Define rules for files in specific paths, such as test data, -+# for line endings, binary types etc. -+java/java.hints/test/unit/data/goldenfiles/** text eol=lf -diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/TreeRuleTestBase.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/TreeRuleTestBase.java -index ede2a586e888..a351d52bd5fc 100644 ---- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/TreeRuleTestBase.java -+++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/TreeRuleTestBase.java -@@ -242,9 +242,11 @@ protected String performFixTest(String fileName, String code, int pos, String er - String realCode = toCheckDocument.getText(0, toCheckDocument.getLength()); - - //ignore whitespaces: -- realCode = realCode.replaceAll("[ \t\n]+", " "); -+ realCode = realCode.replaceAll("\\s+", " "); - - if (golden != null) { -+ //ignore CRLF/LF differences in golden: -+ if (!"\n".equals(System.lineSeparator())) golden = golden.replaceAll(System.lineSeparator(), " "); - assertEquals("The output code does not match the expected code.", golden, realCode); - } - -diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/indexing/VanillaCompileWorkerTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/indexing/VanillaCompileWorkerTest.java -index bcd1c07c8701..fb4f11400726 100644 ---- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/indexing/VanillaCompileWorkerTest.java -+++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/indexing/VanillaCompileWorkerTest.java -@@ -685,6 +685,7 @@ public void testPreserveValidMethods1() throws Exception { - " System.err.println(\"Hello, world!\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -729,6 +730,7 @@ public void testClearInvalidMethod() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code - compiler.err.cant.resolve.location\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -792,6 +794,7 @@ public void testPreserveValidInitializers() throws Exception { - " private int F5a;\n" + - " private int F5b;\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -834,6 +837,7 @@ public void testBrokenClassHeader1() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -883,6 +887,7 @@ public void testNullReturnUnknown() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -932,6 +937,7 @@ public void testBrokenNewClass() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -983,6 +989,7 @@ public void testReturnBroken() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1037,6 +1044,7 @@ public void testAssertBroken() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1117,6 +1125,7 @@ public void testAnonymousComplex() throws Exception { - " };\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1165,6 +1174,7 @@ public void testFieldInit() throws Exception { - " super();\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1239,6 +1249,7 @@ public void testAnonymousComplex2() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1285,6 +1296,7 @@ public void testNewClass() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code - compiler.err.cant.apply.symbol\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1336,6 +1348,7 @@ public void testUndefNewArray() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1412,6 +1425,7 @@ public void testUndefAnonymous() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1471,6 +1485,7 @@ public void testWeirdSuperCall() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1590,6 +1605,7 @@ public void testAnonymousComplex3() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1690,6 +1706,7 @@ public void testAnonymousComplex4() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code - compiler.err.cant.resolve.location.args\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1763,6 +1780,7 @@ public void testAnonymousComplexCorrect() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1806,6 +1824,7 @@ public void testWarningsAreNotErrors() throws Exception { - " }\n" + - " Test t;\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1878,6 +1897,7 @@ public void testSuperCall() throws Exception { - " public default void test2() {\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -1923,6 +1943,7 @@ public void testStaticInit() throws Exception { - " System.err.println();\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2161,6 +2182,7 @@ public void testMethodWithErroneousInMemberRef() throws Exception { - " \n" + - " public Object test(Object o);\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2242,6 +2264,7 @@ public void testPatternSwitch() throws Exception { - " throw new java.lang.RuntimeException(\"Uncompilable code\");\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2294,6 +2317,7 @@ public void testTypeTest() throws Exception { - " }\n" + - " }\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2339,6 +2363,7 @@ public void testWrongRecordComponent() throws Exception { - " }\n" + - " private final int wait;\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2391,6 +2416,7 @@ public void testRecord1() throws Exception { - " }\n" + - " private final int i;\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - -@@ -2428,6 +2454,7 @@ public void testRecord2() throws Exception { - " }\n" + - " private final int i;\n" + - "}"); -+ if (!"\n".equals(System.lineSeparator())) file2Fixed.replaceAll((k, v) -> v.replaceAll(System.lineSeparator(), "\n")); - assertEquals(expected, file2Fixed); - } - diff --git a/patches/7921.diff b/patches/7921.diff deleted file mode 100644 index 75f831d6..00000000 --- a/patches/7921.diff +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -index 7a5a5f40e4f9..85c223130e32 100644 ---- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java -@@ -128,6 +128,7 @@ - import org.eclipse.lsp4j.DocumentSymbol; - import org.eclipse.lsp4j.DocumentSymbolParams; - import org.eclipse.lsp4j.FoldingRange; -+import org.eclipse.lsp4j.FoldingRangeCapabilities; - import org.eclipse.lsp4j.FoldingRangeKind; - import org.eclipse.lsp4j.FoldingRangeRequestParams; - import org.eclipse.lsp4j.Hover; -@@ -160,6 +161,7 @@ - import org.eclipse.lsp4j.SignatureHelpParams; - import org.eclipse.lsp4j.SignatureInformation; - import org.eclipse.lsp4j.SymbolInformation; -+import org.eclipse.lsp4j.TextDocumentClientCapabilities; - import org.eclipse.lsp4j.TextDocumentContentChangeEvent; - import org.eclipse.lsp4j.TextDocumentEdit; - import org.eclipse.lsp4j.TextEdit; -@@ -1638,7 +1640,12 @@ public CompletableFuture> foldingRange(FoldingRangeRequestPar - if (source == null) { - return CompletableFuture.completedFuture(Collections.emptyList()); - } -- final boolean lineFoldingOnly = client.getNbCodeCapabilities().getClientCapabilities().getTextDocument().getFoldingRange().getLineFoldingOnly() == Boolean.TRUE; -+ ClientCapabilities clientCapabilities = client.getNbCodeCapabilities() -+ .getClientCapabilities(); -+ TextDocumentClientCapabilities textDocumentCapabilities = clientCapabilities != null ? clientCapabilities.getTextDocument() : null; -+ FoldingRangeCapabilities foldingRangeCapabilities = textDocumentCapabilities != null ? textDocumentCapabilities.getFoldingRange() : null; -+ Boolean lineFoldingOnlyCapability = foldingRangeCapabilities != null ? foldingRangeCapabilities.getLineFoldingOnly() : null; -+ final boolean lineFoldingOnly = lineFoldingOnlyCapability == Boolean.TRUE; - CompletableFuture> result = new CompletableFuture<>(); - try { - source.runUserActionTask(cc -> { diff --git a/patches/7923.diff b/patches/7923.diff deleted file mode 100644 index a87ce06f..00000000 --- a/patches/7923.diff +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java -index a72abd44ef..12acbc7081 100644 ---- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java -+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/refactoring/MoveRefactoring.java -@@ -420,6 +420,9 @@ public final class MoveRefactoring extends CodeRefactoring { - } - - private static Project getSelectedProject(NamedPath selectedProject) { -+ if (selectedProject == null) { -+ return null; -+ } - try { - String path = selectedProject.getPath(); - return path != null ? FileOwnerQuery.getOwner(Utils.fromUri(path)) : null; -@@ -429,6 +432,9 @@ public final class MoveRefactoring extends CodeRefactoring { - } - - private static FileObject getSelectedRoot(NamedPath selectedRoot) { -+ if (selectedRoot == null) { -+ return null; -+ } - try { - String path = selectedRoot.getPath(); - return path != null ? Utils.fromUri(path) : null; diff --git a/patches/7926.diff b/patches/7926.diff deleted file mode 100644 index 1c1f3ef1..00000000 --- a/patches/7926.diff +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5-nonmac.pass b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5-nonmac.pass -deleted file mode 100644 -index 6564d61694f4..000000000000 ---- a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5-nonmac.pass -+++ /dev/null -@@ -1,3 +0,0 @@ --5:8-5:14:error:cannot find symbol -- symbol:method create() -- location:class TestShortErrors5 -diff --git a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5.pass b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5.pass -index a040a93300df..6564d61694f4 100644 ---- a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5.pass -+++ b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testShortErrors5.pass -@@ -1 +1,3 @@ --5:8-5:14:error:compiler message file broken:key=compiler.err.cant.resolve.location.args arguments=method, create, , , class, javahints.TestShortErrors5, {6}, {7} -+5:8-5:14:error:cannot find symbol -+ symbol:method create() -+ location:class TestShortErrors5 -diff --git a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning-nonmac.pass b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning-nonmac.pass -deleted file mode 100644 -index a04bd4bb6bc3..000000000000 ---- a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning-nonmac.pass -+++ /dev/null -@@ -1 +0,0 @@ --2:13-2:40:warning:[serial] serializable class TestShortErrorsSVUIDWarning has no definition of serialVersionUID -diff --git a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning.pass b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning.pass -index 24348a1a6a23..a04bd4bb6bc3 100644 ---- a/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning.pass -+++ b/java/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest/testTestShortErrorsSVUIDWarning.pass -@@ -1 +1 @@ --2:13-2:40:warning:serializable class javahints.TestShortErrorsSVUIDWarning has no definition of serialVersionUID -+2:13-2:40:warning:[serial] serializable class TestShortErrorsSVUIDWarning has no definition of serialVersionUID -diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest.java -index f173387f11f7..de225bbab0d4 100644 ---- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest.java -+++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/infrastructure/ErrorHintsProviderTest.java -@@ -180,7 +180,7 @@ public void testShortErrors4() throws Exception { - } - - public void testShortErrors5() throws Exception { -- performTest("TestShortErrors5", true); -+ performTest("TestShortErrors5", false); - } - - public void testShortErrors6() throws Exception { -@@ -228,7 +228,7 @@ public void testTestShortErrorsSVUIDWarning() throws Exception { - TestCompilerSettings.commandLine = "-Xlint:serial"; - - try { -- performTest("TestShortErrorsSVUIDWarning", true); -+ performTest("TestShortErrorsSVUIDWarning", false); - } finally { - TestCompilerSettings.commandLine = null; - } diff --git a/patches/generate-dependencies.diff b/patches/generate-dependencies.diff index 8c7bd57a..d2ed3154 100644 --- a/patches/generate-dependencies.diff +++ b/patches/generate-dependencies.diff @@ -562,3 +562,34 @@ index d7e1fec8f9..2ec5fa05e8 100644 + + } } +diff --git a/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java b/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java +index 536df96b0e..8428268f51 100644 +--- a/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java ++++ b/nbbuild/misc/prepare-bundles/src/main/java/org/netbeans/prepare/bundles/PrepareBundles.java +@@ -48,6 +48,9 @@ import java.util.regex.Pattern; + import java.util.stream.Collectors; + import java.util.stream.Stream; + import java.util.zip.ZipEntry; ++import java.security.MessageDigest; ++import java.nio.charset.StandardCharsets; ++import java.math.BigInteger; + + /** + * Prepare bundles and license files for a group of node modules. +@@ -143,7 +146,15 @@ public class PrepareBundles { + LicenseUses use = e.getValue(); + String licenseName = knownLicenseTokens2LicenseKey.get(e.getKey()); + if (licenseName == null) { +- licenseName = use.key + "-" + use.projects.stream().collect(Collectors.joining("-")); ++ ++ String projectsString = use.projects.stream().collect(Collectors.joining("-")); ++ ++ MessageDigest digest = MessageDigest.getInstance("SHA-256"); ++ byte[] hashBytes = digest.digest(projectsString.getBytes(StandardCharsets.UTF_8)); ++ String shasum = String.format("%064x", new BigInteger(1, hashBytes)); ++ ++ licenseName = use.key + "-" + shasum; ++ + try (OutputStream out = Files.newOutputStream(licensesDir.resolve(licenseName))) { + out.write(use.licenseText.getBytes("UTF-8")); + } diff --git a/patches/no-security-manager-allow.diff b/patches/no-security-manager-allow.diff deleted file mode 100644 index 561a0f4a..00000000 --- a/patches/no-security-manager-allow.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/platform/o.n.bootstrap/launcher/unix/nbexec b/platform/o.n.bootstrap/launcher/unix/nbexec -index 1d6ad6e530..228b37cbe2 100755 ---- a/platform/o.n.bootstrap/launcher/unix/nbexec -+++ b/platform/o.n.bootstrap/launcher/unix/nbexec -@@ -192,7 +192,7 @@ fi - # rename old heap dump to .old - mv "${userdir}/var/log/heapdump.hprof" "${userdir}/var/log/heapdump.hprof.old" > /dev/null 2>&1 - --jargs_without_clusters="$jargs -Djava.security.manager=allow" -+jargs_without_clusters="$jargs" - jargs="-Dnetbeans.dirs=\"${clusters}\" $jargs_without_clusters" - - if [ -z "$cachedirspecified" ]; then diff --git a/patches/rename-debugger.diff b/patches/rename-debugger.diff index 9c2dd743..4ab83e19 100644 --- a/patches/rename-debugger.diff +++ b/patches/rename-debugger.diff @@ -27,18 +27,18 @@ index 91bf8e30db..6d9a77e63a 100644 @Override public CompletableFuture> configurations(Supplier> projectSupplier) { diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -index 4fce71a094..2b6362ce37 100644 +index 4c504f9f25..560aaee021 100644 --- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java +++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java -@@ -177,6 +177,7 @@ import org.netbeans.api.sendopts.CommandLine; - import org.netbeans.junit.NbTestCase; +@@ -178,6 +178,7 @@ import org.netbeans.junit.NbTestCase; import org.netbeans.modules.java.hints.infrastructure.JavaErrorProvider; + import static org.netbeans.modules.java.lsp.server.LspTestUtils.tripleSlashUri; import org.netbeans.modules.java.lsp.server.TestCodeLanguageClient; +import org.netbeans.modules.java.lsp.server.debugging.attach.AttachConfigurations; import org.netbeans.modules.java.lsp.server.input.QuickPickItem; import org.netbeans.modules.java.lsp.server.input.ShowQuickPickParams; import org.netbeans.modules.java.lsp.server.input.ShowInputBoxParams; -@@ -1223,7 +1224,7 @@ public class ServerTest extends NbTestCase { +@@ -1224,7 +1225,7 @@ public class ServerTest extends NbTestCase { } private void checkAttachToPort(DebugConnector c) { @@ -47,7 +47,7 @@ index 4fce71a094..2b6362ce37 100644 List arguments = c.getArguments(); assertEquals(2, arguments.size()); assertEquals("hostName", arguments.get(0)); -@@ -1232,7 +1233,7 @@ public class ServerTest extends NbTestCase { +@@ -1233,7 +1234,7 @@ public class ServerTest extends NbTestCase { } private void checkAttachToProcess(DebugConnector c) { diff --git a/script/etc/nbcode.conf b/script/etc/nbcode.conf index 879725aa..532be4c7 100644 --- a/script/etc/nbcode.conf +++ b/script/etc/nbcode.conf @@ -58,7 +58,7 @@ default_cachedir="${DEFAULT_CACHEDIR_ROOT}/dev" # options used by the launcher by default, can be overridden by explicit # command line switches -default_options="--nogui --nosplash --branding nbcode -J-Xmx1G -J-XX:+UseParallelGC -J-XX:GCTimeRatio=4 -J-XX:AdaptiveSizePolicyWeight=90 -J-Djava.awt.headless=true -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions" +default_options="--nogui --nosplash --branding nbcode -J-Xmx1G -J-XX:+UseParallelGC -J-XX:GCTimeRatio=4 -J-XX:AdaptiveSizePolicyWeight=90 -J-Djava.awt.headless=true -J-DTopSecurityManager.disable=true -J--enable-native-access=ALL-UNNAMED -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions" # for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea diff --git a/vscode/package.json b/vscode/package.json index a42deec0..c3bb4794 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -236,6 +236,11 @@ "type": "boolean", "default": false, "description": "%jdk.configuration.disableProjectSearchLimit.description%" + }, + "jdk.completion.warning.time": { + "type": "integer", + "default": 10000, + "description": "%jdk.debugger.configuration.completion.warning.time.description%" } } }, @@ -290,8 +295,13 @@ "vmArgs": { "type": [ "string", + "array", "null" ], + "items": { + "type": "string", + "description": "%jdk.debugger.configuration.vmArgs.items.description%" + }, "description": "%jdk.debugger.configuration.vmArgs.description%", "default": null }, diff --git a/vscode/package.nls.ja.json b/vscode/package.nls.ja.json index 1f07da05..48acea78 100755 --- a/vscode/package.nls.ja.json +++ b/vscode/package.nls.ja.json @@ -50,6 +50,7 @@ "jdk.debugger.configuration.classPaths.description": "JVMの起動のためのクラスパス。", "jdk.debugger.configuration.console.description": "プログラムを起動する指定されたコンソール。", "jdk.debugger.configuration.args.description": "実行クラスの引数", + "jdk.debugger.configuration.vmArgs.items.description": "Single argument for the Java VM", "jdk.debugger.configuration.vmArgs.description": "Java VMの引数", "jdk.debugger.configuration.cwd.description": "プログラム実行の作業ディレクトリ", "jdk.debugger.configuration.env.description": "プログラム実行の環境変数", @@ -60,6 +61,7 @@ "jdk.debugger.configuration.attach.processId.description": "デバッグ対象のプロセスID", "jdk.debugger.configuration.attach.listen.description": "接続するデバッグ対象をリスニング", "jdk.debugger.configuration.attach.timeout.description": "接続を待つ間のタイムアウト", + "jdk.debugger.configuration.completion.warning.time.description": "When code completion takes longer than this specified time (in milliseconds), there will be a warning produced (-1 to disable)", "jdk.initialConfigurations.launchJavaApp.name": "Javaアプリケーションの起動", "jdk.configurationSnippets.name": "Javaアプリケーションの起動", "jdk.configurationSnippets.label": "Java+: Javaアプリケーションの起動", diff --git a/vscode/package.nls.json b/vscode/package.nls.json index 654199e3..0e579fa9 100644 --- a/vscode/package.nls.json +++ b/vscode/package.nls.json @@ -50,6 +50,7 @@ "jdk.debugger.configuration.classPaths.description": "The classpaths for launching the JVM.", "jdk.debugger.configuration.console.description": "The specified console to launch the program.", "jdk.debugger.configuration.args.description": "Arguments for the executed class", + "jdk.debugger.configuration.vmArgs.items.description": "Single argument for the Java VM", "jdk.debugger.configuration.vmArgs.description": "Arguments for the Java VM", "jdk.debugger.configuration.cwd.description": "Working directory for the program execution", "jdk.debugger.configuration.env.description": "Environment variables for the program execution", @@ -60,6 +61,7 @@ "jdk.debugger.configuration.attach.processId.description": "Process Id of the debuggee", "jdk.debugger.configuration.attach.listen.description": "Listen for the debuggee to attach", "jdk.debugger.configuration.attach.timeout.description": "Timeout while waiting to attach", + "jdk.debugger.configuration.completion.warning.time.description": "When code completion takes longer than this specified time (in milliseconds), there will be a warning produced (-1 to disable)", "jdk.initialConfigurations.launchJavaApp.name": "Launch Java App", "jdk.configurationSnippets.name": "Launch Java App", "jdk.configurationSnippets.label": "Java+: Launch Java Application", diff --git a/vscode/package.nls.zh-cn.json b/vscode/package.nls.zh-cn.json index 8bb29e61..5b85d099 100755 --- a/vscode/package.nls.zh-cn.json +++ b/vscode/package.nls.zh-cn.json @@ -50,6 +50,7 @@ "jdk.debugger.configuration.classPaths.description": "用于启动 JVM 的类路径。", "jdk.debugger.configuration.console.description": "用于启动程序的指定控制台。", "jdk.debugger.configuration.args.description": "所执行类的参数", + "jdk.debugger.configuration.vmArgs.items.description": "Single argument for the Java VM", "jdk.debugger.configuration.vmArgs.description": "Java VM 的参数", "jdk.debugger.configuration.cwd.description": "程序执行的工作目录", "jdk.debugger.configuration.env.description": "程序执行的环境变量", @@ -60,6 +61,7 @@ "jdk.debugger.configuration.attach.processId.description": "被调试程序的进程 ID", "jdk.debugger.configuration.attach.listen.description": "监听要附加的被调试程序", "jdk.debugger.configuration.attach.timeout.description": "等待附加操作时的超时", + "jdk.debugger.configuration.completion.warning.time.description": "When code completion takes longer than this specified time (in milliseconds), there will be a warning produced (-1 to disable)", "jdk.initialConfigurations.launchJavaApp.name": "启动 Java 应用程序", "jdk.configurationSnippets.name": "启动 Java 应用程序", "jdk.configurationSnippets.label": "Java+:启动 Java 应用程序", diff --git a/vscode/src/commands/buildOperations.ts b/vscode/src/commands/buildOperations.ts index 1d8bebff..28c8d81c 100644 --- a/vscode/src/commands/buildOperations.ts +++ b/vscode/src/commands/buildOperations.ts @@ -19,21 +19,58 @@ import { l10n } from "../localiser"; import { extCommands, nbCommands } from "./commands"; import { ICommand } from "./types"; import { wrapCommandWithProgress, wrapProjectActionWithProgress } from "./utils"; +import { workspace } from "vscode"; +import * as fs from 'fs'; + +const saveFilesInWorkspaceBeforeBuild = async (callbackFn: Function) => { + const docsTosave: Thenable[] = workspace.textDocuments. + filter(d => fs.existsSync(d.uri.fsPath)). + map(d => d.save()); + await Promise.all(docsTosave); + + return callbackFn(); +} const compileWorkspaceHandler = () => { - return wrapCommandWithProgress(nbCommands.buildWorkspace, l10n.value('jdk.extension.command.progress.compilingWorkSpace'), LOGGER.getOutputChannel()); + const complileFunction = () => + wrapCommandWithProgress(nbCommands.buildWorkspace, + l10n.value('jdk.extension.command.progress.compilingWorkSpace'), + LOGGER.getOutputChannel() + ); + + return saveFilesInWorkspaceBeforeBuild(complileFunction); } const cleanWorkspaceHandler = () => { - return wrapCommandWithProgress(nbCommands.cleanWorkspace,l10n.value('jdk.extension.command.progress.cleaningWorkSpace'), LOGGER.getOutputChannel()); + const cleanFunction = () => wrapCommandWithProgress( + nbCommands.cleanWorkspace, + l10n.value('jdk.extension.command.progress.cleaningWorkSpace'), + LOGGER.getOutputChannel() + ); + + return saveFilesInWorkspaceBeforeBuild(cleanFunction); } const compileProjectHandler = (args: any) => { - wrapProjectActionWithProgress('build', undefined, l10n.value('jdk.extension.command.progress.compilingProject'), LOGGER.getOutputChannel(), args); + const compileProjectFunction = () => + wrapProjectActionWithProgress('build', + undefined, l10n.value('jdk.extension.command.progress.compilingProject'), + LOGGER.getOutputChannel(), + args + ); + + saveFilesInWorkspaceBeforeBuild(compileProjectFunction); } const cleanProjectHandler = (args: any) => { - wrapProjectActionWithProgress('clean', undefined, l10n.value('jdk.extension.command.progress.cleaningProject'), LOGGER.getOutputChannel(), args); + const cleanProjectHandler = () => wrapProjectActionWithProgress('clean', + undefined, + l10n.value('jdk.extension.command.progress.cleaningProject'), + LOGGER.getOutputChannel(), + args + ); + + saveFilesInWorkspaceBeforeBuild(cleanProjectHandler); } @@ -44,10 +81,10 @@ export const registerBuildOperationCommands: ICommand[] = [ }, { command: extCommands.cleanWorkspace, handler: cleanWorkspaceHandler - },{ + }, { command: extCommands.compileProject, handler: compileProjectHandler - },{ + }, { command: extCommands.cleanProject, handler: cleanProjectHandler } diff --git a/vscode/src/commands/debug.ts b/vscode/src/commands/debug.ts index 64522262..48c04593 100644 --- a/vscode/src/commands/debug.ts +++ b/vscode/src/commands/debug.ts @@ -66,7 +66,7 @@ const runDebug = async (noDebug: boolean, testRun: boolean, uri: any, methodName } debugConfig['testRun'] = testRun; const workspaceFolder = vscode.workspace.getWorkspaceFolder(docUri); - if (project) { + if (project || testRun) { debugConfig['projectFile'] = docUri.toString(); debugConfig['project'] = true; } else { diff --git a/vscode/src/debugger/debugger.ts b/vscode/src/debugger/debugger.ts index e9770e61..4fbe5eca 100644 --- a/vscode/src/debugger/debugger.ts +++ b/vscode/src/debugger/debugger.ts @@ -24,7 +24,7 @@ import { l10n } from '../localiser'; import { StreamDebugAdapter } from './streamDebugAdapter'; import { extCommands, nbCommands } from '../commands/commands'; import { argumentsNode, environmentVariablesNode, vmOptionsNode, workingDirectoryNode } from '../views/runConfiguration'; -import { initializeRunConfiguration } from '../utils'; +import { initializeRunConfiguration, parseArguments } from '../utils'; import { globalState } from '../globalState'; export function registerDebugger(context: ExtensionContext): void { @@ -237,7 +237,13 @@ class RunConfigurationProvider implements vscode.DebugConfigurationProvider { if (vmArgs) { if (!config.vmArgs) { config.vmArgs = vmArgs; + } else if (Array.isArray(config.vmArgs)) { + let cfg: string[] = config.vmArgs; + + const result = parseArguments(vmArgs); + cfg.push(...result); } else { + // assume the config is a string config.vmArgs = `${config.vmArgs} ${vmArgs}`; } } @@ -266,4 +272,4 @@ class RunConfigurationProvider implements vscode.DebugConfigurationProvider { }); } -} +} \ No newline at end of file diff --git a/vscode/src/lsp/launchOptions.ts b/vscode/src/lsp/launchOptions.ts index 63e93b0e..d104414b 100644 --- a/vscode/src/lsp/launchOptions.ts +++ b/vscode/src/lsp/launchOptions.ts @@ -53,9 +53,7 @@ const extraLaunchOptions = [ "-J-XX:PerfMaxStringConstLength=10240", "--locale", l10n.nbLocaleCode(), "--start-java-language-server=listen-hash:0", - "--start-java-debug-adapter-server=listen-hash:0", - "-J-DTopSecurityManager.disable=true", - "-J--enable-native-access=ALL-UNNAMED" + "--start-java-debug-adapter-server=listen-hash:0" ]; const prepareUserConfigLaunchOptions = (): string[] => { diff --git a/vscode/src/lsp/listeners/requests/register.ts b/vscode/src/lsp/listeners/requests/register.ts index bb333eab..116b4343 100644 --- a/vscode/src/lsp/listeners/requests/register.ts +++ b/vscode/src/lsp/listeners/requests/register.ts @@ -17,9 +17,16 @@ import { NbLanguageClient } from "../../nbLanguageClient" import { notificationOrRequestListenerType } from "../../types" import { requestListeners } from "./handlers" +import { terminalListeners } from "./terminal" + + +const listeners: notificationOrRequestListenerType[] = [ + ...requestListeners, + ...terminalListeners +]; export const registerRequestListeners = (client: NbLanguageClient) => { - requestListeners.forEach((listener: notificationOrRequestListenerType) => { + listeners.forEach((listener: notificationOrRequestListenerType) => { const { type, handler } = listener; client.onRequest(type, handler); }) diff --git a/vscode/src/lsp/listeners/requests/terminal.ts b/vscode/src/lsp/listeners/requests/terminal.ts new file mode 100644 index 00000000..8e7465ff --- /dev/null +++ b/vscode/src/lsp/listeners/requests/terminal.ts @@ -0,0 +1,54 @@ +/* + Copyright (c) 2023-2025, Oracle and/or its affiliates. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { LineBufferingPseudoterminal } from "../../../views/pseudoTerminal"; +import { CloseOutputRequest, ResetOutputRequest, ShowOutputRequest, WriteOutputRequest } from "../../protocol"; +import { notificationOrRequestListenerType } from "../../types"; + +const writeOutputRequestHandler = (param: any) => { + const outputTerminal = LineBufferingPseudoterminal.getInstance(param.outputName) + outputTerminal.acceptInput(param.message); +} + +const showOutputRequestHandler = (param: any) => { + const outputTerminal = LineBufferingPseudoterminal.getInstance(param) + outputTerminal.show(); +} + +const closeOutputRequestHandler = (param: any) => { + const outputTerminal = LineBufferingPseudoterminal.getInstance(param) + outputTerminal.close(); +} + +const resetOutputRequestHandler = (param: any) => { + const outputTerminal = LineBufferingPseudoterminal.getInstance(param) + outputTerminal.clear(); +} + + +export const terminalListeners: notificationOrRequestListenerType[] = [{ + type: WriteOutputRequest.type, + handler: writeOutputRequestHandler +}, { + type: ShowOutputRequest.type, + handler: showOutputRequestHandler +}, { + type: CloseOutputRequest.type, + handler: closeOutputRequestHandler +}, { + type: ResetOutputRequest.type, + handler: resetOutputRequestHandler +}]; \ No newline at end of file diff --git a/vscode/src/lsp/protocol.ts b/vscode/src/lsp/protocol.ts index fc3dd609..32cd87e2 100644 --- a/vscode/src/lsp/protocol.ts +++ b/vscode/src/lsp/protocol.ts @@ -321,3 +321,25 @@ export function asRange(value: Range | undefined | null): vscode.Range | undefin export function asRanges(value: Range[]): vscode.Range[] { return value.map(value => asRange(value)); } + +export interface OutputMessage { + outputName: string; + message: string; + stdIO: boolean; +} + +export namespace WriteOutputRequest { + export const type = new ProtocolRequestType('output/write'); +} + +export namespace ShowOutputRequest { + export const type = new ProtocolRequestType('output/show'); +} + +export namespace CloseOutputRequest { + export const type = new ProtocolRequestType('output/close'); +} + +export namespace ResetOutputRequest { + export const type = new ProtocolRequestType('output/reset'); +} \ No newline at end of file diff --git a/vscode/src/utils.ts b/vscode/src/utils.ts index 77d07193..9ebd334c 100644 --- a/vscode/src/utils.ts +++ b/vscode/src/utils.ts @@ -301,4 +301,42 @@ export async function initializeRunConfiguration(): Promise { } } return false; -} \ No newline at end of file +} + +const isQuotes = (c: string): boolean => { + return c === "'" || c === '"'; +} + +export const parseArguments = (input: string): string[] => { + const result: string[] = []; + let current = ""; + if (input.search(/['"]/) < 0) return input.split(/\s+/); + for (let i = 0; i < input.length; i++) { + const char = input[i]; + if (char === " ") { + result.push(current); + current = ""; + } else if (isQuotes(char)) { + const quoteType = char; + current += char; + i++; + let f = true; + while (i < input.length && f) { + current += input[i]; + const isEscapingSomethingElse = (i > 1 && input[i - 1] == "\\" && input[i - 2] == "\\"); + if (input[i] === quoteType && input[i - 1] != "\\" && !isEscapingSomethingElse) + f = false; + else + i++; + } + } else { + current += char; + } + } + if (current) { + result.push(current); + } + + return result; +} + diff --git a/vscode/src/views/pseudoTerminal.ts b/vscode/src/views/pseudoTerminal.ts new file mode 100644 index 00000000..6598622c --- /dev/null +++ b/vscode/src/views/pseudoTerminal.ts @@ -0,0 +1,117 @@ +/* + Copyright (c) 2023-2025, Oracle and/or its affiliates. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { Pseudoterminal, EventEmitter, Event, Terminal, window } from "vscode"; + +export class LineBufferingPseudoterminal implements Pseudoterminal { + private static instances = new Map(); + + private writeEmitter = new EventEmitter(); + onDidWrite: Event = this.writeEmitter.event; + + private closeEmitter = new EventEmitter(); + onDidClose?: Event = this.closeEmitter.event; + + private buffer: string = ''; + private isOpen = false; + private readonly name: string; + private terminal: Terminal | undefined; + + private constructor(name: string) { + this.name = name; + } + + open(): void { + this.isOpen = true; + } + + close(): void { + this.isOpen = false; + this.closeEmitter.fire(); + } + + /** + * Accepts partial input strings and logs complete lines when they are formed. + * Also processes carriage returns (\r) to overwrite the current line. + * @param input The string input to the pseudoterminal. + */ + public acceptInput(input: string): void { + if (!this.isOpen) { + return; + } + + for (const char of input) { + if (char === '\n') { + // Process a newline: log the current buffer and reset it + this.logLine(this.buffer.trim()); + this.buffer = ''; + } else if (char === '\r') { + // Process a carriage return: log the current buffer on the same line + this.logInline(this.buffer.trim()); + this.buffer = ''; + } else { + // Append characters to the buffer + this.buffer += char; + } + } + } + + private logLine(line: string): void { + this.writeEmitter.fire(`${line}\r\n`); + } + + private logInline(line: string): void { + // Clear the current line and move the cursor to the start + this.writeEmitter.fire(`\x1b[2K\x1b[1G${line}`); + } + + public flushBuffer(): void { + if (this.buffer.trim().length > 0) { + this.logLine(this.buffer.trim()); + this.buffer = ''; + } + } + + public clear(): void { + this.writeEmitter.fire('\x1b[2J\x1b[3J\x1b[H'); // Clear screen and move cursor to top-left + } + + public show(): void { + if (!this.terminal) { + this.terminal = window.createTerminal({ + name: this.name, + pty: this, + }); + } + this.terminal.show(true); + } + + /** + * Gets an existing instance or creates a new one by the terminal name. + * The terminal is also created and managed internally. + * @param name The name of the pseudoterminal. + * @returns The instance of the pseudoterminal. + */ + public static getInstance(name: string): LineBufferingPseudoterminal { + if (!this.instances.has(name)) { + const instance = new LineBufferingPseudoterminal(name); + this.instances.set(name, instance); + } + const instance = this.instances.get(name)!; + instance.show(); + return instance; + } +} \ No newline at end of file