Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: Jiří Techet techet@gmail.com Date: Sun, 26 Jan 2025 20:44:23 UTC Commit: e3849d8d92c915051b326a36eb0504e8ca2e012b https://github.com/geany/geany-plugins/commit/e3849d8d92c915051b326a36eb0504...
Log Message: ----------- Add LSP plugin
Modified Paths: -------------- MAINTAINERS Makefile.am README build/geany-plugins.nsi build/lsp.m4 configure.ac lsp/AUTHORS lsp/COPYING lsp/ChangeLog lsp/Makefile.am lsp/NEWS lsp/README lsp/data/Makefile.am lsp/data/lsp.conf lsp/deps/Makefile.am lsp/deps/json-glib/json-array.c lsp/deps/json-glib/json-builder.c lsp/deps/json-glib/json-builder.h lsp/deps/json-glib/json-debug.c lsp/deps/json-glib/json-debug.h lsp/deps/json-glib/json-enum-types.c lsp/deps/json-glib/json-enum-types.h lsp/deps/json-glib/json-gboxed.c lsp/deps/json-glib/json-generator.c lsp/deps/json-glib/json-generator.h lsp/deps/json-glib/json-glib.h lsp/deps/json-glib/json-gobject-private.h lsp/deps/json-glib/json-gobject.c lsp/deps/json-glib/json-gobject.h lsp/deps/json-glib/json-gvariant.c lsp/deps/json-glib/json-gvariant.h lsp/deps/json-glib/json-node.c lsp/deps/json-glib/json-object.c lsp/deps/json-glib/json-parser.c lsp/deps/json-glib/json-parser.h lsp/deps/json-glib/json-path.c lsp/deps/json-glib/json-path.h lsp/deps/json-glib/json-reader.c lsp/deps/json-glib/json-reader.h lsp/deps/json-glib/json-scanner.c lsp/deps/json-glib/json-scanner.h lsp/deps/json-glib/json-serializable.c lsp/deps/json-glib/json-types-private.h lsp/deps/json-glib/json-types.h lsp/deps/json-glib/json-utils.c lsp/deps/json-glib/json-utils.h lsp/deps/json-glib/json-value.c lsp/deps/json-glib/json-version-macros.h lsp/deps/json-glib/json-version.h lsp/deps/jsonrpc-glib/jsonrpc-client.c lsp/deps/jsonrpc-glib/jsonrpc-client.h lsp/deps/jsonrpc-glib/jsonrpc-glib.h lsp/deps/jsonrpc-glib/jsonrpc-input-stream-private.h lsp/deps/jsonrpc-glib/jsonrpc-input-stream.c lsp/deps/jsonrpc-glib/jsonrpc-input-stream.h lsp/deps/jsonrpc-glib/jsonrpc-marshalers.c lsp/deps/jsonrpc-glib/jsonrpc-marshalers.h lsp/deps/jsonrpc-glib/jsonrpc-message.c lsp/deps/jsonrpc-glib/jsonrpc-message.h lsp/deps/jsonrpc-glib/jsonrpc-output-stream.c lsp/deps/jsonrpc-glib/jsonrpc-output-stream.h lsp/deps/jsonrpc-glib/jsonrpc-server.c lsp/deps/jsonrpc-glib/jsonrpc-server.h lsp/deps/jsonrpc-glib/jsonrpc-version-macros.h lsp/deps/jsonrpc-glib/jsonrpc-version.h lsp/src/Makefile.am lsp/src/lsp-autocomplete.c lsp/src/lsp-autocomplete.h lsp/src/lsp-code-lens.c lsp/src/lsp-code-lens.h lsp/src/lsp-command.c lsp/src/lsp-command.h lsp/src/lsp-diagnostics.c lsp/src/lsp-diagnostics.h lsp/src/lsp-extension.c lsp/src/lsp-extension.h lsp/src/lsp-format.c lsp/src/lsp-format.h lsp/src/lsp-goto-anywhere.c lsp/src/lsp-goto-anywhere.h lsp/src/lsp-goto-panel.c lsp/src/lsp-goto-panel.h lsp/src/lsp-goto.c lsp/src/lsp-goto.h lsp/src/lsp-highlight.c lsp/src/lsp-highlight.h lsp/src/lsp-hover.c lsp/src/lsp-hover.h lsp/src/lsp-log.c lsp/src/lsp-log.h lsp/src/lsp-main.c lsp/src/lsp-progress.c lsp/src/lsp-progress.h lsp/src/lsp-rename.c lsp/src/lsp-rename.h lsp/src/lsp-rpc.c lsp/src/lsp-rpc.h lsp/src/lsp-selection-range.c lsp/src/lsp-selection-range.h lsp/src/lsp-semtokens.c lsp/src/lsp-semtokens.h lsp/src/lsp-server.c lsp/src/lsp-server.h lsp/src/lsp-signature.c lsp/src/lsp-signature.h lsp/src/lsp-symbol-kinds.c lsp/src/lsp-symbol-kinds.h lsp/src/lsp-symbol-tree.c lsp/src/lsp-symbol-tree.h lsp/src/lsp-symbol.c lsp/src/lsp-symbol.h lsp/src/lsp-symbols.c lsp/src/lsp-symbols.h lsp/src/lsp-sync.c lsp/src/lsp-sync.h lsp/src/lsp-utils.c lsp/src/lsp-utils.h lsp/src/lsp-workspace-folders.c lsp/src/lsp-workspace-folders.h lsp/src/spawn/lspunixinputstream.c lsp/src/spawn/lspunixinputstream.h lsp/src/spawn/lspunixoutputstream.c lsp/src/spawn/lspunixoutputstream.h lsp/src/spawn/spawn.c lsp/src/spawn/spawn.h po/POTFILES.in po/POTFILES.skip
Modified: MAINTAINERS 7 lines changed, 7 insertions(+), 0 deletions(-) =================================================================== @@ -194,6 +194,13 @@ M: Frank Lanitz frank@frank.uvena.de W: http://plugins.geany.org/lipsum.html S: Maintained
+lsp +P: Jiří Techet techet@gmail.com +g: @techee +M: Jiří Techet techet@gmail.com +W: http://plugins.geany.org/lsp.html +S: Maintained + markdown P: Matthew Brush matt@geany.org g: @codebrainz
Modified: Makefile.am 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -109,6 +109,10 @@ if ENABLE_LIPSUM SUBDIRS += lipsum endif
+if ENABLE_LSP +SUBDIRS += lsp +endif + if ENABLE_MARKDOWN SUBDIRS += markdown endif
Modified: README 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -71,6 +71,7 @@ Available plugins are: * ``latex`` -- the LaTeX plugin * ``lineoperations`` -- simple line functions that can be applied to an open file * ``lipsum`` -- the Lipsum plugin +* ``lsp`` -- the LSP plugin * ``markdown`` -- the Markdown plugin * ``overview``-- the overview plugin * ``pairtaghighlighter`` -- the PairTagHighlighter plugin
Modified: build/geany-plugins.nsi 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -198,6 +198,7 @@ Section Uninstall Delete "$INSTDIR\lib\geany\keyrecord.dll" Delete "$INSTDIR\lib\geany\lipsum.dll" Delete "$INSTDIR\lib\geany\lineoperations.dll" + Delete "$INSTDIR\lib\geany\lsp.dll" Delete "$INSTDIR\lib\geany\overview.dll" Delete "$INSTDIR\lib\geany\pairtaghighlighter.dll" Delete "$INSTDIR\lib\geany\pohelper.dll"
Modified: build/lsp.m4 39 lines changed, 39 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,39 @@ +AC_DEFUN([GP_CHECK_LSP], +[ + GP_ARG_DISABLE([LSP], [auto]) + + JSON_GLIB_PACKAGE_NAME=json-glib-1.0 + JSON_GLIB_VERSION=1.10 + JSONRPC_GLIB_PACKAGE_NAME=jsonrpc-glib-1.0 + JSONRPC_GLIB_VERSION=3.44 + + AC_ARG_ENABLE(system-jsonrpc, + AC_HELP_STRING([--enable-system-jsonrpc], + [Force using system json-glib and jsonrpc-glib libraries for the LSP plugin. [[default=no]]]),, + enable_system_jsonrpc=no) + + PKG_CHECK_MODULES([SYSTEM_JSONRPC], + [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION} + ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}], + have_system_jsonrpc=yes + echo "Required system versions of json-glib and jsonrpc-glib found - using them.", + have_system_jsonrpc=no + echo "Required system versions of json-glib and jsonrpc-glib not found - using builtin versions.") + + AS_IF([test x"$enable_system_jsonrpc" = "xyes" || test x"$have_system_jsonrpc" = "xyes"], + [GP_CHECK_PLUGIN_DEPS([LSP], [LSP], + [${JSON_GLIB_PACKAGE_NAME} >= ${JSON_GLIB_VERSION} + ${JSONRPC_GLIB_PACKAGE_NAME} >= ${JSONRPC_GLIB_VERSION}])], + []) + + AM_CONDITIONAL(ENABLE_BUILTIN_JSONRPC, [ test x"$have_system_jsonrpc" = "xno" ]) + + GP_COMMIT_PLUGIN_STATUS([LSP]) + + AC_CONFIG_FILES([ + lsp/Makefile + lsp/deps/Makefile + lsp/src/Makefile + lsp/data/Makefile + ]) +])
Modified: configure.ac 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -55,6 +55,7 @@ GP_CHECK_GITCHANGEBAR GP_CHECK_KEYRECORD GP_CHECK_LINEOPERATIONS GP_CHECK_LIPSUM +GP_CHECK_LSP GP_CHECK_MARKDOWN GP_CHECK_OVERVIEW GP_CHECK_PAIRTAGHIGHLIGHTER
Modified: lsp/AUTHORS 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1 @@ +Jiří Techet techet@gmail.com
Modified: lsp/COPYING 340 lines changed, 340 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License.
Modified: lsp/ChangeLog 0 lines changed, 0 insertions(+), 0 deletions(-) =================================================================== No diff available, check online
Modified: lsp/Makefile.am 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,4 @@ +include $(top_srcdir)/build/vars.auxfiles.mk + +SUBDIRS = deps src data +plugin = lsp
Modified: lsp/NEWS 0 lines changed, 0 insertions(+), 0 deletions(-) =================================================================== No diff available, check online
Modified: lsp/README 288 lines changed, 288 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,288 @@ +=== +LSP +=== + +.. contents:: + +About +===== + +LSP Client is a language server protocol client plugin that allows to run multiple +language servers for various programming languages, making their functionality +accessible to Geany. + +Configuration +============= + +The plugin does not come bundled with any language server; these must +be installed independently of the plugin. For installation and configuration +instructions, please refer to the documentation of the specific servers you plan +to use, as some may have specific requirements. Note that many language servers, +such as ``clangd``, ``pylsp``, and ``gopls``, are often packaged by Linux +distributions, making them easy to install and use. + +You can configure servers and other settings using the User configuration file, +accessible from:: + + Tools->LSP Client->User configuration + +This file provides extensive information about all the settings options, so be +sure to refer to it for more details. The default configuration file comes with +pre-configured values for several language servers; other servers have to be +added manually. + +By default, the LSP plugin is disabled unless explicitly enabled for a +project under + +:: + + Project->Properties->LSP Client + +This behavior can be controlled by the first three configuration options in +the ``[all]`` section of the configuration file. + +Language servers are started lazily, meaning they only launch when you switch +a tab to a file with a filetype that has a corresponding LSP server configured. +After the initial handshake between the client and server, you can check the +result under + +:: + + Tools->LSP Client->Server Initialize Responses + +This file also provides information about the capabilities offered by the server; +for more details, refer to: + +https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17... + +In addition to the User configuration file, you can also create a per-project +configuration file (which can also be shared by multiple projects). This file +can be configured under the + +:: + + Project->Properties->LSP Client + +tab. + +Furthermore, the plugin offers a range of customizable keybindings, which can be +configured from:: + + Edit->Preferences->Keybindings->LSP Client + +Usage +===== + +This section provides an overview of the individual LSP features supported by +the plugin, along with guidance on how to use them. You can enable or disable +each feature in the configuration file, where you can also customize certain +aspects of their behavior. + +Please note that not all language servers support every feature. For more +information on the specific features supported by a language server, consult +the server's documentation. + +Autocompletion +-------------- + +Autocompletion works similarly to Geany's autocompletion feature. You can +configure keybindings triggering the autocompletion popup. + +Function signagure +------------------ + +When you type an open brace after a function name, the plugin displays the +function's signature in a popup window similarly to Geany's behavior. + +Diagnostic messages +------------------- + +LSP diagnostic messages typically include error messages or warnings from +compilers, as well as messages from linters. These messages are highlighted in +the code; the exact style of highlighting can be configured to suit your +preferences. When you hover over the highlighted part with your mouse cursor, +a popup window appears, providing additional details about the issue. It is +also possible to display all diagnostic messages received from the server in +the message window. + +Code actions +------------ + +Some servers offer auto-fixes of certain issues or various refactoring options. +For instance, the ``clangd`` server displays ``fix available`` next to the issue +in the hover popup window. To perform the auto-fix, right-click the line with +the issue and select the corresponding option from the Commands submenu. This +popup can also be invoked by a keybinding. + +Code lenses +----------- + +Code lenses are executable commands that are specific to a particular piece of +code. As Geany's Scintilla component limitations prevent these commands +from being clickable and executable directly in the editor, they are accessible +through the Commands submenu of the context menu, similarly to code actions. + +Semantic token type highlighting +-------------------------------- + +Language servers that provide semantic token support can be used to highlight +types, such as class names, in the code. You can customize various aspects of +how the results are visualized in the editor through the configuration file. + +Hover popup +----------- + +The language server can be configured to display a popup window with detailed +information about the symbol under the mouse cursor. However, as this feature +can be slightly annoying, it is disabled by default. Alternatively, you can +access this feature through a keybinding. + +Symbol tree +----------- + +The LSP symbol tree tab in the sidebar, separate from Geany's Symbols tab, +shows document symbols in a similar manner to the Geany's symbol tree feature. + +Go to symbol definition/declaration +----------------------------------- + +Similarly to Geany, you can navigate to the symbol definition/declaration +by control-clicking it in the document or by using the corresponding keybinding. +This feature is also available from the context menu. + +Go to type definition +--------------------- + +This feature enables quick navigation to the definition of the type associated +with the symbol under the cursor, such as the type of a variable. You can also +access this feature from the context menu. + +Swap header/source +------------------ + +This is a non-standard clangd extension allowing quick swapping between a +source file and the corresponding header. This feature is not supported by +any other language server. + +Find references +--------------- + +This feature finds all references of the symbol under the cursor in the project. +This feature is also accessible from the context menu. + +Find implementations +-------------------- + +This feature allows you to locate all classes that implement the interface under +the cursor. + +Navigation to document/project symbols, files, and line numbers +--------------------------------------------------------------- + +The plugin provides a simple, VSCode-style panel for navigating your project. +The + +:: + + Tools->LSP Client->Go to Anywhere + +command offers four types of navigation options: + +- Open files by typing their name directly in the entry +- Navigate to symbols in the current document by prefixing the query with ``@`` +- Navigate to symbols across the entire project by prefixing the query with ``#`` +- Jump to a specific line in the current document by prefixing the query with ``:`` + +The other related queries in the LSP Client menu (also accessible via a keybinding) +simply pre-fill the prefix for you, but otherwise function identically. + +Code formatting +--------------- + +The code formatting feature allows you to format either the entire document or +a selected portion of code, depending on the LSP server's support for this +functionality. You can access this feature from the context menu. + +Identical symbol highlighting +----------------------------- + +When you click on a symbol in the document, this feature highlights all its +occurrences in the document. You can customize the highlighting style to your +preference by configuring it in the configuration file. Also, it is possible +to disable this feature to be performed automatically, but, instead, manually +through a keybinding. + +Smart selection expanding/shrinking +----------------------------------- + +This feature allows to expand the current text selection to contain the next +upper syntactic element such as a parent block in programming languages or a +parent tag in XML. Selection shrinking works in the opposite direction. + +Document symbol renaming +------------------------ + +This feature leverages the identical symbol highlighting described above to +select all symbol occurrences, create multiple cursors at their positions in the +document, and rename them simultaneously as you type. You can also access this +feature from the context menu. + +Project-wide renaming +--------------------- + +After selecting Rename in Project from the context menu or the plugin menu, +you can rename all symbols in the project. + +**Warning:** This feature has a potential to modify many files and language +servers may not be completely reliable when performing the rename so be very +cautious when using it. The plugin does not perform any additional +checks and does not show any preview of the changes so it is best to use this +feature only after committing all modified files so you can +easily revert to a working state if needed. Since this is potentially a +dangerous operation, to prevent accidental renames, the "Rename" button in the +dialog is not selected by defalut and simply pressing enter just cancels the +dialog. + +Limitations +=========== + +By design, the plugin communicates over stdin/stdout only, is responsible +for launching and terminating the language server process, and supports only +a single language server per file type. + +All of these limitations are addressed by the LSP proxy project available at +https://github.com/techee/lsp-proxy and related issues should be directed there. + +License +======= + +Geany LSP Client is distributed under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. A copy of this license +can be found in the file COPYING included with the source code of this +program. + +Downloads +========= + +Geany LSP Client can be downloaded from the development repository available +at https://github.com/techee/geany-lsp/. In addition, it is also distributed +as part of the combined Geany Plugins release. For more information and +downloads, please visit https://plugins.geany.org/geany-plugins/ + +Development Code +================ + +Get the code from:: + + git clone https://github.com/techee/geany-lsp.git + +Ideas, questions, patches and bug reports +========================================= + +Please direct all questions, bug reports and patches to the development +repository at https://github.com/techee/geany-lsp/ and open the corresponding +bug report or pull request there. + +2023-2024 by Jiří Techet +techet(at)gmail(dot)com
Modified: lsp/data/Makefile.am 5 lines changed, 5 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,5 @@ +include $(top_srcdir)/build/vars.docs.mk + +plugin = lsp + +dist_plugindata_DATA = lsp.conf
Modified: lsp/data/lsp.conf 534 lines changed, 534 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,534 @@ +# The global configuration file, accessible through +# Tools->LSP Client->Global Configuration, defines default values for various +# configuration options. +# +# When accessing the user configuration file using +# Tools->LSP Client->User Configuration, a copy of the global configuration file +# is created in user's configuration directory in which users can override +# various settings from the global configuration file. +# +# In addition, it is possible to create a project-wide configuration file used +# for a single project or shared by multiple projects whose path can be +# specified under Project->Properties->LSP Client->Configuration file. When such +# a file is defined and the project is configured to use the project +# configuration, this configuration file overrides the global configuration +# instead of the user configuration file. +# +# Each configuration file may contain the [all] section which contains settings +# common for all language servers, and several filetype-specific sections +# containing settings specific for the given filetype. The names of these +# sections are identical to the names defined in +# Tools->Configuration Files->filetype_extensions.conf; for instance [Python] +# for the Python programming language (case sensitive). Most of the options can +# appear both in the [all] section and the filetype-specific sections except for +# a few that make only sense in the filetype-specific section, like e.g. the +# 'cmd' option containing the command that starts the server. Any option defined +# in the filetype-specific section overrides identically named option defined in +# the [all] section for that particular language server. +# +# Not all LSP features are supported by all LSP servers. To learn more about +# what features are supported by the particular server you are trying to use, +# you can check the result of the initial client-server handshake by going to +# Tools->LSP Client->Server Initialize Responses (the server must be running +# to see any result). +# +# All servers are automatically restarted when any of the configuration files +# changes. Servers are started lazily after a tab is switched to a document for +# which a server is configured (this means that restart typically means shutdown +# of all servers after which they are started as needed). + + +[all] +# Defines whether the plugin should be enabled automatically for new or existing +# projects (that have not yet been configured to use LSP). This option +# is only valid in the [all] section +enable_by_default=false +# Defines whether the server should be used when no project is open. Servers +# may not work correctly without a project because most of them need to know +# the path to the project directory which corresponds to the path defined under +# Project->Properties->Base path. This option can be partially overridden +# by project_root_marker_patterns, see below +use_without_project=false +# Defines whether the server should be used for files whose path is not within +# the project directory. This option can be partially overridden by +# project_root_marker_patterns, see below +use_outside_project_dir=false +# A semicolon-separated list of glob patterns of files that are typically stored +# inside the root directory of the project. Language servers supporting +# changeNotifications of workspaceFolders (these two values should appear inside +# the server initialize response) can use these marker files to detect root +# project directories of open files. Starting from the open file directory, +# the plugin goes up in the directory structure and tests whether a file +# matching project_root_marker_patterns exists - if it does, such a directory +# is considered to be the root directory of the project. This allows to +# detect projects without any Geany project open and allows the plugin to work +# on multiple projects simultaneously. Typically, the pattern contains +# files/directories such as .git, configure.ac, go.mod, etc. If a pattern is +# found, use_without_project and use_outside_project_dir are ignored +project_root_marker_patterns= +# In additon to standard identifier characters a-zA-Z0-9_, this configuration +# option allows adding extra characters that can appear inside identifiers. +# For instance $- will add '$' and '-' to the above set. +extra_identifier_characters= +# Some servers require that the initialization options configuration is sent +# using workspace/didChangeConfiguration instead of the initialize request. +# This option does this right after the initialize request completes. +send_did_change_configuration=false + +# The number of keybindings that can be assigned to LSP code action commands. +# This option is valid only within the [all] section and changing the value +# requires either the plugin reload or Geany restart +command_keybinding_num=5 +# When the keybinding Command 1 is invoked, it checks whether the +# command_1_regex matches any of the items from the Commands submenu of the +# context menu. The first matched entry is executed. For convenience, regex +# matches are case insensitive. Up to command_keybinding_num command keybindings +# can be specified this way +command_1_regex= +# Regex specifying which of the commands present in the context menu under the +# Commands submenu will be automatically performed on save. If multiple entries +# match, all of them will be performed. For convenience, regex matches are case +# insensitive +command_on_save_regex= + +# When the filetype-specific 'rpc_log' settings is defined, this option +# specifies whether the log should contain all details including method +# parameters, or just the method name and type of the communication +rpc_log_full=false +# Show server's stderr in Geany's stderr (when started from terminal) +show_server_stderr=false +# Tracing level of the server (when supported). When enabled, tracing messages +# are logged into stdout. Valid values are 'off', 'messages', 'verbose' +trace_value=off +# Enables or disables telemetry notification logging to stdout +telemetry_notifications=false + +# Whether LSP should be used for autocompletion +autocomplete_enable=true +# Servers return the label that can be shown in the autocompletion popup for +# individual autocompletion entries, or it is possible to use just the text that +# gets inserted when selecting the entry. See also autocomplete_use_snippets. +autocomplete_use_label=true +# Whether snippets should be shown in the autocompletion list. Snippet support +# is only partial so things may not work as expected. When snippets are enabled, +# it is recommended to use autocomplete_use_label=true, otherwise snippet +# tab stops and other snippet information is shown in the autocompletion popup. +autocomplete_use_snippets=false +# Maximum number of autocompletion entries shown in the popup window (including +# those that will only get visible after scrolling the contents) +autocomplete_window_max_entries=20 +# Maximum number of autocompletion entries shown without scrolling (defining the +# actual height of the popup) +autocomplete_window_max_displayed=8 +# The maximum width of the autocompletion popup in displayed characters +autocomplete_window_max_width=60 +# Whether to automatically apply additional edits defined for the autocompletion +# entry. These are typically imports of the modules where the inserted symbol is +# defined +autocomplete_apply_additional_edits=false +# Semicolon separated list of character sequences which can trigger +# autocompletion. Normally, the server defines these but this option can be used +# to further restrict the list only to some sequences if the server-provided +# value does not work well (e.g. when server's trigger chars for autocompletion +# clash with signature trigger chars - Rust server for instance uses '(' for +# both and omitting '(' in autocomplete sequences shows signature instead) +autocomplete_trigger_sequences= +# Semicolon separated list of words that make the autocompletion popup hide. +# This is useful for instance for languages like Pascal that use keywords +# 'begin' and 'end' which are typically followed by a newline where typing enter +# after these words might select some unwanted word from the autocompletion list. +autocomplete_hide_after_words= +# Whether to perform autocompletion inside strings +autocomplete_in_strings=false +# Show documentation (if available) of selected item in autocompletion popup +# in Geany status bar +autocomplete_show_documentation=true + +# Whether LSP should be used to display diagnostic messages. Typically these are +# compiler errors or warnings +diagnostics_enable=true +# Semicolon-separated glob patterns specifying files for which diagnostic +# messages are not shown. Useful when the server has a problem with some files +diagnostics_disable_for= +# For the statusbar issue number indicator, consider only issues of the +# configured severity or highler. Valid values are: 1 (error), 2 (warning), +# 3 (info), 4 (hint). E.g. setting this value to 2 will show issue number +# for errors and warnings only. +diagnostics_statusbar_severity=2 +# Defines the style of error diagnostics - visual style such as underline, and +# its color. Empty value means that diagnostic messages of the given severity +# are not displayed. +# The first number is the "indicator index" of Scintilla - each style should +# have a unique value from 8 to 31. Can be changed when the value clashes with +# some other plugin. +# The remaining values correspond to +# SCI_INDICSETFORE; SCI_INDICSETALPHA; SCI_INDICSETOUTLINEALPHA; SCI_INDICSETSTYLE +# - see Scintilla documentation for more information +diagnostics_error_style=13;#ff3030;70;255;1 +# Defines the style of warning diagnostics +diagnostics_warning_style=14;#ee00ee;70;255;1 +# Defines the style of information diagnostics +diagnostics_info_style=15;#909090;70;255;14 +# Defines the style of hint diagnostics +diagnostics_hint_style=16;#909090;70;255;14 + +# Whether LSP should be used to show a popup with details when hovering over +# symbols. +hover_enable=false +# Maximum number of lines of the popup window +hover_popup_max_lines=20 +# Maximum number of paragraphs shown in the popup window +hover_popup_max_paragraphs=1000 + +# Whether LSP should be used to show function parameter signatures e.g. after +# typing '(' +signature_enable=true + +# Whether LSP should be used for going to symbol definition/declaration +goto_enable=true + +# Whether LSP should be used for displaying symbols in the sidebar (in a tab +# separate from normal Geany symbols) +document_symbols_enable=true +# The label used for the LSP symbols tab. When left empty, the tab is not +# displayed. This option is only valid in the [all] section +document_symbols_tab_label=LSP Symbols + +# Whether LSP should be used for highlighting semantic tokens in the editor, +# such as types. Most servers don't support this feature so disabled by default. +semantic_tokens_enable=false +# Always perform "full" semantic token request instead of using "delta" +# requests. Can be used when servers don't support delta tokens correctly +semantic_tokens_force_full=false +# Semicolon-separated list of semantic tokens that should be highlighted as +# types. For valid values, see +# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17... +semantic_tokens_types=type;class;enum;interface;struct +# When not empty, Scintilla indicators are used for highlighting semantic +# token types. See diagnostics_error_style for more details about the valid +# values. Note that because of Scintilla limitations, this value cannot be bold +#semantic_tokens_type_style=17;#00007f;255;255;17 +semantic_tokens_type_style= +# When not using semantic_tokens_type_style, this indicates the index in the +# Scintilla lexer used for custom keywords. This feature is supported only by +# some lexers like C/C++ and derived lexers. When using this method, the +# value can be bold but all the occurrences of the given word in the document +# is highlighted regardless of the context in which it is used +semantic_tokens_lexer_kw_index=3 + +# Whether LSP should be used for highlighting all other uses of a variable under +# cursor. +highlighting_enable=true +# Indicator style used for highlighting - see diagnostics_error_style +highlighting_style=18;#b0b0b0;90;255;8 + +# Whether LSP should be used for "code lenses" showing commands available +# for the given line. After right-clicking the line with the code lens, these +# commands are available in the Commands submenu. +code_lens_enable=true +# Defines the foreground and the background color of the code lens indicator. +code_lens_style=#000000;#ffffa0 + +# JSON file containing formatting options defined in +# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17... +# e.g. { "tabSize": 4, "insertSpaces": false }. Supported only by some language +# servers. +#formatting_options_file=/home/some_user/my_formatting_config_file.json +formatting_options_file= +# Like above but with the JSON placed directly into the value. When both +# formatting_options_file and formatting_options are specified, the JSON from +# formatting_options_file is used +formatting_options={ "tabSize": 4, "insertSpaces": false } +# Defines whether the LSP code-formatting feature should be auto-performed +# on every save +format_on_save=false + +# Show progress bar for work in progress server operations. Can be disabled +# when servers do not correctly terminate progress notifications. +progress_bar_enable=true + +# Enable non-standard clangd extension allowing to swap between C/C++ headers +# and sources. Only usable for clangd, it does not work with other servers. +swap_header_source_enable=false + + +# This is a dummy language server configuration describing the available +# language-specific options. Most of the configuration options from the [all] +# section can be used here as well. +# For an extensive list of various servers and their configurations, check +# https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md +# While the configuration options names of neovim differ from Geany, the +# general concepts are similar and applicable here. +[DummyLanguage] +# The command (including parameters and possibly also the full path) used to +# start the LSP server. Instead of starting a new server, it is also possible to +# reuse other language's server using the 'use' option - see the C++ +# configuration +cmd=srvcmd +# The server can be started with additional environment variables (such as foo +# with the value bar, and foo1 with the value bar1 like in the example below). +env=foo=bar;foo1=bar1 +# File containing initialization options of the server. The server is +# automatically restarted when this file is modified from within Geany +initialization_options_file=/home/some_user/init_options.json +# Like above but with the JSON placed directly into the value. When both +# initialization_options_file and formatting_options are specified, the JSON +# from initialization_options_file is used +initialization_options={"compilationDatabasePath": "/home/some_user/"} +# When defined, performs logging to the specified file where all RPC +# communication between the client plugin and the server will be stored (can +# also be 'stdout' or 'stderr') +rpc_log=stdout +# Additional files and their mappings to LSP language IDs for which the server +# is used as well. The Nth item in the list is always a LSP language ID and the +# (N+1)th item is a glob pattern defining files for which the language ID is +# used +lang_id_mappings=dummylanguage;*.dummy + + +[C] +# By default, clangd expects compile_commands.json inside the 'build' directory +# of your project. You can create it using either 'meson setup build' if your +# project uses meson or e.g. using: +# mkdir build; bear --output build/compile_commands.json -- make +# if your project uses some other build tool (you need to install the bear tool +# first). The compile_commands.json file has to be manually regenerated when +# the build is modified in any way, such as a file is added/removed. +cmd=clangd +swap_header_source_enable=true +autocomplete_in_strings=true +autocomplete_use_label=false +semantic_tokens_enable=true +#initialization_options={"compilationDatabasePath": "/home/some_user/my_project/my_builddir"} +formatting_options={ "tabSize": 4, "insertSpaces": false } +command_1_regex=Apply fix:.* +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[C++] +# Don't start a new server but reuse the server defined for some other language +# instead (C server used for C++ in this case) +use=C + + +[CSS] +cmd=vscode-css-language-server --stdio +extra_identifier_characters=- +send_did_change_configuration=true +autocomplete_use_snippets=true +use_without_project=true +use_outside_project_dir=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Dart] +cmd=dart language-server --protocol=lsp +# everything except ( which conflicts with signature help +autocomplete_trigger_sequences=.;=;$;";';{;/;: +semantic_tokens_enable=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Go] +cmd=gopls +autocomplete_apply_additional_edits=true +lang_id_mappings=go.mod;go.mod;go.sum;go.sum;gotmpl;*tmpl +semantic_tokens_enable=true +semantic_tokens_type_style=17;#00007f;255;255;17 +format_on_save=true +command_on_save_regex=Organize Imports +progress_bar_enable=false +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Haskell] +cmd=haskell-language-server-wrapper --lsp +# Full semantic tokens work but are kind of useless as Scintilla already +# highlights types +semantic_tokens_enable=false +#semantic_tokens_force_full=true +#initialization_options={"plugin": {"semanticTokens": {"config": { }, "globalOn": true}}} +#semantic_tokens_type_style=17;#00007f;255;255;17 +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[HTML] +cmd=vscode-html-language-server --stdio +extra_identifier_characters=& +send_did_change_configuration=true +autocomplete_use_snippets=true +use_without_project=true +use_outside_project_dir=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Java] +cmd=jdtls +autocomplete_use_label=false +#semantic_tokens_enable=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[JSON] +cmd=vscode-json-languageserver --stdio +#initialization_options={"provideFormatter": true, "json": { "schemas": [ { "fileMatch": [ "*.json"], "url": "file:///home/parallels/schema.json"}]}} +send_did_change_configuration=true +autocomplete_use_snippets=true +use_without_project=true +use_outside_project_dir=true +#formatting_options={ "tabSize": 4, "insertSpaces": true } +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[LaTeX] +cmd=texlab +autocomplete_use_snippets=true +extra_identifier_characters=: +use_without_project=true +use_outside_project_dir=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Lua] +cmd=lua-language-server +autocomplete_use_label=false +autocomplete_hide_after_words=do;then;true;false;end;else +use_outside_project_dir=true +use_without_project=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Nix] +cmd=nil +use_without_project=true +use_outside_project_dir=true +extra_identifier_characters=-' +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[PHP] +# Note: Server returns highlighting indices off by 1 and highlighting doesn't work +cmd=phpactor.phar language-server +autocomplete_trigger_sequences=:;>;$;[;@;';;\ +extra_identifier_characters=$ +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Python] +# pip install pyright (or: pipx install pyright) +cmd=pyright-langserver --stdio +cmd=pyright-langserver --stdio +# alternatively pylsp, jedi, ruff +#cmd=pylsp +#cmd=jedi-language-server +#cmd=ruff server +use_outside_project_dir=true +use_without_project=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Ruby] +cmd=solargraph stdio +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Rust] +cmd=rust-analyzer +semantic_tokens_enable=true +autocomplete_trigger_sequences=:;.;' +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Sh] +cmd=bash-language-server start +autocomplete_use_snippets=true +use_outside_project_dir=true +use_without_project=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[TypeScript] +cmd=typescript-language-server --stdio +semantic_tokens_enable=true +use_outside_project_dir=true +use_without_project=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Javascript] +use=TypeScript + + +[XML] +cmd=lemminx +autocomplete_use_snippets=true +diagnostics_statusbar_severity=4 +use_without_project=true +use_outside_project_dir=true +autocomplete_in_strings=true +# see https://github.com/eclipse/lemminx/blob/main/docs/Configuration.md +#initialization_options_file=/home/some_user/init_options.json +#formatting_options={ "tabSize": 4, "insertSpaces": true } +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[YAML] +cmd=yaml-language-server --stdio +#initialization_options={"yaml": {"schemas": { "/home/parallels/schema.json": "*"}}} +use_without_project=true +use_outside_project_dir=true +#formatting_options={ "tabSize": 4, "insertSpaces": true } +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +[Zig] +cmd=zls +semantic_tokens_enable=true +#autocomplete_use_snippets=true +#rpc_log=stdout +#rpc_log_full=true +#show_server_stderr=true + + +# TODO: help needed! Only the above defined language servers have been tested +# (lightly). If you know some other working language server or find a problem +# with the settings above, please open an issue report or a pull request +# on Github.
Modified: lsp/deps/Makefile.am 78 lines changed, 78 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,78 @@ +include $(top_srcdir)/build/vars.build.mk + +noinst_LTLIBRARIES = libjsonrpc.la + +json_glib_srcs = \ + json-glib/json-array.c \ + json-glib/json-builder.c \ + json-glib/json-builder.h \ + json-glib/json-debug.c \ + json-glib/json-debug.h \ + json-glib/json-enum-types.c \ + json-glib/json-enum-types.h \ + json-glib/json-gboxed.c \ + json-glib/json-generator.c \ + json-glib/json-generator.h \ + json-glib/json-glib.h \ + json-glib/json-gobject.c \ + json-glib/json-gobject.h \ + json-glib/json-gobject-private.h \ + json-glib/json-gvariant.c \ + json-glib/json-gvariant.h \ + json-glib/json-node.c \ + json-glib/json-object.c \ + json-glib/json-parser.c \ + json-glib/json-parser.h \ + json-glib/json-path.c \ + json-glib/json-path.h \ + json-glib/json-reader.c \ + json-glib/json-reader.h \ + json-glib/json-scanner.c \ + json-glib/json-scanner.h \ + json-glib/json-serializable.c \ + json-glib/json-types.h \ + json-glib/json-types-private.h \ + json-glib/json-utils.c \ + json-glib/json-utils.h \ + json-glib/json-value.c \ + json-glib/json-version.h \ + json-glib/json-version-macros.h + +jsonrpc_glib_srcs = \ + jsonrpc-glib/jsonrpc-client.c \ + jsonrpc-glib/jsonrpc-client.h \ + jsonrpc-glib/jsonrpc-glib.h \ + jsonrpc-glib/jsonrpc-input-stream.c \ + jsonrpc-glib/jsonrpc-input-stream.h \ + jsonrpc-glib/jsonrpc-input-stream-private.h \ + jsonrpc-glib/jsonrpc-marshalers.c \ + jsonrpc-glib/jsonrpc-marshalers.h \ + jsonrpc-glib/jsonrpc-message.c \ + jsonrpc-glib/jsonrpc-message.h \ + jsonrpc-glib/jsonrpc-output-stream.c \ + jsonrpc-glib/jsonrpc-output-stream.h \ + jsonrpc-glib/jsonrpc-server.c \ + jsonrpc-glib/jsonrpc-server.h \ + jsonrpc-glib/jsonrpc-version.h \ + jsonrpc-glib/jsonrpc-version-macros.h + +if ENABLE_BUILTIN_JSONRPC + +libjsonrpc_la_SOURCES = \ + $(json_glib_srcs) \ + $(jsonrpc_glib_srcs) + +libjsonrpc_la_CPPFLAGS = $(AM_CPPFLAGS) \ + -DG_LOG_DOMAIN="LSP" \ + -DJSON_COMPILATION \ + -DJSONRPC_GLIB_COMPILATION \ + -I$(top_srcdir)/lsp/deps/json-glib \ + -I$(top_srcdir)/lsp/deps/jsonrpc-glib +libjsonrpc_la_CFLAGS = $(AM_CFLAGS) + +# do not enable cppcheck for json-glib or jsonrpc-glib as it generates lots of +# false positives and it's not "our" code anyway +# +# include $(top_srcdir)/build/cppcheck.mk + +endif
Modified: lsp/deps/json-glib/json-array.c 838 lines changed, 838 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,838 @@ +/* json-array.c - JSON array implementation + * + * This file is part of JSON-GLib + * Copyright (C) 2007 OpenedHand Ltd. + * Copyright (C) 2009 Intel Corp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see http://www.gnu.org/licenses/. + * + * Author: + * Emmanuele Bassi ebassi@linux.intel.com + */ + +#include "config.h" + +#include "json-types-private.h" + +/** + * JsonArray: + * + * `JsonArray` is the representation of the array type inside JSON. + * + * A `JsonArray` contains [struct@Json.Node] elements, which may contain + * fundamental types, other arrays or objects. + * + * Since arrays can be arbitrarily big, copying them can be expensive; for + * this reason, they are reference counted. You can control the lifetime of + * a `JsonArray` using [method@Json.Array.ref] and [method@Json.Array.unref]. + * + * To append an element, use [method@Json.Array.add_element]. + * + * To extract an element at a given index, use [method@Json.Array.get_element]. + * + * To retrieve the entire array in list form, use [method@Json.Array.get_elements]. + * + * To retrieve the length of the array, use [method@Json.Array.get_length]. + */ + +G_DEFINE_BOXED_TYPE (JsonArray, json_array, json_array_ref, json_array_unref); + +/** + * json_array_new: (constructor) + * + * Creates a new array. + * + * Return value: (transfer full): the newly created array + */ +JsonArray * +json_array_new (void) +{ + JsonArray *array; + + array = g_slice_new0 (JsonArray); + + array->ref_count = 1; + array->elements = g_ptr_array_new (); + + return array; +} + +/** + * json_array_sized_new: (constructor) + * @n_elements: number of slots to pre-allocate + * + * Creates a new array with `n_elements` slots already allocated. + * + * Return value: (transfer full): the newly created array + */ +JsonArray * +json_array_sized_new (guint n_elements) +{ + JsonArray *array; + + array = g_slice_new0 (JsonArray); + + array->ref_count = 1; + array->elements = g_ptr_array_sized_new (n_elements); + + return array; +} + +/** + * json_array_ref: + * @array: the array to reference + * + * Acquires a reference on the given array. + * + * Return value: (transfer none): the passed array, with the reference count + * increased by one + */ +JsonArray * +json_array_ref (JsonArray *array) +{ + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (array->ref_count > 0, NULL); + + array->ref_count++; + + return array; +} + +/** + * json_array_unref: + * @array: the array to unreference + * + * Releases a reference on the given array. + * + * If the reference count reaches zero, the array is destroyed and all + * its allocated resources are freed. + */ +void +json_array_unref (JsonArray *array) +{ + g_return_if_fail (array != NULL); + g_return_if_fail (array->ref_count > 0); + + if (--array->ref_count == 0) + { + guint i; + + for (i = 0; i < array->elements->len; i++) + json_node_unref (g_ptr_array_index (array->elements, i)); + + g_ptr_array_free (array->elements, TRUE); + array->elements = NULL; + + g_slice_free (JsonArray, array); + } +} + +/** + * json_array_seal: + * @array: the array to seal + * + * Seals the given array, making it immutable to further changes. + * + * This function will recursively seal all elements in the array too. + * + * If the `array` is already immutable, this is a no-op. + * + * Since: 1.2 + */ +void +json_array_seal (JsonArray *array) +{ + guint i; + + g_return_if_fail (array != NULL); + g_return_if_fail (array->ref_count > 0); + + if (array->immutable) + return; + + /* Propagate to all members. */ + for (i = 0; i < array->elements->len; i++) + json_node_seal (g_ptr_array_index (array->elements, i)); + + array->immutable_hash = json_array_hash (array); + array->immutable = TRUE; +} + +/** + * json_array_is_immutable: + * @array: a JSON array + * + * Check whether the given `array` has been marked as immutable by calling + * [method@Json.Array.seal] on it. + * + * Since: 1.2 + * Returns: %TRUE if the array is immutable + */ +gboolean +json_array_is_immutable (JsonArray *array) +{ + g_return_val_if_fail (array != NULL, FALSE); + g_return_val_if_fail (array->ref_count > 0, FALSE); + + return array->immutable; +} + +/** + * json_array_get_elements: + * @array: a JSON array + * + * Retrieves all the elements of an array as a list of nodes. + * + * Return value: (element-type JsonNode) (transfer container) (nullable): the elements + * of the array + */ +GList * +json_array_get_elements (JsonArray *array) +{ + GList *retval; + guint i; + + g_return_val_if_fail (array != NULL, NULL); + + retval = NULL; + for (i = 0; i < array->elements->len; i++) + retval = g_list_prepend (retval, + g_ptr_array_index (array->elements, i)); + + return g_list_reverse (retval); +} + +/** + * json_array_dup_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Retrieves a copy of the element at the given position in the array. + * + * Return value: (transfer full): a copy of the element at the given position + * + * Since: 0.6 + */ +JsonNode * +json_array_dup_element (JsonArray *array, + guint index_) +{ + JsonNode *retval; + + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (index_ < array->elements->len, NULL); + + retval = json_array_get_element (array, index_); + if (!retval) + return NULL; + + return json_node_copy (retval); +} + +/** + * json_array_get_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Retrieves the element at the given position in the array. + * + * Return value: (transfer none): the element at the given position + */ +JsonNode * +json_array_get_element (JsonArray *array, + guint index_) +{ + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (index_ < array->elements->len, NULL); + + return g_ptr_array_index (array->elements, index_); +} + +/** + * json_array_get_int_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the integer value of the element at the given + * position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_int] + * + * Return value: the integer value + * + * Since: 0.8 + */ +gint64 +json_array_get_int_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, 0); + g_return_val_if_fail (index_ < array->elements->len, 0); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, 0); + g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0); + + return json_node_get_int (node); +} + +/** + * json_array_get_double_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the floating point value of the element at + * the given position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_double] + * + * Return value: the floating point value + * + * Since: 0.8 + */ +gdouble +json_array_get_double_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, 0.0); + g_return_val_if_fail (index_ < array->elements->len, 0.0); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, 0.0); + g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0); + + return json_node_get_double (node); +} + +/** + * json_array_get_boolean_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the boolean value of the element at the given + * position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_boolean] + * + * Return value: the boolean value + * + * Since: 0.8 + */ +gboolean +json_array_get_boolean_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, FALSE); + g_return_val_if_fail (index_ < array->elements->len, FALSE); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, FALSE); + g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE); + + return json_node_get_boolean (node); +} + +/** + * json_array_get_string_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the string value of the element at the given + * position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_string] + * + * Return value: (transfer none): the string value + * + * Since: 0.8 + */ +const gchar * +json_array_get_string_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (index_ < array->elements->len, NULL); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, NULL); + g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL); + + if (JSON_NODE_HOLDS_NULL (node)) + return NULL; + + return json_node_get_string (node); +} + +/** + * json_array_get_null_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently checks whether the element at the given position inside the + * array contains a `null` value. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.is_null] + * + * Return value: `TRUE` if the element is `null` + * + * Since: 0.8 + */ +gboolean +json_array_get_null_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, FALSE); + g_return_val_if_fail (index_ < array->elements->len, FALSE); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, FALSE); + + if (JSON_NODE_HOLDS_NULL (node)) + return TRUE; + + if (JSON_NODE_HOLDS_ARRAY (node)) + return json_node_get_array (node) == NULL; + + if (JSON_NODE_HOLDS_OBJECT (node)) + return json_node_get_object (node) == NULL; + + return FALSE; +} + +/** + * json_array_get_array_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the array at the given position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_array] + * + * Return value: (transfer none): the array + * + * Since: 0.8 + */ +JsonArray * +json_array_get_array_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (index_ < array->elements->len, NULL); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, NULL); + g_return_val_if_fail (JSON_NODE_HOLDS_ARRAY (node) || JSON_NODE_HOLDS_NULL (node), NULL); + + if (JSON_NODE_HOLDS_NULL (node)) + return NULL; + + return json_node_get_array (node); +} + +/** + * json_array_get_object_element: + * @array: a JSON array + * @index_: the index of the element to retrieve + * + * Conveniently retrieves the object at the given position inside an array. + * + * See also: [method@Json.Array.get_element], [method@Json.Node.get_object] + * + * Return value: (transfer none): the object + * + * Since: 0.8 + */ +JsonObject * +json_array_get_object_element (JsonArray *array, + guint index_) +{ + JsonNode *node; + + g_return_val_if_fail (array != NULL, NULL); + g_return_val_if_fail (index_ < array->elements->len, NULL); + + node = g_ptr_array_index (array->elements, index_); + g_return_val_if_fail (node != NULL, NULL); + g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL); + + if (JSON_NODE_HOLDS_NULL (node)) + return NULL; + + return json_node_get_object (node); +} + +/** + * json_array_get_length: + * @array: a JSON array + * + * Retrieves the length of the given array + * + * Return value: the length of the array + */ +guint +json_array_get_length (JsonArray *array) +{ + g_return_val_if_fail (array != NULL, 0); + + return array->elements->len; +} + +/** + * json_array_add_element: + * @array: a JSON array + * @node: (transfer full): the element to add + * + * Appends the given `node` inside an array. + */ +void +json_array_add_element (JsonArray *array, + JsonNode *node) +{ + g_return_if_fail (array != NULL); + g_return_if_fail (node != NULL); + + g_ptr_array_add (array->elements, node); +} + +/** + * json_array_add_int_element: + * @array: a JSON array + * @value: the integer value to add + * + * Conveniently adds the given integer value into an array. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.set_int] + * + * Since: 0.8 + */ +void +json_array_add_int_element (JsonArray *array, + gint64 value) +{ + g_return_if_fail (array != NULL); + + json_array_add_element (array, json_node_init_int (json_node_alloc (), value)); +} + +/** + * json_array_add_double_element: + * @array: a JSON array + * @value: the floating point value to add + * + * Conveniently adds the given floating point value into an array. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.set_double] + * + * Since: 0.8 + */ +void +json_array_add_double_element (JsonArray *array, + gdouble value) +{ + g_return_if_fail (array != NULL); + + json_array_add_element (array, json_node_init_double (json_node_alloc (), value)); +} + +/** + * json_array_add_boolean_element: + * @array: a JSON array + * @value: the boolean value to add + * + * Conveniently adds the given boolean value into an array. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.set_boolean] + * + * Since: 0.8 + */ +void +json_array_add_boolean_element (JsonArray *array, + gboolean value) +{ + g_return_if_fail (array != NULL); + + json_array_add_element (array, json_node_init_boolean (json_node_alloc (), value)); +} + +/** + * json_array_add_string_element: + * @array: a JSON array + * @value: the string value to add + * + * Conveniently adds the given string value into an array. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.set_string] + * + * Since: 0.8 + */ +void +json_array_add_string_element (JsonArray *array, + const gchar *value) +{ + JsonNode *node; + + g_return_if_fail (array != NULL); + + node = json_node_alloc (); + + if (value != NULL) + json_node_init_string (node, value); + else + json_node_init_null (node); + + json_array_add_element (array, node); +} + +/** + * json_array_add_null_element: + * @array: a JSON array + * + * Conveniently adds a `null` element into an array + * + * See also: [method@Json.Array.add_element], `JSON_NODE_NULL` + * + * Since: 0.8 + */ +void +json_array_add_null_element (JsonArray *array) +{ + g_return_if_fail (array != NULL); + + json_array_add_element (array, json_node_init_null (json_node_alloc ())); +} + +/** + * json_array_add_array_element: + * @array: a JSON array + * @value: (nullable) (transfer full): the array to add + * + * Conveniently adds an array element into an array. + * + * If `value` is `NULL`, a `null` element will be added instead. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.take_array] + * + * Since: 0.8 + */ +void +json_array_add_array_element (JsonArray *array, + JsonArray *value) +{ + JsonNode *node; + + g_return_if_fail (array != NULL); + + node = json_node_alloc (); + + if (value != NULL) + { + json_node_init_array (node, value); + json_array_unref (value); + } + else + json_node_init_null (node); + + json_array_add_element (array, node); +} + +/** + * json_array_add_object_element: + * @array: a JSON array + * @value: (transfer full) (nullable): the object to add + * + * Conveniently adds an object into an array. + * + * If `value` is `NULL`, a `null` element will be added instead. + * + * See also: [method@Json.Array.add_element], [method@Json.Node.take_object] + * + * Since: 0.8 + */ +void +json_array_add_object_element (JsonArray *array, + JsonObject *value) +{ + JsonNode *node; + + g_return_if_fail (array != NULL); + + node = json_node_alloc (); + + if (value != NULL) + { + json_node_init_object (node, value); + json_object_unref (value); + } + else + json_node_init_null (node); + + json_array_add_element (array, node); +} + +/** + * json_array_remove_element: + * @array: a JSON array + * @index_: the position of the element to be removed + * + * Removes the element at the given position inside an array. + * + * This function will release the reference held on the element. + */ +void +json_array_remove_element (JsonArray *array, + guint index_) +{ + g_return_if_fail (array != NULL); + g_return_if_fail (index_ < array->elements->len); + + json_node_unref (g_ptr_array_remove_index (array->elements, index_)); +} + +/** + * json_array_foreach_element: + * @array: a JSON array + * @func: (scope call): the function to be called on each element + * @data: (closure): data to be passed to the function + * + * Iterates over all elements of an array, and calls a function on + * each one of them. + * + * It is safe to change the value of an element of the array while + * iterating over it, but it is not safe to add or remove elements + * from the array. + * + * Since: 0.8 + */ +void +json_array_foreach_element (JsonArray *array, + JsonArrayForeach func, + gpointer data) +{ + g_return_if_fail (array != NULL); + g_return_if_fail (func != NULL); + + for (guint i = 0; i < array->elements->len; i++) + { + JsonNode *element_node; + + element_node = g_ptr_array_index (array->elements, i); + + (* func) (array, i, element_node, data); + } +} + +/** + * json_array_hash: + * @key: (type JsonArray) (not nullable): a JSON array to hash + * + * Calculates a hash value for the given `key`. + * + * The hash is calculated over the array and all its elements, recursively. + * + * If the array is immutable, this is a fast operation; otherwise, it scales + * proportionally with the length of the array. + * + * Returns: hash value for the key + * Since: 1.2 + */ +guint +json_array_hash (gconstpointer key) +{ + JsonArray *array; /* unowned */ + guint hash = 0; + guint i; + + g_return_val_if_fail (key != NULL, 0); + + array = (JsonArray *) key; + + /* If the array is immutable, we can use the calculated hash. */ + if (array->immutable) + return array->immutable_hash; + + /* Otherwise, calculate the hash. */ + for (i = 0; i < array->elements->len; i++) + { + JsonNode *node = g_ptr_array_index (array->elements, i); + hash ^= (i ^ json_node_hash (node)); + } + + return hash; +} + +/** + * json_array_equal: + * @a: (type JsonArray) (not nullable): a JSON array + * @b: (type JsonArray) (not nullable): another JSON array + * + * Check whether two arrays are equal. + * + * Equality is defined as: + * + * - the array have the same number of elements + * - the values of elements in corresponding positions are equal + * + * Returns: `TRUE` if the arrays are equal, and `FALSE` otherwise + * Since: 1.2 + */ +gboolean +json_array_equal (gconstpointer a, + gconstpointer b) +{ + JsonArray *array_a, *array_b; /* unowned */ + guint length_a, length_b, i; + + g_return_val_if_fail (a != NULL, FALSE); + g_return_val_if_fail (b != NULL, FALSE); + + array_a = (JsonArray *) a; + array_b = (JsonArray *) b; + + /* Identity comparison. */ + if (array_a == array_b) + return TRUE; + + /* Check lengths. */ + length_a = json_array_get_length (array_a); + length_b = json_array_get_length (array_b); + + if (length_a != length_b) + return FALSE; + + /* Check elements. */ + for (i = 0; i < length_a; i++) + { + JsonNode *child_a, *child_b; /* unowned */ + + child_a = json_array_get_element (array_a, i); + child_b = json_array_get_element (array_b, i); + + if (!json_node_equal (child_a, child_b)) + return FALSE; + } + + return TRUE; +}
Modified: lsp/deps/json-glib/json-builder.c 845 lines changed, 845 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,845 @@ +/* json-generator.c - JSON tree builder + * + * This file is part of JSON-GLib + * Copyright (C) 2010 Luca Bruno lethalman88@gmail.com + * Copyright (C) 2015 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see http://www.gnu.org/licenses/. + * + * Author: + * Luca Bruno lethalman88@gmail.com + * Philip Withnall philip.withnall@collabora.co.uk + */ + +/** + * JsonBuilder: + * + * `JsonBuilder` provides an object for generating a JSON tree. + * + * The root of the JSON tree can be either a [struct@Json.Object] or a [struct@Json.Array]. + * Thus the first call must necessarily be either + * [method@Json.Builder.begin_object] or [method@Json.Builder.begin_array]. + * + * For convenience to language bindings, most `JsonBuilder` method return the + * instance, making it easy to chain function calls. + * + * ## Using `JsonBuilder` + * + * ```c + * g_autoptr(JsonBuilder) builder = json_builder_new (); + * + * json_builder_begin_object (builder); + * + * json_builder_set_member_name (builder, "url"); + * json_builder_add_string_value (builder, "http://www.gnome.org/img/flash/two-thirty.png"); + * + * json_builder_set_member_name (builder, "size"); + * json_builder_begin_array (builder); + * json_builder_add_int_value (builder, 652); + * json_builder_add_int_value (builder, 242); + * json_builder_end_array (builder); + * + * json_builder_end_object (builder); + * + * g_autoptr(JsonNode) root = json_builder_get_root (builder); + * + * g_autoptr(JsonGenerator) gen = json_generator_new (); + * json_generator_set_root (gen, root); + * g_autofree char *str = json_generator_to_data (gen, NULL); + * + * // str now contains the following JSON data + * // { "url" : "http://www.gnome.org/img/flash/two-thirty.png", "size" : [ 652, 242 ] } + * ``` + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> + +#include "json-types-private.h" + +#include "json-builder.h" + +struct _JsonBuilderPrivate +{ + GQueue *stack; + JsonNode *root; + gboolean immutable; +}; + +enum +{ + PROP_IMMUTABLE = 1, + PROP_LAST +}; + +static GParamSpec *builder_props[PROP_LAST] = { NULL, }; + +typedef enum +{ + JSON_BUILDER_MODE_OBJECT, + JSON_BUILDER_MODE_ARRAY, + JSON_BUILDER_MODE_MEMBER +} JsonBuilderMode; + +typedef struct +{ + JsonBuilderMode mode; + + union + { + JsonObject *object; + JsonArray *array; + } data; + gchar *member_name; +} JsonBuilderState; + +static void +json_builder_state_free (JsonBuilderState *state) +{ + if (G_LIKELY (state)) + { + switch (state->mode) + { + case JSON_BUILDER_MODE_OBJECT: + case JSON_BUILDER_MODE_MEMBER: + json_object_unref (state->data.object); + g_free (state->member_name); + state->data.object = NULL; + state->member_name = NULL; + break; + + case JSON_BUILDER_MODE_ARRAY: + json_array_unref (state->data.array); + state->data.array = NULL; + break; + + default: + g_assert_not_reached (); + } + + g_slice_free (JsonBuilderState, state); + } +} + +G_DEFINE_TYPE_WITH_PRIVATE (JsonBuilder, json_builder, G_TYPE_OBJECT) + +static void +json_builder_free_all_state (JsonBuilder *builder) +{ + JsonBuilderState *state; + + while (!g_queue_is_empty (builder->priv->stack)) + { + state = g_queue_pop_head (builder->priv->stack); + json_builder_state_free (state); + } + + if (builder->priv->root) + { + json_node_unref (builder->priv->root); + builder->priv->root = NULL; + } +} + +static void +json_builder_finalize (GObject *gobject) +{ + JsonBuilderPrivate *priv = json_builder_get_instance_private ((JsonBuilder *) gobject); + + json_builder_free_all_state (JSON_BUILDER (gobject)); + + g_queue_free (priv->stack); + priv->stack = NULL; + + G_OBJECT_CLASS (json_builder_parent_class)->finalize (gobject); +} + +static void +json_builder_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv; + + switch (prop_id) + { + case PROP_IMMUTABLE: + /* Construct-only. */ + priv->immutable = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +json_builder_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + JsonBuilderPrivate *priv = JSON_BUILDER (gobject)->priv; + + switch (prop_id) + { + case PROP_IMMUTABLE: + g_value_set_boolean (value, priv->immutable); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +json_builder_class_init (JsonBuilderClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * JsonBuilder:immutable: + * + * Whether the tree should be immutable when created. + * + * Making the output immutable on creation avoids the expense + * of traversing it to make it immutable later. + * + * Since: 1.2 + */ + builder_props[PROP_IMMUTABLE] = + g_param_spec_boolean ("immutable", + "Immutable Output", + "Whether the builder output is immutable.", + FALSE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + + gobject_class->set_property = json_builder_set_property; + gobject_class->get_property = json_builder_get_property; + gobject_class->finalize = json_builder_finalize; + + g_object_class_install_properties (gobject_class, PROP_LAST, builder_props); +} + +static void +json_builder_init (JsonBuilder *builder) +{ + JsonBuilderPrivate *priv = json_builder_get_instance_private (builder); + + builder->priv = priv; + + priv->stack = g_queue_new (); + priv->root = NULL; +} + +static inline JsonBuilderMode +json_builder_current_mode (JsonBuilder *builder) +{ + JsonBuilderState *state = g_queue_peek_head (builder->priv->stack); + return state->mode; +} + +static inline gboolean +json_builder_is_valid_add_mode (JsonBuilder *builder) +{ + JsonBuilderMode mode = json_builder_current_mode (builder); + return mode == JSON_BUILDER_MODE_MEMBER || mode == JSON_BUILDER_MODE_ARRAY; +} + +/** + * json_builder_new: + * + * Creates a new `JsonBuilder`. + * + * You can use this object to generate a JSON tree and obtain the root node. + * + * Return value: the newly created builder instance + */ +JsonBuilder * +json_builder_new (void) +{ + return g_object_new (JSON_TYPE_BUILDER, NULL); +} + +/** + * json_builder_new_immutable: (constructor) + * + * Creates a new, immutable `JsonBuilder` instance. + * + * It is equivalent to setting the [property@Json.Builder:immutable] property + * set to `TRUE` at construction time. + * + * Since: 1.2 + * Returns: (transfer full): the newly create builder instance + */ +JsonBuilder * +json_builder_new_immutable (void) +{ + return g_object_new (JSON_TYPE_BUILDER, "immutable", TRUE, NULL); +} + +/** + * json_builder_get_root: + * @builder: a builder + * + * Returns the root of the currently constructed tree. + * + * if the build is incomplete (ie: if there are any opened objects, or any + * open object members and array elements) then this function will return + * `NULL`. + * + * Return value: (nullable) (transfer full): the root node + */ +JsonNode * +json_builder_get_root (JsonBuilder *builder) +{ + JsonNode *root = NULL; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + + if (builder->priv->root) + root = json_node_copy (builder->priv->root); + + /* Sanity check. */ + g_assert (!builder->priv->immutable || + root == NULL || + json_node_is_immutable (root)); + + return root; +} + +/** + * json_builder_reset: + * @builder: a builder + * + * Resets the state of the builder back to its initial state. + */ +void +json_builder_reset (JsonBuilder *builder) +{ + g_return_if_fail (JSON_IS_BUILDER (builder)); + + json_builder_free_all_state (builder); +} + +/** + * json_builder_begin_object: + * @builder: a builder + * + * Opens an object inside the given builder. + * + * You can add a new member to the object by using [method@Json.Builder.set_member_name], + * followed by [method@Json.Builder.add_value]. + * + * Once you added all members to the object, you must call [method@Json.Builder.end_object] + * to close the object. + * + * If the builder is in an inconsistent state, this function will return `NULL`. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_begin_object (JsonBuilder *builder) +{ + JsonObject *object; + JsonBuilderState *state; + JsonBuilderState *cur_state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (builder->priv->root == NULL, NULL); + g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL); + + object = json_object_new (); + cur_state = g_queue_peek_head (builder->priv->stack); + if (cur_state) + { + switch (cur_state->mode) + { + case JSON_BUILDER_MODE_ARRAY: + json_array_add_object_element (cur_state->data.array, json_object_ref (object)); + break; + + case JSON_BUILDER_MODE_MEMBER: + json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object)); + g_free (cur_state->member_name); + cur_state->member_name = NULL; + cur_state->mode = JSON_BUILDER_MODE_OBJECT; + break; + + default: + g_assert_not_reached (); + } + } + + state = g_slice_new (JsonBuilderState); + state->data.object = object; + state->member_name = NULL; + state->mode = JSON_BUILDER_MODE_OBJECT; + g_queue_push_head (builder->priv->stack, state); + + return builder; +} + +/** + * json_builder_end_object: + * @builder: a builder + * + * Closes the object inside the given builder that was opened by the most + * recent call to [method@Json.Builder.begin_object]. + * + * This function cannot be called after [method@Json.Builder.set_member_name]. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_end_object (JsonBuilder *builder) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL); + + state = g_queue_pop_head (builder->priv->stack); + + if (builder->priv->immutable) + json_object_seal (state->data.object); + + if (g_queue_is_empty (builder->priv->stack)) + { + builder->priv->root = json_node_new (JSON_NODE_OBJECT); + json_node_take_object (builder->priv->root, json_object_ref (state->data.object)); + + if (builder->priv->immutable) + json_node_seal (builder->priv->root); + } + + json_builder_state_free (state); + + return builder; +} + +/** + * json_builder_begin_array: + * @builder: a builder + * + * Opens an array inside the given builder. + * + * You can add a new element to the array by using [method@Json.Builder.add_value]. + * + * Once you added all elements to the array, you must call + * [method@Json.Builder.end_array] to close the array. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_begin_array (JsonBuilder *builder) +{ + JsonArray *array; + JsonBuilderState *state; + JsonBuilderState *cur_state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (builder->priv->root == NULL, NULL); + g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL); + + array = json_array_new (); + cur_state = g_queue_peek_head (builder->priv->stack); + if (cur_state) + { + switch (cur_state->mode) + { + case JSON_BUILDER_MODE_ARRAY: + json_array_add_array_element (cur_state->data.array, json_array_ref (array)); + break; + + case JSON_BUILDER_MODE_MEMBER: + json_object_set_array_member (cur_state->data.object, cur_state->member_name, json_array_ref (array)); + g_free (cur_state->member_name); + cur_state->member_name = NULL; + cur_state->mode = JSON_BUILDER_MODE_OBJECT; + break; + + default: + g_assert_not_reached (); + } + } + + state = g_slice_new (JsonBuilderState); + state->data.array = array; + state->mode = JSON_BUILDER_MODE_ARRAY; + g_queue_push_head (builder->priv->stack, state); + + return builder; +} + +/** + * json_builder_end_array: + * @builder: a builder + * + * Closes the array inside the given builder that was opened by the most + * recent call to [method@Json.Builder.begin_array]. + * + * This function cannot be called after [method@Json.Builder.set_member_name]. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_end_array (JsonBuilder *builder) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_ARRAY, NULL); + + state = g_queue_pop_head (builder->priv->stack); + + if (builder->priv->immutable) + json_array_seal (state->data.array); + + if (g_queue_is_empty (builder->priv->stack)) + { + builder->priv->root = json_node_new (JSON_NODE_ARRAY); + json_node_take_array (builder->priv->root, json_array_ref (state->data.array)); + + if (builder->priv->immutable) + json_node_seal (builder->priv->root); + } + + json_builder_state_free (state); + + return builder; +} + +/** + * json_builder_set_member_name: + * @builder: a builder + * @member_name: the name of the member + * + * Sets the name of the member in an object. + * + * This function must be followed by of these functions: + * + * - [method@Json.Builder.add_value], to add a scalar value to the member + * - [method@Json.Builder.begin_object], to add an object to the member + * - [method@Json.Builder.begin_array], to add an array to the member + * + * This function can only be called within an open object. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_set_member_name (JsonBuilder *builder, + const gchar *member_name) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (member_name != NULL, NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL); + + state = g_queue_peek_head (builder->priv->stack); + state->member_name = g_strdup (member_name); + state->mode = JSON_BUILDER_MODE_MEMBER; + + return builder; +} + +/** + * json_builder_add_value: + * @builder: a builder + * @node: (transfer full): the value of the member or element + * + * Adds a value to the currently open object member or array. + * + * If called after [method@Json.Builder.set_member_name], sets the given node + * as the value of the current member in the open object; otherwise, the node + * is appended to the elements of the open array. + * + * The builder will take ownership of the node. + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_add_value (JsonBuilder *builder, + JsonNode *node) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (node != NULL, NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL); + + state = g_queue_peek_head (builder->priv->stack); + + if (builder->priv->immutable) + json_node_seal (node); + + switch (state->mode) + { + case JSON_BUILDER_MODE_MEMBER: + json_object_set_member (state->data.object, state->member_name, node); + g_free (state->member_name); + state->member_name = NULL; + state->mode = JSON_BUILDER_MODE_OBJECT; + break; + + case JSON_BUILDER_MODE_ARRAY: + json_array_add_element (state->data.array, node); + break; + + default: + g_assert_not_reached (); + } + + return builder; +} + +/** + * json_builder_add_int_value: + * @builder: a builder + * @value: the value of the member or element + * + * Adds an integer value to the currently open object member or array. + * + * If called after [method@Json.Builder.set_member_name], sets the given value + * as the value of the current member in the open object; otherwise, the value + * is appended to the elements of the open array. + * + * See also: [method@Json.Builder.add_value] + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_add_int_value (JsonBuilder *builder, + gint64 value) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL); + + state = g_queue_peek_head (builder->priv->stack); + switch (state->mode) + { + case JSON_BUILDER_MODE_MEMBER: + json_object_set_int_member (state->data.object, state->member_name, value); + g_free (state->member_name); + state->member_name = NULL; + state->mode = JSON_BUILDER_MODE_OBJECT; + break; + + case JSON_BUILDER_MODE_ARRAY: + json_array_add_int_element (state->data.array, value); + break; + + default: + g_assert_not_reached (); + } + + return builder; +} + +/** + * json_builder_add_double_value: + * @builder: a builder + * @value: the value of the member or element + * + * Adds a floating point value to the currently open object member or array. + * + * If called after [method@Json.Builder.set_member_name], sets the given value + * as the value of the current member in the open object; otherwise, the value + * is appended to the elements of the open array. + * + * See also: [method@Json.Builder.add_value] + * + * Return value: (nullable) (transfer none): the builder instance + */ +JsonBuilder * +json_builder_add_double_value (JsonBuilder *builder, + gdouble value) +{ + JsonBuilderState *state; + + g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); + g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); + g_return_val_if_fail (json_builder_is_valid_add_mode (builder), NULL); + + sta@@ Diff output truncated at 100000 characters. @@
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org