diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..368a9f1a5 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,9 @@ +{ + "name": "CodeCompass-devcontainer", + "image": "modelcpp/codecompass:dev", + "workspaceFolder": "/CodeCompass/CodeCompass", + "workspaceMount": "src=${localWorkspaceFolder}/..,dst=/CodeCompass,type=bind,consistency=cached", + "appPort": [ + "8001:8080" + ] +} \ No newline at end of file diff --git a/.github/scripts/ubuntu-20.04/compile_build.sh b/.github/scripts/ubuntu-20.04/compile_build.sh index 773ba40e7..578b890b8 100644 --- a/.github/scripts/ubuntu-20.04/compile_build.sh +++ b/.github/scripts/ubuntu-20.04/compile_build.sh @@ -1,3 +1,5 @@ +#!/bin/bash + # Compile dependencies that cannot be acquired via the official repositories mkdir -p ${INSTALL_PATH} diff --git a/.github/scripts/ubuntu-20.04/download_build.sh b/.github/scripts/ubuntu-20.04/download_build.sh index 460817164..b528c1f4a 100644 --- a/.github/scripts/ubuntu-20.04/download_build.sh +++ b/.github/scripts/ubuntu-20.04/download_build.sh @@ -1,3 +1,5 @@ +#!/bin/bash + # Download installers for compiled dependencies mkdir -p ${DOWNLOAD_PATH} @@ -20,4 +22,9 @@ hash_value=$(echo -n "$concatenated_hashes" | md5sum | awk '{print $1}') ## Save said hash -echo "compile-hash-key=${hash_value}" >> $GITHUB_OUTPUT \ No newline at end of file + +### Restore action +echo "ubuntu-20-04-compile-hash-key=${hash_value}" >> "$GITHUB_OUTPUT" + +### Save action +echo "CACHE_KEY=${hash_value}" >> "$GITHUB_ENV" \ No newline at end of file diff --git a/.github/scripts/ubuntu-20.04/postcompile_build.sh b/.github/scripts/ubuntu-20.04/postcompile_build.sh index 77c91dccc..8b071bdf8 100644 --- a/.github/scripts/ubuntu-20.04/postcompile_build.sh +++ b/.github/scripts/ubuntu-20.04/postcompile_build.sh @@ -1,4 +1,8 @@ # Post compilation configuration for building (environmental variables, library location settings etc..) echo "${INSTALL_PATH}/thrift/bin" >> $GITHUB_PATH -echo "CMAKE_PREFIX_PATH=${INSTALL_PATH}/thrift:$CMAKE_PREFIX_PATH" >> $GITHUB_ENV \ No newline at end of file +echo "CMAKE_PREFIX_PATH=${INSTALL_PATH}/thrift:$CMAKE_PREFIX_PATH" >> $GITHUB_ENV + +# Clean up dependency sources and intermediate binaries to save space +rm -f ${DOWNLOAD_PATH}/thrift-0.16.0.tar.gz +rm -rf ${DOWNLOAD_PATH}/thrift-0.16.0/ \ No newline at end of file diff --git a/.github/scripts/ubuntu-20.04/setup_runtime.sh b/.github/scripts/ubuntu-20.04/setup_runtime.sh deleted file mode 100755 index ac9934c23..000000000 --- a/.github/scripts/ubuntu-20.04/setup_runtime.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Install required packages for CodeCompass runtime -sudo apt-get install -y git cmake make g++ graphviz \ - libboost-filesystem1.71.0 libboost-log1.71.0 libboost-program-options1.71.0 \ - libllvm11 clang-11 libclang1-11 default-jre libssl1.1 libmagic1 \ - libgit2-28 ctags googletest libldap-2.4-2 diff --git a/.github/scripts/ubuntu-22.04/compile_build.sh b/.github/scripts/ubuntu-22.04/compile_build.sh new file mode 100755 index 000000000..44a16b63e --- /dev/null +++ b/.github/scripts/ubuntu-22.04/compile_build.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Compile dependencies that cannot be acquired via the official repositories + +mkdir -p ${INSTALL_PATH} + +## Compile build2 + +sh "${DOWNLOAD_PATH}/install_latest_build2.sh" ${INSTALL_PATH}/build2 + +## Compile odb, libodb, and its connectors + +mkdir -p ${DOWNLOAD_PATH}/odb +cd ${DOWNLOAD_PATH}/odb +${INSTALL_PATH}/build2/bin/bpkg create --quiet --jobs $(nproc) cc \ + config.cxx=g++ \ + config.cc.coptions=-O3 \ + config.bin.rpath=${INSTALL_PATH}/odb/lib \ + config.install.root=${INSTALL_PATH}/odb + +### Getting the source +${INSTALL_PATH}/build2/bin/bpkg add https://pkg.cppget.org/1/beta --trust-yes +${INSTALL_PATH}/build2/bin/bpkg fetch --trust-yes + +### Building odb +${INSTALL_PATH}/build2/bin/bpkg build odb --yes +${INSTALL_PATH}/build2/bin/bpkg build libodb --yes +${INSTALL_PATH}/build2/bin/bpkg build libodb-sqlite --yes +${INSTALL_PATH}/build2/bin/bpkg build libodb-pgsql --yes +${INSTALL_PATH}/build2/bin/bpkg install --all --recursive \ No newline at end of file diff --git a/.github/scripts/ubuntu-22.04/download_build.sh b/.github/scripts/ubuntu-22.04/download_build.sh new file mode 100755 index 000000000..59aea7e80 --- /dev/null +++ b/.github/scripts/ubuntu-22.04/download_build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Download installers for compiled dependencies + +mkdir -p "${DOWNLOAD_PATH}" + +## Thrift 0.16 + ODB beta + +wget -O "${DOWNLOAD_PATH}/install_latest_build2.sh" "https://github.com/Ericsson/CodeCompass/raw/master/scripts/install_latest_build2.sh" +build2_version=$(sh "${DOWNLOAD_PATH}/install_latest_build2.sh" --version) +odb_signature=$(wget -qO- https://pkg.cppget.org/1/beta/signature.manifest) + +# Calculate hash of dependencies for Github Cache Action + +hash_value=$(echo -n "${build2_version}${odb_signature}" | md5sum | awk '{print $1}') + +## Save said hash + +### Restore action +echo "ubuntu-22-04-compile-hash-key=${hash_value}" >> "$GITHUB_OUTPUT" + +### Save action +echo "CACHE_KEY=${hash_value}" >> "$GITHUB_ENV" \ No newline at end of file diff --git a/.github/scripts/ubuntu-22.04/postcompile_build.sh b/.github/scripts/ubuntu-22.04/postcompile_build.sh new file mode 100755 index 000000000..c33212c69 --- /dev/null +++ b/.github/scripts/ubuntu-22.04/postcompile_build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Post compilation configuration for building (environmental variables, library location settings etc..) + +echo "${INSTALL_PATH}/odb/bin" >> $GITHUB_PATH +echo "CMAKE_PREFIX_PATH=${INSTALL_PATH}/odb:$CMAKE_PREFIX_PATH" >> $GITHUB_ENV + +# Clean up dependency sources and intermediate binaries to save space +rm -rf ${DOWNLOAD_PATH}/odb \ No newline at end of file diff --git a/.github/scripts/ubuntu-22.04/setup_build.sh b/.github/scripts/ubuntu-22.04/setup_build.sh new file mode 100755 index 000000000..1197d33c1 --- /dev/null +++ b/.github/scripts/ubuntu-22.04/setup_build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Install required packages for CodeCompass build +sudo apt install git cmake make g++ libboost-all-dev \ + llvm-11-dev clang-11 libclang-11-dev \ + gcc-11-plugin-dev thrift-compiler libthrift-dev \ + default-jdk libssl-dev libgraphviz-dev libmagic-dev libgit2-dev exuberant-ctags doxygen \ + libldap2-dev libgtest-dev \ No newline at end of file diff --git a/.github/scripts/ubuntu-22.04/setup_postgresql.sh b/.github/scripts/ubuntu-22.04/setup_postgresql.sh new file mode 100755 index 000000000..b1806d2ae --- /dev/null +++ b/.github/scripts/ubuntu-22.04/setup_postgresql.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Install PostgreSQL +sudo apt-get install postgresql-server-dev-14 \ No newline at end of file diff --git a/.github/scripts/ubuntu-22.04/setup_sqlite3.sh b/.github/scripts/ubuntu-22.04/setup_sqlite3.sh new file mode 100755 index 000000000..4170c6062 --- /dev/null +++ b/.github/scripts/ubuntu-22.04/setup_sqlite3.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Install SQLite3 +sudo apt-get install libsqlite3-dev \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60593c08e..7989a3090 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,21 +12,18 @@ env: permissions: read-all jobs: - - - ## BUILD JOBS build: strategy: matrix: db: [postgresql, sqlite3] - os: [ubuntu-20.04] + os: [ubuntu-20.04, ubuntu-22.04] fail-fast: false runs-on: ${{ matrix.os }} outputs: - has-compiled-dependencies: ${{ steps.compilation-flag.outputs.has-compiled-dependencies }} - compile-hash-key: ${{ steps.download-compile-dependencies.outputs.compile-hash-key }} + ubuntu-20-04-compile-hash-key: ${{ steps.download-compile-dependencies.outputs.compile-hash-key }} + ubuntu-22-04-compile-hash-key: ${{ steps.download-compile-dependencies.outputs.compile-hash-key }} services: # Label used to access the service container @@ -58,34 +55,33 @@ jobs: id: compilation-flag run: | if [ -f ./.github/scripts/${{ matrix.os }}/compile_build.sh ]; then - echo "has-compiled-dependencies=true" >> "$GITHUB_OUTPUT" + echo "HAS_COMPILED_DEPENDENCIES=true" >> "$GITHUB_ENV" else - echo "has-compiled-dependencies=false" >> "$GITHUB_OUTPUT" + echo "HAS_COMPILED_DEPENDENCIES=false" >> "$GITHUB_ENV" fi - name: Download installers for compiled dependencies - if: steps.compilation-flag.outputs.has-compiled-dependencies == 'true' + if: ${{ env.HAS_COMPILED_DEPENDENCIES == 'true' }} id: download-compile-dependencies run: | chmod +x ./.github/scripts/${{ matrix.os }}/download_build.sh ./.github/scripts/${{ matrix.os }}/download_build.sh - name: Restore compiled dependencies - if: steps.compilation-flag.outputs.has-compiled-dependencies == 'true' id: restore-compiled-dependencies uses: actions/cache/restore@v3 with: path: ${{ env.INSTALL_PATH }} - key: ${{ matrix.os }}-compile-install-${{steps.download-compile-dependencies.outputs.compile-hash-key}} + key: ${{ matrix.os }}-compile-install-${{ env.CACHE_KEY }} - name: Compile dependencies - if: steps.restore-compiled-dependencies.outputs.cache-hit != 'true' && steps.compilation-flag.outputs.has-compiled-dependencies == 'true' + if: ${{ env.HAS_COMPILED_DEPENDENCIES == 'true' && steps.restore-compiled-dependencies.outputs.cache-hit != 'true' }} run: | chmod +x ./.github/scripts/${{ matrix.os }}/compile_build.sh ./.github/scripts/${{ matrix.os }}/compile_build.sh - name: Post compilation configuration (build) - if: steps.compilation-flag.outputs.has-compiled-dependencies == 'true' + if: ${{ env.HAS_COMPILED_DEPENDENCIES == 'true' }} run: | if [ -f ./.github/scripts/${{ matrix.os }}/postcompile_build.sh ]; then chmod +x ./.github/scripts/${{ matrix.os }}/postcompile_build.sh @@ -93,12 +89,12 @@ jobs: fi - name: Save dependencies - if: steps.restore-compiled-dependencies.outputs.cache-hit != 'true' && steps.compilation-flag.outputs.has-compiled-dependencies == 'true' + if: ${{ env.HAS_COMPILED_DEPENDENCIES == 'true' && steps.restore-compiled-dependencies.outputs.cache-hit != 'true' }} id: save-compiled-dependencies uses: actions/cache/save@v3 with: path: ${{ env.INSTALL_PATH }} - key: ${{ matrix.os }}-compile-install-${{steps.download-compile-dependencies.outputs.compile-hash-key}} + key: ${{ matrix.os }}-compile-install-${{ env.CACHE_KEY }} - name: Install database packages run: ./.github/scripts/${{ matrix.os }}/setup_${{matrix.db}}.sh @@ -186,7 +182,7 @@ jobs: strategy: matrix: db: [postgresql, sqlite3] - os: [ubuntu-20.04] + os: [ubuntu-20.04, ubuntu-22.04] fail-fast: false runs-on: ${{ matrix.os }} @@ -199,12 +195,13 @@ jobs: env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - # Set health checks to wait until postgres has started + # Set health checks to wait until postgres has started & increase SHM size options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + --shm-size=2gb ports: # Maps tcp port 5432 on service container to the host - 5432:5432 @@ -222,21 +219,26 @@ jobs: - name: Install database packages run: ./.github/scripts/${{ matrix.os }}/setup_${{matrix.db}}.sh + - name: Set has-compiled-dependencies flag + id: compilation-flag + run: | + if [ -f ./.github/scripts/${{ matrix.os }}/compile_build.sh ]; then + echo "HAS_COMPILED_DEPENDENCIES=true" >> "$GITHUB_ENV" + else + echo "HAS_COMPILED_DEPENDENCIES=false" >> "$GITHUB_ENV" + fi + - name: Restore compiled dependencies - if: needs.build.outputs.has-compiled-dependencies == 'true' + if: ${{ env.HAS_COMPILED_DEPENDENCIES == 'true' }} id: restore-compiled-dependencies uses: actions/cache/restore@v3 with: path: ${{ env.INSTALL_PATH }} - key: ${{ matrix.os }}-compile-install-${{needs.build.outputs.compile-hash-key}} - - - name: Post compilation configuration (runtime) - if: needs.build.outputs.has-compiled-dependencies == 'true' - run: | - if [ -f ./.github/scripts/${{ matrix.os }}/postcompile_runtime.sh ]; then - chmod +x ./.github/scripts/${{ matrix.os }}/postcompile_runtime.sh - ./.github/scripts/${{ matrix.os }}/postcompile_runtime.sh - fi + fail-on-cache-miss: true + key: ${{ matrix.os }}-compile-install-${{ needs.build.outputs.ubuntu-20-04-compile-hash-key }} + restore-keys: | + ${{ matrix.os }}-compile-install-${{ needs.build.outputs.ubuntu-20-04-compile-hash-key }} + ${{ matrix.os }}-compile-install-${{ needs.build.outputs.ubuntu-22-04-compile-hash-key }} - name: Download CodeCompass binaries uses: actions/download-artifact@v2 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ff5c1d5f0..4f0b060ec 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -19,7 +19,7 @@ permissions: read-all jobs: docker: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout diff --git a/.gitlab/build-deps.sh b/.gitlab/build-deps.sh index a5000ac82..1701860d4 100644 --- a/.gitlab/build-deps.sh +++ b/.gitlab/build-deps.sh @@ -10,7 +10,7 @@ mkdir -p $PACKAGES_DIR if [ ! -f $DEPS_INSTALL_BUILD_DIR/gcc-install/bin/g++ ]; then cd $PACKAGES_DIR - wget --no-verbose --no-clobber http://robotlab.itk.ppke.hu/gcc/releases/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.xz + wget --no-verbose --no-clobber https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.xz tar -xf gcc-$GCC_VERSION.tar.xz cd gcc-$GCC_VERSION ./contrib/download_prerequisites diff --git a/doc/lsp.md b/doc/lsp.md new file mode 100644 index 000000000..d4e4ebc37 --- /dev/null +++ b/doc/lsp.md @@ -0,0 +1,227 @@ +# Supported LSP Requests + +## Standard + +- [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_declaration) +- [textDocument/definition](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition) +- [textDocument/implementation](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation) +- [textDocument/references](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references) + +## CodeCompass Specific Methods + +### textDocument/thisCalls + +Returns the locations of function calls inside the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/callsOfThis + +Returns the locations where the function at the selected position is called. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/callee + +Returns the locations of the definitions of the functions called by the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/caller + +Returns the locations of the definitions of the functions that call the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/virtualCall + +Returns the locations where the function at the selected position may be virtually called. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/functionPointerCall + +Returns the locations where the function at the selected position is called through a function pointer. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/parameters + +Returns the locations of the parameters of the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/localVariables + +Returns the locations of the local variables of the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/overridden + +Returns the locations of the functions the function at the selected position overrides. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/overriders + +Returns the locations of the functions that override the function at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/read + +Returns the locations the variable at the selected position is read. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/write + +Returns the locations where the variable at the selected position is written. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/signature + +Returns the name of the AST node of the entity at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* string | null + +### textDocument/alias + +Returns the locations of the type aliases of the type at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/implements + +Returns the locations of the types that inherit from the type at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/dataMember + +Returns the locations of the data members of the class at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/methods + +Returns the locations of the methods of the class at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/friends + +Returns the locations of the friends of the class at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/underlyingType + +Returns the location of the underlying type of the type alias at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/enumConstants + +Returns the locations of the constants of the enumeration at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/expansion + +Returns the locations of the expansions of the macro at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/undefinition + +Returns the locations of the undefinitions of the macro at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location) | [Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#location)[] | null + +### textDocument/diagramTypes + +Returns the names of diagram types available at the selected position. + +*Params:* [TextDocumentPositionParams](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentPositionParams) + +*Response:* string[] | null + +### textDocument/diagram + +Returns a diagram of the selected type based on the selected position in SVG format. + +*Params:* diagramParams + +*Response:* string | null + +### directory/diagram + +Returns a diagram of the selected type based on the selected module in SVG format. + +*Params:* diagramParams + +*Response:* string | null + +## CodeCompass Specific Types + +### DiagramParams + +Parameters needed for diagram requests. +Directory based diagrams do not need the position parameter. +The diagramType should contain a valid diagram type name for the given language plugin. +The `textDocument/diagramTypes` method can be used to access these for position dependant diagrams. + +```javascript +interface DiagramParams { + textDocument: TextDocumentIdentifier; + position?: Position; + diagramType: string; +} +``` diff --git a/doc/usage.md b/doc/usage.md index 65f6d5eb1..a73558f03 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -292,4 +292,17 @@ The server will be available in a browser on In both the parser and the webserver it is possible to write the logs to a given directory. This feature can be enabled by passing the `--logtarget` command line option with the full path to the directory to be used for storing the log files. -If this argument is not specified, the logs will be written to the terminal only. \ No newline at end of file +If this argument is not specified, the logs will be written to the terminal only. + +### Language Server Protocol support + +The CodeCompass_webserver is not a fully fledged LSP server on its own, +but it does support some standard and non-standard LSP requests for C and C++ projects. +The full list can be found here: [Supported LSP Requests](lsp.md) + +To access this feature, requests must be sent to the following address: +`http://://CppLspService` + +e.g.: [`http://localhost:6251/MyProject/CppLspService`](http://localhost:6251/MyProject/CppLspService) + +The project name should match the name of the project used by the CodeCompass_parser. diff --git a/docker/dev/install_odb.sh b/docker/dev/install_odb.sh index 1ebe893fd..10662c1f5 100644 --- a/docker/dev/install_odb.sh +++ b/docker/dev/install_odb.sh @@ -33,11 +33,8 @@ for pack in "$BUILD_LIST"; do bpkg build $pack --yes done # Install ODB (to /usr/local) -INSTALL_LIST="$BUILD_LIST libstudxml libcutl" -for pack in "$INSTALL_LIST"; do - bpkg install $pack -done +bpkg install --all --recursive # Clean up cd / sh install_latest_build2.sh --uninstall -rm -rf /odb_build install_latest_build2.sh build2-toolchain-*.tar.gz \ No newline at end of file +rm -rf /odb_build install_latest_build2.sh build2-toolchain-*.tar.gz diff --git a/plugins/cpp/model/include/model/cppfunction.h b/plugins/cpp/model/include/model/cppfunction.h index 00109db98..2492d9f07 100644 --- a/plugins/cpp/model/include/model/cppfunction.h +++ b/plugins/cpp/model/include/model/cppfunction.h @@ -41,15 +41,21 @@ struct CppFunctionParamCount }; #pragma db view \ - object(CppFunction) object(CppVariable = Parameters : CppFunction::parameters) \ - query((?) + "GROUP BY" + cc::model::CppEntity::astNodeId) + object(CppFunction) \ + object(CppVariable = Parameters : CppFunction::parameters) \ + object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) \ + query((?) + "GROUP BY" + cc::model::CppEntity::astNodeId + "," + cc::model::File::path) struct CppFunctionParamCountWithId { - #pragma db column("CppEntity.astNodeId") + #pragma db column(CppEntity::astNodeId) CppAstNodeId id; #pragma db column("count(" + Parameters::id + ")") std::size_t count; + + #pragma db column(File::path) + std::string filePath; }; #pragma db view \ @@ -60,11 +66,20 @@ struct CppFunctionLocalCount std::size_t count; }; -#pragma db view object(CppFunction) -struct CppFunctionMcCabeWithId +#pragma db view \ + object(CppFunction) \ + object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) +struct CppFunctionMcCabe { + #pragma db column(CppEntity::astNodeId) CppAstNodeId astNodeId; + + #pragma db column(CppFunction::mccabe) unsigned int mccabe; + + #pragma db column(File::path) + std::string filePath; }; } diff --git a/plugins/cpp/parser/src/clangastvisitor.h b/plugins/cpp/parser/src/clangastvisitor.h index 47bd608f0..e07e8928e 100644 --- a/plugins/cpp/parser/src/clangastvisitor.h +++ b/plugins/cpp/parser/src/clangastvisitor.h @@ -130,17 +130,23 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor bool shouldVisitImplicitCode() const { return true; } bool shouldVisitTemplateInstantiations() const { return true; } - + bool shouldVisitLambdaBody() const { return true; } + bool TraverseDecl(clang::Decl* decl_) { - bool prevIsImplicit = _isImplicit; - - if (decl_) - _isImplicit = decl_->isImplicit() || _isImplicit; + // We use implicitness to determine if actual symbol location information + // should be stored for AST nodes in our database. This differs somewhat + // from Clang's concept of implicitness. + // To bridge the gap between the two interpretations, we mostly assume + // implicitness to be hereditary from parent to child nodes, except + // in some known special cases (see lambdas in TraverseCXXRecordDecl). + bool wasImplicit = _isImplicit; + if (decl_ != nullptr) + _isImplicit |= decl_->isImplicit(); bool b = Base::TraverseDecl(decl_); - _isImplicit = prevIsImplicit; + _isImplicit = wasImplicit; return b; } @@ -370,6 +376,13 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor bool TraverseCXXRecordDecl(clang::CXXRecordDecl* rd_) { + // Although lambda closure types are implicit by nature as far as + // Clang is concerned, their operator() is not. In order to be able to + // properly assign symbol location information to AST nodes within + // lambda bodies, we must force lambdas to be considered explicit. + bool wasImplicit = _isImplicit; + if (rd_ != nullptr) + _isImplicit &= !rd_->isLambda(); _typeStack.push(std::make_shared()); bool b = Base::TraverseCXXRecordDecl(rd_); @@ -377,6 +390,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor if (_typeStack.top()->astNodeId) _types.push_back(_typeStack.top()); _typeStack.pop(); + _isImplicit = wasImplicit; return b; } @@ -620,7 +634,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor // some implementation defined reasons. The position of this node is at the // name of the record after the "class", "struct", etc. keywords. We don't // want to store these in the database - if (rd_->isImplicit()) + if (rd_->isImplicit() && !rd_->isLambda()) return true; //--- CppAstNode ---// @@ -920,10 +934,12 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor cppFunction->qualifiedType = qualType.getAsString(); cppFunction->mccabe = 1; - clang::CXXMethodDecl* md = llvm::dyn_cast(fn_); - //--- Tags ---// + if (_isImplicit) + cppFunction->tags.insert(model::Tag::Implicit); + + clang::CXXMethodDecl* md = llvm::dyn_cast(fn_); if (md) { if (md->isVirtual()) @@ -939,9 +955,6 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor cppFunction->tags.insert(model::Tag::Destructor); } - if (_isImplicit) - cppFunction->tags.insert(model::Tag::Implicit); - //--- AST type for the return type ---// unsigned rawEncoding @@ -1620,34 +1633,27 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor model::FileLoc fileLoc; if (start_.isInvalid() || end_.isInvalid()) - { fileLoc.file = getFile(start_); - const std::string& type = fileLoc.file.load()->type; - if (type != model::File::DIRECTORY_TYPE && type != _cppSourceType) - { - fileLoc.file->type = _cppSourceType; - _ctx.srcMgr.updateFile(*fileLoc.file); - } - return fileLoc; - } - - clang::SourceLocation realStart = start_; - clang::SourceLocation realEnd = end_; + else + { + clang::SourceLocation realStart = start_; + clang::SourceLocation realEnd = end_; - if (_clangSrcMgr.isMacroBodyExpansion(start_)) - realStart = _clangSrcMgr.getExpansionLoc(start_); - if (_clangSrcMgr.isMacroArgExpansion(start_)) - realStart = _clangSrcMgr.getSpellingLoc(start_); + if (_clangSrcMgr.isMacroBodyExpansion(start_)) + realStart = _clangSrcMgr.getExpansionLoc(start_); + if (_clangSrcMgr.isMacroArgExpansion(start_)) + realStart = _clangSrcMgr.getSpellingLoc(start_); - if (_clangSrcMgr.isMacroBodyExpansion(end_)) - realEnd = _clangSrcMgr.getExpansionLoc(end_); - if (_clangSrcMgr.isMacroArgExpansion(end_)) - realEnd = _clangSrcMgr.getSpellingLoc(end_); + if (_clangSrcMgr.isMacroBodyExpansion(end_)) + realEnd = _clangSrcMgr.getExpansionLoc(end_); + if (_clangSrcMgr.isMacroArgExpansion(end_)) + realEnd = _clangSrcMgr.getSpellingLoc(end_); - if (!_isImplicit) - _fileLocUtil.setRange(realStart, realEnd, fileLoc.range); + if (!_isImplicit) + _fileLocUtil.setRange(realStart, realEnd, fileLoc.range); - fileLoc.file = getFile(realStart); + fileLoc.file = getFile(realStart); + } const std::string& type = fileLoc.file.load()->type; if (type != model::File::DIRECTORY_TYPE && type != _cppSourceType) diff --git a/plugins/cpp/service/include/service/cppservice.h b/plugins/cpp/service/include/service/cppservice.h index 853972881..49944c974 100644 --- a/plugins/cpp/service/include/service/cppservice.h +++ b/plugins/cpp/service/include/service/cppservice.h @@ -19,6 +19,7 @@ #include #include +#include #include namespace cc @@ -69,6 +70,10 @@ class CppServiceHandler : virtual public LanguageServiceIf const core::AstNodeId& astNodeId_, const std::int32_t diagramId_) override; + util::Graph returnDiagram( + const core::AstNodeId& astNodeId_, + const std::int32_t diagramId_); + void getDiagramLegend( std::string& return_, const std::int32_t diagramId_) override; @@ -82,6 +87,10 @@ class CppServiceHandler : virtual public LanguageServiceIf const core::FileId& fileId_, const int32_t diagramId_) override; + util::Graph returnFileDiagram( + const core::FileId& fileId_, + const int32_t diagramId_); + void getFileDiagramLegend( std::string& return_, const std::int32_t diagramId_) override; @@ -131,7 +140,6 @@ class CppServiceHandler : virtual public LanguageServiceIf std::vector& return_, const core::FileRange& range_) override; -private: enum ReferenceType { DEFINITION, /*!< By this option the definition(s) of the AST node can be @@ -258,6 +266,7 @@ class CppServiceHandler : virtual public LanguageServiceIf of a module. */ }; +private: static bool compareByPosition( const model::CppAstNode& lhs, const model::CppAstNode& rhs); diff --git a/plugins/cpp/service/src/cppservice.cpp b/plugins/cpp/service/src/cppservice.cpp index 4b8e8586d..516043a74 100644 --- a/plugins/cpp/service/src/cppservice.cpp +++ b/plugins/cpp/service/src/cppservice.cpp @@ -280,7 +280,7 @@ void CppServiceHandler::getProperties( { VarResult variables = _db->query( VarQuery::entityHash == node.entityHash); - + if (!variables.empty()) { model::CppVariable variable = *variables.begin(); @@ -289,7 +289,7 @@ void CppServiceHandler::getProperties( return_["Type"] = variable.qualifiedType; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying properties " "of C++ variable: " << toShortDiagnosticString(node); @@ -312,7 +312,7 @@ void CppServiceHandler::getProperties( return_["Signature"] = function.name; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying properties " "of C++ function: " << toShortDiagnosticString(node); @@ -338,7 +338,7 @@ void CppServiceHandler::getProperties( return_["Qualified name"] = type.qualifiedName; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying properties " "of C++ type: " << toShortDiagnosticString(node); @@ -359,11 +359,11 @@ void CppServiceHandler::getProperties( return_["Qualified name"] = type.qualifiedName; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying properties " "of C++ typedef: " << toShortDiagnosticString(node); - + break; } @@ -381,7 +381,7 @@ void CppServiceHandler::getProperties( return_["Value"] = std::to_string(enumConst.value); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying properties " "of C++ enum constant: " << toShortDiagnosticString(node); @@ -502,7 +502,7 @@ std::int32_t CppServiceHandler::getReferenceCount( TypeQuery::entityHash == function.typeHash).count; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when counting return types " "of C++ function: " << toShortDiagnosticString(node); @@ -538,7 +538,7 @@ std::int32_t CppServiceHandler::getReferenceCount( TypeQuery::entityHash == variable.typeHash).count; } else - LOG(warning) + LOG(warning) << "Unexpected empty result when counting types " "of C++ variable: " << toShortDiagnosticString(node); @@ -788,7 +788,7 @@ void CppServiceHandler::getReferences( std::to_string(var.load()->astNodeId))); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying parameters " "of C++ function: " << toShortDiagnosticString(node); @@ -811,7 +811,7 @@ void CppServiceHandler::getReferences( std::to_string(var.load()->astNodeId))); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying local variables " "of C++ function: " << toShortDiagnosticString(node); @@ -840,7 +840,7 @@ void CppServiceHandler::getReferences( } } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying return type " "of C++ function: " << toShortDiagnosticString(node); @@ -904,7 +904,7 @@ void CppServiceHandler::getReferences( } } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying type " "of C++ variable: " << toShortDiagnosticString(node); @@ -1005,7 +1005,7 @@ void CppServiceHandler::getReferences( nodes = std::vector(result.begin(), result.end()); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying underlying type " "of C++ typedef: " << toShortDiagnosticString(node); @@ -1033,7 +1033,7 @@ void CppServiceHandler::getReferences( }); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying enum constants " "of C++ enum: " << toShortDiagnosticString(node); @@ -1253,7 +1253,9 @@ void CppServiceHandler::getSyntaxHighlight( // Regular expression to find element position const std::regex specialChars { R"([-[\]{}()*+?.,\^$|#\s])" }; - std::string sanitizedAstValue = std::regex_replace(node.astValue, specialChars, R"(\$&)"); + std::string sanitizedAstValue = std::regex_replace(node.astValue, + specialChars, + R"(\$&)"); std::string reg = "\\b" + sanitizedAstValue + "\\b"; for (std::size_t i = node.location.range.start.line - 1; @@ -1291,6 +1293,16 @@ void CppServiceHandler::getDiagram( std::string& return_, const core::AstNodeId& astNodeId_, const std::int32_t diagramId_) +{ + util::Graph graph = returnDiagram(astNodeId_, diagramId_); + + if (graph.nodeCount() != 0) + return_ = graph.output(util::Graph::SVG); +} + +util::Graph CppServiceHandler::returnDiagram( + const core::AstNodeId& astNodeId_, + const std::int32_t diagramId_) { Diagram diagram(_db, _datadir, _context); util::Graph graph; @@ -1310,8 +1322,7 @@ void CppServiceHandler::getDiagram( break; } - if (graph.nodeCount() != 0) - return_ = graph.output(util::Graph::SVG); + return graph; } void CppServiceHandler::getDiagramLegend( @@ -1366,6 +1377,16 @@ void CppServiceHandler::getFileDiagram( std::string& return_, const core::FileId& fileId_, const int32_t diagramId_) +{ + util::Graph graph = returnFileDiagram(fileId_, diagramId_); + + if (graph.nodeCount() != 0) + return_ = graph.output(util::Graph::SVG); +} + +util::Graph CppServiceHandler::returnFileDiagram( + const core::FileId& fileId_, + const int32_t diagramId_) { FileDiagram diagram(_db, _datadir, _context); util::Graph graph; @@ -1398,8 +1419,7 @@ void CppServiceHandler::getFileDiagram( break; } - if (graph.nodeCount() != 0) - return_ = graph.output(util::Graph::SVG); + return graph; } void CppServiceHandler::getFileDiagramLegend( @@ -1649,7 +1669,7 @@ CppServiceHandler::getTags(const std::vector& nodes_) tags[node.id].push_back(model::tagToString(tag)); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying tags " "of C++ function: " << toShortDiagnosticString(node); @@ -1684,7 +1704,7 @@ CppServiceHandler::getTags(const std::vector& nodes_) tags[node.id].push_back(model::tagToString(tag)); } else - LOG(warning) + LOG(warning) << "Unexpected empty result when querying tags " "of C++ variable: " << toShortDiagnosticString(node); diff --git a/plugins/cpp/service/src/filediagram.cpp b/plugins/cpp/service/src/filediagram.cpp index f3b0addae..44c3bf788 100644 --- a/plugins/cpp/service/src/filediagram.cpp +++ b/plugins/cpp/service/src/filediagram.cpp @@ -107,7 +107,7 @@ void FileDiagram::getIncludeDependencyDiagram( util::bfsBuild(graph_, currentNode,std::bind(&FileDiagram::getRevUsages, this, std::placeholders::_1, std::placeholders::_2), {}, revUsagesEdgeDecoration, 3); - + util::bfsBuild(graph_, currentNode, std::bind(&FileDiagram::getProvides, this, std::placeholders::_1, std::placeholders::_2), {}, usagesEdgeDecoration, 3); diff --git a/plugins/cpp/test/src/cpparsertest.cpp b/plugins/cpp/test/src/cpparsertest.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/plugins/cpp_lsp/CMakeLists.txt b/plugins/cpp_lsp/CMakeLists.txt new file mode 100644 index 000000000..def947f71 --- /dev/null +++ b/plugins/cpp_lsp/CMakeLists.txt @@ -0,0 +1,11 @@ +# The C++ lsp plugin depends on the C++ plugin's components to be built. + +if ("${cpp_PLUGIN_DIR}" STREQUAL "") + # Use SEND_ERROR here so a build file is not generated at the end. + # CodeCompass might use a lot of plugins and produce a lengthy build, so + # a warning at configure time would easily be missed by the users. + message(SEND_ERROR + "C++ LSP plugin found without C++ plugin in the plugins directory.") +endif() + +add_subdirectory(service) diff --git a/plugins/cpp_lsp/service/CMakeLists.txt b/plugins/cpp_lsp/service/CMakeLists.txt new file mode 100644 index 000000000..79e0d9c66 --- /dev/null +++ b/plugins/cpp_lsp/service/CMakeLists.txt @@ -0,0 +1,28 @@ +include_directories( + include + ${PROJECT_SOURCE_DIR}/model/include + ${PROJECT_BINARY_DIR}/service/language/gen-cpp + ${PROJECT_BINARY_DIR}/service/project/gen-cpp + ${PROJECT_SOURCE_DIR}/service/project/include + ${PROJECT_SOURCE_DIR}/plugins/cpp/service/include + ${PROJECT_SOURCE_DIR}/plugins/cpp/model/include + ${CMAKE_BINARY_DIR}/model/include + ${CMAKE_BINARY_DIR}/plugins/cpp/model/include + ${PROJECT_SOURCE_DIR}/util/include + ${PROJECT_SOURCE_DIR}/webserver/include + ${PROJECT_SOURCE_DIR}/service/lsp/include) + +include_directories(SYSTEM + ${THRIFT_LIBTHRIFT_INCLUDE_DIRS}) + +add_library(cpplspservice SHARED + src/cpplspservice.cpp + src/plugin.cpp) + +target_link_libraries(cpplspservice + cppservice + lspservice + util + ${THRIFT_LIBTHRIFT_LIBRARIES}) + +install(TARGETS cpplspservice DESTINATION ${INSTALL_SERVICE_DIR}) diff --git a/plugins/cpp_lsp/service/include/cpplspservice/cpplspservice.h b/plugins/cpp_lsp/service/include/cpplspservice/cpplspservice.h new file mode 100644 index 000000000..f0c6b31b3 --- /dev/null +++ b/plugins/cpp_lsp/service/include/cpplspservice/cpplspservice.h @@ -0,0 +1,192 @@ +#ifndef CC_SERVICE_LSP_CPPLSPSERVICE_H +#define CC_SERVICE_LSP_CPPLSPSERVICE_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +class CppLspServiceHandler : public LspServiceHandler +{ +public: + CppLspServiceHandler( + std::shared_ptr db_, + std::shared_ptr datadir_, + const cc::webserver::ServerContext& context_); + + // Standard LSP methods + + void getDefinition( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getDeclaration( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getImplementation( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getReferences( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + // Extended LSP methods + + void getDiagramTypes( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getModuleDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getSignature( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getParameters( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getLocalVariables( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getOverridden( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getOverrider( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getRead( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getWrite( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getMethods( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getFriends( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getEnumConstants( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getExpansion( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getUndefinition( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getThisCalls( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getCallsOfThis( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getCallee( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getCaller( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getVirtualCall( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getFunctionPointerCall( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getAlias( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getImplements( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getDataMember( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + + void getUnderlyingType( + pt::ptree& responseTree_, + const pt::ptree& params_) override final; + +private: + void fillResponseTree(pt::ptree& responseTree_, + const pt::ptree& params_, + language::CppServiceHandler::ReferenceType refType_, + bool canBeSingle_ = true); + + std::vector responseLocations( + const TextDocumentPositionParams& params_, + language::CppServiceHandler::ReferenceType refType_); + + std::vector fileDiagramTypes( + const DiagramTypeParams& params_); + + std::vector nodeDiagramTypes( + const DiagramTypeParams& params_); + + Diagram fileDiagram( + const DiagramParams& params_); + + Diagram nodeDiagram( + const DiagramParams& params_); + + void addLocationToIdInDiagram( + util::Graph& graph_, + const std::string& root_); + + void addPathToIdInFileDiagram( + util::Graph& graph_, + const std::string& root_); + + std::shared_ptr _db; + util::OdbTransaction _transaction; + + language::CppServiceHandler _cppService; + core::ProjectServiceHandler _projectHandler; +}; + +} // lsp +} // service +} // cc + +#endif // CC_SERVICE_LSP_CPPLSPSERVICE_H diff --git a/plugins/cpp_lsp/service/src/cpplspservice.cpp b/plugins/cpp_lsp/service/src/cpplspservice.cpp new file mode 100644 index 000000000..0d80ea329 --- /dev/null +++ b/plugins/cpp_lsp/service/src/cpplspservice.cpp @@ -0,0 +1,660 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include "language_types.h" + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +CppLspServiceHandler::CppLspServiceHandler( + std::shared_ptr db_, + std::shared_ptr datadir_, + const cc::webserver::ServerContext& context_) + : _db(db_), + _transaction(db_), + _cppService(db_, datadir_, context_), + _projectHandler(db_, datadir_, context_) +{ +} + +void CppLspServiceHandler::fillResponseTree(pt::ptree& responseTree_, + const pt::ptree& params_, + language::CppServiceHandler::ReferenceType refType_, + bool canBeSingle_) +{ + TextDocumentPositionParams positionParams; + positionParams.readNode(params_); + + std::vector locations = responseLocations(positionParams, refType_); + + if (canBeSingle_ && locations.size() == 1) + { + responseTree_.put_child("result", locations[0].createNode()); + } + else if (locations.size() > 1) + { + pt::ptree resultNode; + for (const Location &location : locations) + { + resultNode.push_back(std::make_pair("", location.createNode())); + } + responseTree_.put_child("result", resultNode); + } +} + +std::vector CppLspServiceHandler::responseLocations( + const TextDocumentPositionParams& params_, + language::CppServiceHandler::ReferenceType refType_) +{ + language::AstNodeInfo astNodeInfo; + core::FilePosition cppPosition; + + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == params_.textDocument.uri); + }); + + if (!file) + return std::vector(); + + cppPosition.file = std::to_string(file->id); + cppPosition.pos.line = params_.position.line; + cppPosition.pos.column = params_.position.character; + + _cppService.getAstNodeInfoByPosition(astNodeInfo, cppPosition); + + std::vector nodeInfos; + _cppService.getReferences(nodeInfos, astNodeInfo.id, refType_, {}); + + std::vector locations(nodeInfos.size()); + std::transform( + nodeInfos.begin(), nodeInfos.end(), + locations.begin(), + [&, this](const language::AstNodeInfo& nodeInfo) + { + std::string path = _transaction([&, this](){ + return _db->load(std::stoull(nodeInfo.range.file))->path; + }); + + Location location; + location.uri = path; + location.range.start.line = nodeInfo.range.range.startpos.line; + location.range.start.character = nodeInfo.range.range.startpos.column; + location.range.end.line = nodeInfo.range.range.endpos.line; + location.range.end.character = nodeInfo.range.range.endpos.column; + + return location; + }); + + return locations; +} + +void CppLspServiceHandler::getSignature( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + TextDocumentPositionParams positionParams; + positionParams.readNode(params_); + + language::AstNodeInfo astNodeInfo; + core::FilePosition cppPosition; + + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == positionParams.textDocument.uri); + }); + + if (file) + { + cppPosition.file = std::to_string(file->id); + cppPosition.pos.line = positionParams.position.line; + cppPosition.pos.column = positionParams.position.character; + + _cppService.getAstNodeInfoByPosition(astNodeInfo, cppPosition); + + responseTree_.put("result", astNodeInfo.astNodeValue); + } +} + +void CppLspServiceHandler::getDefinition( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::DEFINITION); +} + +void CppLspServiceHandler::getDeclaration( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::DECLARATION); +} + +void CppLspServiceHandler::getImplementation( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::INHERIT_BY); +} + +void CppLspServiceHandler::getReferences( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::USAGE, + false); // the result must always be a vector +} + +void CppLspServiceHandler::getParameters( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::PARAMETER); +} + +void CppLspServiceHandler::getLocalVariables( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::LOCAL_VAR); +} + +void CppLspServiceHandler::getOverridden( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::OVERRIDE); +} + +void CppLspServiceHandler::getOverrider( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::OVERRIDDEN_BY); +} + +void CppLspServiceHandler::getRead( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::READ); +} + +void CppLspServiceHandler::getWrite( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::WRITE); +} + +void CppLspServiceHandler::getMethods( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::METHOD); +} + +void CppLspServiceHandler::getFriends( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::FRIEND); +} + +void CppLspServiceHandler::getEnumConstants( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::ENUM_CONSTANTS); +} + +void CppLspServiceHandler::getExpansion( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::EXPANSION); +} + +void CppLspServiceHandler::getUndefinition( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::UNDEFINITION); +} + +void CppLspServiceHandler::getThisCalls( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::THIS_CALLS); +} + +void CppLspServiceHandler::getCallsOfThis( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::CALLS_OF_THIS); +} + +void CppLspServiceHandler::getCallee( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::CALLEE); +} + +void CppLspServiceHandler::getCaller( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::CALLER); +} + +void CppLspServiceHandler::getVirtualCall( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::VIRTUAL_CALL); +} + +void CppLspServiceHandler::getFunctionPointerCall( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::FUNC_PTR_CALL); +} + +void CppLspServiceHandler::getAlias( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::ALIAS); +} + +void CppLspServiceHandler::getImplements( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::INHERIT_FROM); +} + +void CppLspServiceHandler::getDataMember( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::DATA_MEMBER); +} + +void CppLspServiceHandler::getUnderlyingType( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + fillResponseTree( + responseTree_, + params_, + language::CppServiceHandler::UNDERLYING_TYPE); +} + +void CppLspServiceHandler::getDiagramTypes( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + DiagramTypeParams diagramTypeParams; + diagramTypeParams.readNode(params_); + + std::vector diagramTypesResult; + if (!diagramTypeParams.position) + { + diagramTypesResult = fileDiagramTypes(diagramTypeParams); + } + else + { + diagramTypesResult = nodeDiagramTypes(diagramTypeParams); + } + + pt::ptree resultNode; + for (const std::string& diagramType : diagramTypesResult) + { + resultNode.push_back(std::make_pair("", pt::ptree(diagramType))); + } + responseTree_.put_child("result", resultNode); +} + +std::vector CppLspServiceHandler::fileDiagramTypes( + const DiagramTypeParams& params_) +{ + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == params_.textDocument.uri); + }); + + if (!file) + return {}; + + std::map result; + _cppService.getFileDiagramTypes(result, std::to_string(file->id)); + + std::vector diagramTypes(result.size()); + std::transform(result.begin(), result.end(), diagramTypes.begin(), + [](std::pair item) + { + return item.first; + } + ); + + return diagramTypes; +} + +std::vector CppLspServiceHandler::nodeDiagramTypes( + const DiagramTypeParams& params_) +{ + language::AstNodeInfo astNodeInfo; + core::FilePosition cppPosition; + + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == params_.textDocument.uri); + }); + + if (!file) + return {}; + + cppPosition.file = std::to_string(file->id); + cppPosition.pos.line = params_.position->line; + cppPosition.pos.column = params_.position->character; + _cppService.getAstNodeInfoByPosition(astNodeInfo, cppPosition); + + std::map result; + _cppService.getDiagramTypes(result, astNodeInfo.id); + + std::vector diagramTypes(result.size()); + std::transform(result.begin(), result.end(), diagramTypes.begin(), + [](std::pair item) + { + return item.first; + } + ); + + return diagramTypes; +} + +void CppLspServiceHandler::getDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + DiagramParams diagramParams; + diagramParams.readNode(params_); + + Diagram diagramResult; + if (!diagramParams.position) + { + diagramResult = fileDiagram(diagramParams); + } + else + { + diagramResult = nodeDiagram(diagramParams); + } + + responseTree_.put("result", diagramResult); +} + +void CppLspServiceHandler::getModuleDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_) +{ + getDiagram(responseTree_, params_); +} + +Diagram CppLspServiceHandler::fileDiagram( + const DiagramParams& params_) +{ + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == params_.textDocument.uri); + }); + + if (!file) + return std::string(); + + const static std::map diagramTypes = + { + {"Internal architecture of this module", + language::CppServiceHandler::SUBSYSTEM_DEPENDENCY}, + {"This module depends on", + language::CppServiceHandler::EXTERNAL_DEPENDENCY}, + {"Users of this module", language::CppServiceHandler::EXTERNAL_USERS}, + {"Include Dependency", language::CppServiceHandler::INCLUDE_DEPENDENCY}, + {"Component Users", language::CppServiceHandler::COMPONENT_USERS}, + {"Interface Diagram", language::CppServiceHandler::INTERFACE}, + }; + + auto diagramTypeIt = diagramTypes.find(params_.diagramType); + if (diagramTypeIt == diagramTypes.end()) + return std::string(); + + auto graph = _cppService.returnFileDiagram( + std::to_string(file->id), + diagramTypeIt->second); + + if (graph.nodeCount() != 0) + { + addPathToIdInFileDiagram(graph, std::to_string(file->id)); + return graph.output(util::Graph::SVG); + } + return std::string(); +} + +Diagram CppLspServiceHandler::nodeDiagram( + const DiagramParams& params_) +{ + language::AstNodeInfo astNodeInfo; + core::FilePosition cppPosition; + + model::FilePtr file = _transaction([&, this](){ + return _db->query_one( + odb::query::path == params_.textDocument.uri); + }); + + if (!file) + return std::string(); + + cppPosition.file = std::to_string(file->id); + cppPosition.pos.line = params_.position->line; + cppPosition.pos.column = params_.position->character; + + _cppService.getAstNodeInfoByPosition(astNodeInfo, cppPosition); + + const static std::map diagramTypes = + { + {"Function call diagram", language::CppServiceHandler::FUNCTION_CALL}, + {"Detailed class diagram", language::CppServiceHandler::DETAILED_CLASS}, + {"Class collaboration diagram", + language::CppServiceHandler::CLASS_COLLABORATION}, + }; + + auto diagramTypeIt = diagramTypes.find(params_.diagramType); + if (diagramTypeIt == diagramTypes.end()) + return std::string(); + + auto graph = _cppService.returnDiagram(astNodeInfo.id, diagramTypeIt->second); + + if (graph.nodeCount() != 0) + { + addLocationToIdInDiagram(graph, astNodeInfo.id); + return graph.output(util::Graph::SVG); + } + return std::string(); +} + +void CppLspServiceHandler::addLocationToIdInDiagram( + util::Graph& graph_, + const std::string& root_) +{ + std::stack unvisited; + std::map visited; + unvisited.push(root_); + + while (!unvisited.empty()) + { + std::string current = unvisited.top(); + unvisited.pop(); + std::vector nodes; + _cppService.getReferences( + nodes, current, language::CppServiceHandler::DEFINITION, {}); + language::AstNodeInfo& nodeInfo = nodes.front(); + if (visited.find(nodeInfo.id) == visited.end() || !visited[nodeInfo.id]) + { + visited[nodeInfo.id] = true; + for (const auto& child : graph_.getChildren(nodeInfo.id)) + { + if (visited.find(child) == visited.end()) + { + unvisited.push(child); + visited[child] = false; + } + } + for (const auto& parent : graph_.getParents(nodeInfo.id)) + { + if (visited.find(parent) == visited.end()) + { + unvisited.push(parent); + visited[parent] = false; + } + } + + std::stringstream ss; + ss<<_transaction([&, this](){ + return _db->load(std::stoull(nodeInfo.range.file))->path; + }) + <<';' + < unvisited; + std::map visited; + unvisited.push(root_); + + while (!unvisited.empty()) + { + std::string current = unvisited.top(); + unvisited.pop(); + core::FileInfo fileInfo; + _projectHandler.getFileInfo(fileInfo, current); + if (visited.find(fileInfo.id) == visited.end() || !visited[fileInfo.id]) + { + visited[fileInfo.id] = true; + for (const auto& child : graph_.getChildren(fileInfo.id)) + { + if (visited.find(child) == visited.end()) + { + unvisited.push(child); + visited[child] = false; + } + } + for (const auto& parent : graph_.getParents(fileInfo.id)) + { + if (visited.find(parent) == visited.end()) + { + unvisited.push(parent); + visited[parent] = false; + } + } + graph_.setNodeAttribute(fileInfo.id, "id", fileInfo.path, true); + } + } +} + +} // lsp +} // service +} // cc diff --git a/plugins/cpp_lsp/service/src/plugin.cpp b/plugins/cpp_lsp/service/src/plugin.cpp new file mode 100644 index 000000000..c0488fc0c --- /dev/null +++ b/plugins/cpp_lsp/service/src/plugin.cpp @@ -0,0 +1,32 @@ +#include + +#include +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +extern "C" +{ + boost::program_options::options_description getOptions() + { + boost::program_options::options_description description("LSP Plugin"); + + return description; + } + + void registerPlugin( + const cc::webserver::ServerContext& context_, + cc::webserver::PluginHandler* pluginHandler_) + { + cc::webserver::registerPluginSimple( + context_, + pluginHandler_, + CODECOMPASS_LSP_SERVICE_FACTORY_WITH_CFG(Cpp, lsp), + "CppLspService"); + } +} +#pragma clang diagnostic pop diff --git a/plugins/cpp_metrics/model/CMakeLists.txt b/plugins/cpp_metrics/model/CMakeLists.txt index 2f5c29eb6..38d8ca343 100644 --- a/plugins/cpp_metrics/model/CMakeLists.txt +++ b/plugins/cpp_metrics/model/CMakeLists.txt @@ -2,10 +2,9 @@ include_directories( include ${cpp_PLUGIN_DIR}/model/include) -message(WARNING "${cpp_PLUGIN_DIR}/model/include") - set(ODB_SOURCES include/model/cppastnodemetrics.h + include/model/cppcohesionmetrics.h include/model/cppfilemetrics.h) generate_odb_files("${ODB_SOURCES}" "cpp") diff --git a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h index 3334a9bd7..eb17cdf3d 100644 --- a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h @@ -2,6 +2,8 @@ #define CC_MODEL_CPPASTNODEMETRICS_H #include +#include +#include namespace cc { @@ -13,8 +15,10 @@ struct CppAstNodeMetrics { enum Type { - PARAMETER_COUNT, - MCCABE + PARAMETER_COUNT = 1, + MCCABE = 2, + LACK_OF_COHESION = 3, + LACK_OF_COHESION_HS = 4, }; #pragma db id auto @@ -26,8 +30,18 @@ struct CppAstNodeMetrics #pragma db not_null Type type; - #pragma db not_null - unsigned value; + #pragma db null + double value; +}; + +#pragma db view \ + object(CppRecord) \ + object(CppAstNodeMetrics : \ + CppRecord::astNodeId == CppAstNodeMetrics::astNodeId) +struct CppRecordMetricsView +{ + #pragma db column(CppAstNodeMetrics::value) + double value; }; } //model diff --git a/plugins/cpp_metrics/model/include/model/cppcohesionmetrics.h b/plugins/cpp_metrics/model/include/model/cppcohesionmetrics.h new file mode 100644 index 000000000..bc8a20629 --- /dev/null +++ b/plugins/cpp_metrics/model/include/model/cppcohesionmetrics.h @@ -0,0 +1,77 @@ +#ifndef CC_MODEL_CPPCOHESIONMETRICS_H +#define CC_MODEL_CPPCOHESIONMETRICS_H + +#include +#include +#include + +namespace cc +{ +namespace model +{ +#pragma db view \ + object(CppRecord) \ + object(CppAstNode : CppRecord::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) +struct CohesionCppRecordView +{ + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppEntity::qualifiedName) + std::string qualifiedName; + + #pragma db column(CppEntity::astNodeId) + CppAstNodeId astNodeId; + + #pragma db column(File::path) + std::string filePath; +}; + +#pragma db view \ + object(CppMemberType) \ + object(CppAstNode : CppMemberType::memberAstNode) \ + query(CppMemberType::kind == cc::model::CppMemberType::Kind::Field && (?)) +struct CohesionCppFieldView +{ + #pragma db column(CppAstNode::entityHash) + std::size_t entityHash; +}; + +#pragma db view \ + object(CppMemberType) \ + object(CppAstNode : CppMemberType::memberAstNode) \ + object(File : CppAstNode::location.file) \ + query(CppMemberType::kind == cc::model::CppMemberType::Kind::Method && (?)) +struct CohesionCppMethodView +{ + typedef cc::model::Position::PosType PosType; + + #pragma db column(CppAstNode::location.range.start.line) + PosType startLine; + #pragma db column(CppAstNode::location.range.start.column) + PosType startColumn; + #pragma db column(CppAstNode::location.range.end.line) + PosType endLine; + #pragma db column(CppAstNode::location.range.end.column) + PosType endColumn; + + #pragma db column(File::path) + std::string filePath; +}; + +#pragma db view \ + object(CppAstNode) \ + object(File : CppAstNode::location.file) \ + query((CppAstNode::astType == cc::model::CppAstNode::AstType::Read \ + || CppAstNode::astType == cc::model::CppAstNode::AstType::Write) && (?)) +struct CohesionCppAstNodeView +{ + #pragma db column(CppAstNode::entityHash) + std::uint64_t entityHash; +}; + +} //model +} //cc + +#endif //CC_MODEL_CPPCOHESIONMETRICS_H diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index 518361a25..6dcfb0bc2 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -10,6 +10,9 @@ #include #include +#include +#include + #include #include @@ -23,13 +26,20 @@ class CppMetricsParser : public AbstractParser public: CppMetricsParser(ParserContext& ctx_); virtual ~CppMetricsParser(); + virtual bool cleanupDatabase() override; virtual bool parse() override; private: + // Calculate the count of parameters for every function. void functionParameters(); + // Calculate the McCabe complexity of functions. void functionMcCabe(); + // Calculate the lack of cohesion between member variables + // and member functions for every type. + void lackOfCohesion(); + std::vector _inputPaths; std::unordered_set _fileIdCache; std::unordered_map _astNodeIdCache; std::unique_ptr> _pool; diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index bbe3cfdf4..7e8269a4d 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include @@ -10,7 +12,9 @@ #include +#include #include +#include #include #include @@ -20,8 +24,14 @@ namespace cc namespace parser { +namespace fs = boost::filesystem; + CppMetricsParser::CppMetricsParser(ParserContext& ctx_): AbstractParser(ctx_) { + for (const std::string& path : + _ctx.options["input"].as>()) + _inputPaths.push_back(fs::canonical(path).string()); + util::OdbTransaction {_ctx.db} ([&, this] { for (const model::CppFileMetrics& fm : _ctx.db->query()) @@ -98,6 +108,10 @@ void CppMetricsParser::functionParameters() for (const model::CppFunctionParamCountWithId& paramCount : _ctx.db->query()) { + // Skip functions that were included from external libraries. + if (!cc::util::isRootedUnderAnyOf(_inputPaths, paramCount.filePath)) + continue; + model::CppAstNodeMetrics funcParams; funcParams.astNodeId = paramCount.id; funcParams.type = model::CppAstNodeMetrics::Type::PARAMETER_COUNT; @@ -111,9 +125,13 @@ void CppMetricsParser::functionMcCabe() { util::OdbTransaction {_ctx.db} ([&, this] { - for (const model::CppFunctionMcCabeWithId& function - : _ctx.db->query()) + for (const model::CppFunctionMcCabe& function + : _ctx.db->query()) { + // Skip functions that were included from external libraries. + if (!cc::util::isRootedUnderAnyOf(_inputPaths, function.filePath)) + continue; + model::CppAstNodeMetrics funcMcCabe; funcMcCabe.astNodeId = function.astNodeId; funcMcCabe.type = model::CppAstNodeMetrics::Type::MCCABE; @@ -123,13 +141,116 @@ void CppMetricsParser::functionMcCabe() }); } +void CppMetricsParser::lackOfCohesion() +{ + util::OdbTransaction {_ctx.db} ([&, this] + { + // Simplify some type names for readability. + typedef std::uint64_t HashType; + + typedef odb::query::query_columns QField; + const auto& QFieldTypeHash = QField::CppMemberType::typeHash; + + typedef odb::query::query_columns QMethod; + const auto& QMethodTypeHash = QMethod::CppMemberType::typeHash; + + typedef odb::query::query_columns QNode; + const auto& QNodeFilePath = QNode::File::path; + const auto& QNodeRange = QNode::CppAstNode::location.range; + + // Calculate the cohesion metric for all types. + for (const model::CohesionCppRecordView& type + : _ctx.db->query()) + { + // Skip types that were included from external libraries. + if (!cc::util::isRootedUnderAnyOf(_inputPaths, type.filePath)) + continue; + + std::unordered_set fieldHashes; + // Query all fields of the current type. + for (const model::CohesionCppFieldView& field + : _ctx.db->query( + QFieldTypeHash == type.entityHash + )) + { + // Record these fields for later use. + fieldHashes.insert(field.entityHash); + } + std::size_t fieldCount = fieldHashes.size(); + + std::size_t methodCount = 0; + std::size_t totalCohesion = 0; + // Query all methods of the current type. + for (const model::CohesionCppMethodView& method + : _ctx.db->query( + QMethodTypeHash == type.entityHash + )) + { + // Do not consider methods with no explicit bodies. + const model::Position start(method.startLine, method.startColumn); + const model::Position end(method.endLine, method.endColumn); + if (start < end) + { + std::unordered_set usedFields; + + // Query all AST nodes that use a variable for reading or writing... + for (const model::CohesionCppAstNodeView& node + : _ctx.db->query( + // ... in the same file as the current method + (QNodeFilePath == method.filePath && + // ... within the textual scope of the current method's body. + (QNodeRange.start.line >= start.line + || (QNodeRange.start.line == start.line + && QNodeRange.start.column >= start.column)) && + (QNodeRange.end.line <= end.line + || (QNodeRange.end.line == end.line + && QNodeRange.end.column <= end.column))) + )) + { + // If this AST node is a reference to a field of the type... + if (fieldHashes.find(node.entityHash) != fieldHashes.end()) + { + // ... then mark it as used by this method. + usedFields.insert(node.entityHash); + } + } + + ++methodCount; + totalCohesion += usedFields.size(); + } + } + + // Calculate and record metrics. + const double dF = fieldCount; + const double dM = methodCount; + const double dC = totalCohesion; + const bool trivial = fieldCount == 0 || methodCount == 0; + const bool singular = methodCount == 1; + + // Standard lack of cohesion (range: [0,1]) + model::CppAstNodeMetrics lcm; + lcm.astNodeId = type.astNodeId; + lcm.type = model::CppAstNodeMetrics::Type::LACK_OF_COHESION; + lcm.value = trivial ? 0.0 : + (1.0 - dC / (dM * dF)); + _ctx.db->persist(lcm); + + // Henderson-Sellers variant (range: [0,2]) + model::CppAstNodeMetrics lcm_hs; + lcm_hs.astNodeId = type.astNodeId; + lcm_hs.type = model::CppAstNodeMetrics::Type::LACK_OF_COHESION_HS; + lcm_hs.value = trivial ? 0.0 : singular ? NAN : + ((dM - dC / dF) / (dM - 1.0)); + _ctx.db->persist(lcm_hs); + } + }); +} + bool CppMetricsParser::parse() { - // Function parameter number metric. functionParameters(); - // Function McCabe metric functionMcCabe(); - + lackOfCohesion(); return true; } diff --git a/plugins/cpp_metrics/service/CMakeLists.txt b/plugins/cpp_metrics/service/CMakeLists.txt index c146a02f3..96b5a1fdf 100644 --- a/plugins/cpp_metrics/service/CMakeLists.txt +++ b/plugins/cpp_metrics/service/CMakeLists.txt @@ -1,6 +1,11 @@ include_directories( include ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp + ${PROJECT_BINARY_DIR}/service/project/gen-cpp + ${PROJECT_SOURCE_DIR}/service/project/include + ${PROJECT_SOURCE_DIR}/model/include + ${PROJECT_BINARY_DIR}/service/language/gen-cpp + ${PLUGIN_DIR}/model/include ${PROJECT_SOURCE_DIR}/util/include ${PROJECT_SOURCE_DIR}/webserver/include) @@ -9,35 +14,45 @@ include_directories(SYSTEM add_custom_command( OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/cxxmetrics_types.cpp + ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/cxxmetrics_types.h ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/CppMetricsService.cpp ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/CppMetricsService.h ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp COMMAND ${THRIFT_EXECUTABLE} --gen cpp -o ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/cppmetrics.thrift + -I ${PROJECT_SOURCE_DIR}/service + ${CMAKE_CURRENT_SOURCE_DIR}/cxxmetrics.thrift DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/cppmetrics.thrift + ${CMAKE_CURRENT_SOURCE_DIR}/cxxmetrics.thrift COMMENT - "Generating Thrift for cppmetrics.thrift") + "Generating Thrift for cxxmetrics.thrift") -add_library(cppmetricsthrift STATIC +add_library(cxxmetricsthrift STATIC + ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/cxxmetrics_types.cpp ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp/CppMetricsService.cpp) -target_compile_options(cppmetricsthrift PUBLIC -fPIC) +target_compile_options(cxxmetricsthrift PUBLIC -fPIC) -add_library(cppmetricsservice SHARED +add_dependencies(cxxmetricsthrift projectthrift) + +add_library(cxxmetricsservice SHARED src/cppmetricsservice.cpp src/plugin.cpp) -target_compile_options(cppmetricsservice PUBLIC -Wno-unknown-pragmas) +target_compile_options(cxxmetricsservice PUBLIC -Wno-unknown-pragmas) -target_link_libraries(cppmetricsservice - cppmetricsmodel - model +target_link_libraries(cxxmetricsservice util ${THRIFT_LIBTHRIFT_LIBRARIES} + model + cppmetricsmodel + projectthrift + projectservice + commonthrift ${ODB_LIBRARIES} - cppmetricsthrift) + cxxmetricsthrift) -install(TARGETS cppmetricsservice DESTINATION ${INSTALL_SERVICE_DIR}) +install(TARGETS cxxmetricsservice DESTINATION ${INSTALL_SERVICE_DIR}) +install_js_thrift() diff --git a/plugins/cpp_metrics/service/cppmetrics.thrift b/plugins/cpp_metrics/service/cppmetrics.thrift deleted file mode 100644 index 834d3f890..000000000 --- a/plugins/cpp_metrics/service/cppmetrics.thrift +++ /dev/null @@ -1,7 +0,0 @@ -namespace cpp cc.service.cppmetrics -namespace java cc.service.cppmetrics - -service CppMetricsService -{ - -} \ No newline at end of file diff --git a/plugins/cpp_metrics/service/cxxmetrics.thrift b/plugins/cpp_metrics/service/cxxmetrics.thrift new file mode 100644 index 000000000..0762ac534 --- /dev/null +++ b/plugins/cpp_metrics/service/cxxmetrics.thrift @@ -0,0 +1,48 @@ +include "project/common.thrift" +include "project/project.thrift" + +namespace cpp cc.service.cppmetrics +namespace java cc.service.cppmetrics + +enum CppMetricsType +{ + ParameterCount = 1, + McCabe = 2, + LackOfCohesion = 3, + LackOfCohesionHS = 4 +} + +struct CppMetricsTypeName +{ + 1:CppMetricsType type, + 2:string name +} + +struct CppMetricsAstNode +{ + 1:CppMetricsType type, + 2:double value +} + +service CppMetricsService +{ + /** + * This function returns the required C++ metric + * for a particular AST node. + */ + double getSingleCppMetricForAstNode( + 1:common.AstNodeId astNodeId, + 2:CppMetricsType metric) + + /** + * This function returns all available C++ metrics + * for a particular AST node. + */ + list getCppMetricsForAstNode( + 1:common.AstNodeId astNodeId) + + /** + * This function returns the names of metrics. + */ + list getCppMetricsTypeNames() +} \ No newline at end of file diff --git a/plugins/cpp_metrics/service/include/service/cppmetricsservice.h b/plugins/cpp_metrics/service/include/service/cppmetricsservice.h index 2409d36d1..4a65bd306 100644 --- a/plugins/cpp_metrics/service/include/service/cppmetricsservice.h +++ b/plugins/cpp_metrics/service/include/service/cppmetricsservice.h @@ -1,11 +1,18 @@ -#ifndef CC_SERVICE_DUMMY_DUMMYSSERVICE_H -#define CC_SERVICE_DUMMY_DUMMYSSERVICE_H +#ifndef CC_SERVICE_CPPMETRICSSERVICE_H +#define CC_SERVICE_CPPMETRICSSERVICE_H #include #include #include +#include + +#include +#include +#include +#include + #include #include #include @@ -27,6 +34,17 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf std::shared_ptr datadir_, const cc::webserver::ServerContext& context_); + double getSingleCppMetricForAstNode( + const core::AstNodeId& astNodeId_, + CppMetricsType::type metric_) override; + + void getCppMetricsForAstNode( + std::vector& _return, + const core::AstNodeId& astNodeId_) override; + + void getCppMetricsTypeNames( + std::vector& _return) override; + private: std::shared_ptr _db; util::OdbTransaction _transaction; @@ -38,4 +56,4 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf } // service } // cc -#endif // CC_SERVICE_DUMMY_CPPMETRICSSSERVICE_H +#endif // CC_SERVICE_CPPMETRICSSERVICE_H diff --git a/plugins/cpp_metrics/service/src/cppmetricsservice.cpp b/plugins/cpp_metrics/service/src/cppmetricsservice.cpp index 9749aa272..d1b7c5556 100644 --- a/plugins/cpp_metrics/service/src/cppmetricsservice.cpp +++ b/plugins/cpp_metrics/service/src/cppmetricsservice.cpp @@ -10,12 +10,77 @@ namespace cppmetrics CppMetricsServiceHandler::CppMetricsServiceHandler( std::shared_ptr db_, - std::shared_ptr /*datadir_*/, + std::shared_ptr datadir_, const cc::webserver::ServerContext& context_) : _db(db_), _transaction(db_), _config(context_.options) { } +void CppMetricsServiceHandler::getCppMetricsTypeNames( + std::vector& _return) +{ + CppMetricsTypeName typeName; + + typeName.type = CppMetricsType::ParameterCount; + typeName.name = "Number of function parameters"; + _return.push_back(typeName); + + typeName.type = CppMetricsType::McCabe; + typeName.name = "McCabe metric"; + _return.push_back(typeName); + + typeName.type = CppMetricsType::LackOfCohesion; + typeName.name = "Lack of cohesion of function"; + _return.push_back(typeName); + + typeName.type = CppMetricsType::LackOfCohesionHS; + typeName.name = "Lack of cohesion of function (Henderson-Sellers variant)"; + _return.push_back(typeName); +} + +void CppMetricsServiceHandler::getCppMetricsForAstNode( + std::vector& _return, + const core::AstNodeId& astNodeId_) +{ + CppMetricsAstNode metric; + + _transaction([&, this](){ + typedef odb::query CppAstNodeMetricsQuery; + + auto nodeMetrics = _db->query( + CppAstNodeMetricsQuery::astNodeId == std::stoull(astNodeId_)); + + for (const auto& nodeMetric : nodeMetrics) + { + metric.type = static_cast(nodeMetric.type); + metric.value = nodeMetric.value; + _return.push_back(metric); + } + }); +} + +double CppMetricsServiceHandler::getSingleCppMetricForAstNode( + const core::AstNodeId& astNodeId_, + CppMetricsType::type metric_) +{ + return _transaction([&, this]() -> std::double_t { + typedef odb::query CppAstNodeMetricsQuery; + + auto nodeMetric = _db->query( + CppAstNodeMetricsQuery::astNodeId == std::stoull(astNodeId_) && + CppAstNodeMetricsQuery::type == static_cast(metric_)); + + if (nodeMetric.empty()) + { + core::InvalidInput ex; + ex.__set_msg("Invalid metric type for AST node: " + astNodeId_); + throw ex; + } + + return nodeMetric.begin()->value; + }); +} + } // cppmetrics } // service } // cc diff --git a/plugins/cpp_metrics/test/CMakeLists.txt b/plugins/cpp_metrics/test/CMakeLists.txt index 34b7cf60e..c063b7938 100644 --- a/plugins/cpp_metrics/test/CMakeLists.txt +++ b/plugins/cpp_metrics/test/CMakeLists.txt @@ -1,8 +1,13 @@ include_directories( - ${PLUGIN_DIR}/model/include - ${PLUGIN_DIR}/service/include - ${CMAKE_CURRENT_BINARY_DIR}/../service/gen-cpp - ${PROJECT_SOURCE_DIR}/model/include) + include + ${PLUGIN_DIR}/model/include + ${PLUGIN_DIR}/service/include + ${CMAKE_CURRENT_BINARY_DIR}/../service/gen-cpp + ${PROJECT_SOURCE_DIR}/model/include + ${PROJECT_BINARY_DIR}/service/project/gen-cpp + ${PROJECT_SOURCE_DIR}/service/project/include + ${PROJECT_SOURCE_DIR}/plugins/cpp_metrics/model/include + ${PROJECT_BINARY_DIR}/plugins/cpp_metrics/model/include) include_directories(SYSTEM ${THRIFT_LIBTHRIFT_INCLUDE_DIRS}) @@ -22,13 +27,15 @@ target_link_libraries(cppmetricsservicetest model cppmodel cppservice + commonthrift ${Boost_LIBRARIES} ${GTEST_BOTH_LIBRARIES} pthread) target_link_libraries(cppmetricsparsertest - util + cppmetricsmodel model + util cppmodel ${Boost_LIBRARIES} ${GTEST_BOTH_LIBRARIES} @@ -53,6 +60,7 @@ else() --database \"${TEST_DB}\" \ --name cppmetricsservicetest \ --input ${CMAKE_CURRENT_BINARY_DIR}/build/compile_commands.json \ + --input ${CMAKE_CURRENT_SOURCE_DIR}/sources/service \ --workspace ${CMAKE_CURRENT_BINARY_DIR}/workdir/ \ --force" "${TEST_DB}") @@ -68,6 +76,7 @@ else() --database \"${TEST_DB}\" \ --name cppparsertest \ --input ${CMAKE_CURRENT_BINARY_DIR}/build/compile_commands.json \ + --input ${CMAKE_CURRENT_SOURCE_DIR}/sources/parser \ --workspace ${CMAKE_CURRENT_BINARY_DIR}/workdir/ \ --force" "${TEST_DB}") diff --git a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt index 305294e31..7a4633ff0 100644 --- a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt +++ b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 2.6) -project(CppTestProject) +project(CppMetricsTestProject) -add_library(CppTestProject STATIC - mccabe.cpp) +add_library(CppMetricsTestProject STATIC + mccabe.cpp + lackofcohesion.cpp) diff --git a/plugins/cpp_metrics/test/sources/parser/lackofcohesion.cpp b/plugins/cpp_metrics/test/sources/parser/lackofcohesion.cpp new file mode 100644 index 000000000..a2c9b1f71 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/lackofcohesion.cpp @@ -0,0 +1,223 @@ +//////////////// + +struct trivial_0_0 +{ + +}; + +//////////////// + +struct trivial_1_0 +{ + int field1; +}; + +struct trivial_2_0 +{ + int field1; + int field2; +}; + +struct trivial_3_0 +{ + int field1; + int field2; + int field3; +}; + +//////////////// + +struct trivial_0_1 +{ + void method1() {} +}; + +struct trivial_0_2 +{ + void method1() {} + void method2() {} +}; + +struct trivial_0_3 +{ + void method1() {} + void method2() {} + void method3() {} +}; + +//////////////// + +struct fully_cohesive_read +{ + int single_field; + + int single_method() const { return single_field; } +}; + +struct fully_cohesive_write +{ + int single_field; + + void single_method(int value) { single_field = value; } +}; + +struct fully_cohesive_read_write +{ + int single_field; + + bool single_method(int value) + { + if (single_field != value) + { + single_field = value; + return true; + } + else return false; + } +}; + +//////////////// + +struct fully_cohesive_2_1 +{ + int field1; + int field2; + + int method1() const { return field1 + field2; } +}; + +struct fully_cohesive_1_2 +{ + int field1; + + int method1() const { return +field1; } + int method2() const { return -field1; } +}; + +struct fully_cohesive_2_2 +{ + int field1; + int field2; + + int method1() const { return field1 + field2; } + int method2() const { return field1 - field2; } +}; + +struct fully_cohesive_3_3 +{ + int field1; + int field2; + int field3; + + int method1() const { return field1 + field2 + field3; } + int method2() const { return field1 * field2 * field3; } + void method3(int value) { field1 = field2 = field3 = value; } +}; + +//////////////// + +struct fully_incohesive_1_1 +{ + int field1; + + void method1() {} +}; + +struct fully_incohesive_1_2 +{ + int field1; + + void method1() {} + void method2() {} +}; + +struct fully_incohesive_2_1 +{ + int field1; + int field2; + + void method1() {} +}; + +struct fully_incohesive_2_2 +{ + int field1; + int field2; + + void method1() {} + void method2() {} +}; + +//////////////// + +struct partially_cohesive_1_2 +{ + int field1; + + int method1() const { return field1; } + int method2() const { return 42; } +}; + +struct partially_cohesive_2_1 +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } +}; + +struct partially_cohesive_2_2_A +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return 42; } +}; + +struct partially_cohesive_2_2_B +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return field2 - 42; } +}; + +struct partially_cohesive_2_2_C +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return field2 - field1; } +}; + +//////////////// + +struct same_partial_coh_A +{ + int field1, field2, field3; + + int method1() const { return field1; } + void method2() { field2 = field1; } + int method3() { return field3 = field2 * field1; } +}; + +struct same_partial_coh_B +{ + int field1, field2, field3; + + int method1() const { return field1 + field1; } + void method2() { field2 += field1; } + int method3() { return field3 = field2 * field2 + field1 * field1; } +}; + +struct same_partial_coh_C +{ + int field1, field2, field3; + + int method1() const { return 2 * field3; } + void method2() { field2 = 42 * field3 / field2; } + int method3() { return field1 = field3 + field2; } +}; diff --git a/plugins/cpp_metrics/test/sources/service/CMakeLists.txt b/plugins/cpp_metrics/test/sources/service/CMakeLists.txt index 305294e31..7a4633ff0 100644 --- a/plugins/cpp_metrics/test/sources/service/CMakeLists.txt +++ b/plugins/cpp_metrics/test/sources/service/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 2.6) -project(CppTestProject) +project(CppMetricsTestProject) -add_library(CppTestProject STATIC - mccabe.cpp) +add_library(CppMetricsTestProject STATIC + mccabe.cpp + lackofcohesion.cpp) diff --git a/plugins/cpp_metrics/test/sources/service/lackofcohesion.cpp b/plugins/cpp_metrics/test/sources/service/lackofcohesion.cpp new file mode 100644 index 000000000..a2c9b1f71 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/service/lackofcohesion.cpp @@ -0,0 +1,223 @@ +//////////////// + +struct trivial_0_0 +{ + +}; + +//////////////// + +struct trivial_1_0 +{ + int field1; +}; + +struct trivial_2_0 +{ + int field1; + int field2; +}; + +struct trivial_3_0 +{ + int field1; + int field2; + int field3; +}; + +//////////////// + +struct trivial_0_1 +{ + void method1() {} +}; + +struct trivial_0_2 +{ + void method1() {} + void method2() {} +}; + +struct trivial_0_3 +{ + void method1() {} + void method2() {} + void method3() {} +}; + +//////////////// + +struct fully_cohesive_read +{ + int single_field; + + int single_method() const { return single_field; } +}; + +struct fully_cohesive_write +{ + int single_field; + + void single_method(int value) { single_field = value; } +}; + +struct fully_cohesive_read_write +{ + int single_field; + + bool single_method(int value) + { + if (single_field != value) + { + single_field = value; + return true; + } + else return false; + } +}; + +//////////////// + +struct fully_cohesive_2_1 +{ + int field1; + int field2; + + int method1() const { return field1 + field2; } +}; + +struct fully_cohesive_1_2 +{ + int field1; + + int method1() const { return +field1; } + int method2() const { return -field1; } +}; + +struct fully_cohesive_2_2 +{ + int field1; + int field2; + + int method1() const { return field1 + field2; } + int method2() const { return field1 - field2; } +}; + +struct fully_cohesive_3_3 +{ + int field1; + int field2; + int field3; + + int method1() const { return field1 + field2 + field3; } + int method2() const { return field1 * field2 * field3; } + void method3(int value) { field1 = field2 = field3 = value; } +}; + +//////////////// + +struct fully_incohesive_1_1 +{ + int field1; + + void method1() {} +}; + +struct fully_incohesive_1_2 +{ + int field1; + + void method1() {} + void method2() {} +}; + +struct fully_incohesive_2_1 +{ + int field1; + int field2; + + void method1() {} +}; + +struct fully_incohesive_2_2 +{ + int field1; + int field2; + + void method1() {} + void method2() {} +}; + +//////////////// + +struct partially_cohesive_1_2 +{ + int field1; + + int method1() const { return field1; } + int method2() const { return 42; } +}; + +struct partially_cohesive_2_1 +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } +}; + +struct partially_cohesive_2_2_A +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return 42; } +}; + +struct partially_cohesive_2_2_B +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return field2 - 42; } +}; + +struct partially_cohesive_2_2_C +{ + int field1; + int field2; + + int method1() const { return field1 + 42; } + int method2() const { return field2 - field1; } +}; + +//////////////// + +struct same_partial_coh_A +{ + int field1, field2, field3; + + int method1() const { return field1; } + void method2() { field2 = field1; } + int method3() { return field3 = field2 * field1; } +}; + +struct same_partial_coh_B +{ + int field1, field2, field3; + + int method1() const { return field1 + field1; } + void method2() { field2 += field1; } + int method3() { return field3 = field2 * field2 + field1 * field1; } +}; + +struct same_partial_coh_C +{ + int field1, field2, field3; + + int method1() const { return 2 * field3; } + void method2() { field2 = 42 * field3 / field2; } + int method3() { return field1 = field3 + field2; } +}; diff --git a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp index c958ff44a..b299bea0f 100644 --- a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp +++ b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp @@ -1,7 +1,18 @@ +#include #include +// Same as EXPECT_NEAR, but NANs are also considered equal. +#define EXPECT_EQF(val1, val2, abs_error) { \ + const auto v1 = val1; const auto v2 = val2; \ + const bool n1 = isnan(v1); const bool n2 = isnan(v2); \ + EXPECT_EQ(n1, n2); \ + if (!n1 && !n2) EXPECT_NEAR(v1, v2, abs_error); \ +} + #include #include +#include +#include #include #include @@ -19,16 +30,46 @@ class CppMetricsParserTest : public ::testing::Test {} protected: + typedef model::CppAstNodeMetrics::Type Type; + + bool queryRecordMetric( + const std::string& qualType_, + Type metricType_, + double& result_); + std::shared_ptr _db; util::OdbTransaction _transaction; }; +bool CppMetricsParserTest::queryRecordMetric( + const std::string& qualType_, + Type metricType_, + double& result_) +{ + typedef odb::query::query_columns QEntry; + const auto& QEntryQualName = QEntry::CppRecord::qualifiedName; + const auto& QEntryType = QEntry::CppAstNodeMetrics::type; + + model::CppRecordMetricsView entry; + if (_db->query_one( + QEntryQualName == qualType_ && QEntryType == metricType_, entry)) + { + result_ = entry.value; + return true; + } + else return false; +} + +// McCabe + +typedef std::pair McCabeParam; + class ParameterizedMcCabeTest : public CppMetricsParserTest, - public ::testing::WithParamInterface> + public ::testing::WithParamInterface {}; -std::vector> parameters = { +std::vector paramMcCabe = { {"conditionals", 8}, {"loops1", 6}, {"loops2", 6}, @@ -53,5 +94,68 @@ TEST_P(ParameterizedMcCabeTest, McCabeTest) { INSTANTIATE_TEST_SUITE_P( ParameterizedMcCabeTestSuite, ParameterizedMcCabeTest, - ::testing::ValuesIn(parameters) - ); \ No newline at end of file + ::testing::ValuesIn(paramMcCabe) +); + +// Lack of Cohesion + +struct LackOfCohesionParam +{ + std::string typeName; + double loc; + double locHS; +}; + +class ParameterizedLackOfCohesionTest + : public CppMetricsParserTest, + public ::testing::WithParamInterface +{}; + +constexpr double C1_3 = 1.0 / 3.0; +std::vector paramLackOfCohesion = { + {"trivial_0_0", 0, 0}, + {"trivial_1_0", 0, 0}, + {"trivial_2_0", 0, 0}, + {"trivial_3_0", 0, 0}, + {"trivial_0_1", 0, 0}, + {"trivial_0_2", 0, 0}, + {"trivial_0_3", 0, 0}, + {"fully_cohesive_read", 0, NAN}, + {"fully_cohesive_write", 0, NAN}, + {"fully_cohesive_read_write", 0, NAN}, + {"fully_cohesive_2_1", 0, NAN}, + {"fully_cohesive_1_2", 0, 0}, + {"fully_cohesive_2_2", 0, 0}, + {"fully_cohesive_3_3", 0, 0}, + {"fully_incohesive_1_1", 1, NAN}, + {"fully_incohesive_1_2", 1, 2}, + {"fully_incohesive_2_1", 1, NAN}, + {"fully_incohesive_2_2", 1, 2}, + {"partially_cohesive_1_2", 0.5, 1}, + {"partially_cohesive_2_1", 0.5, NAN}, + {"partially_cohesive_2_2_A", 0.75, 1.5}, + {"partially_cohesive_2_2_B", 0.5, 1}, + {"partially_cohesive_2_2_C", 0.25, 0.5}, + {"same_partial_coh_A", C1_3, 0.5}, + {"same_partial_coh_B", C1_3, 0.5}, + {"same_partial_coh_C", C1_3, 0.5}, +}; + +TEST_P(ParameterizedLackOfCohesionTest, LackOfCohesionTest) { + _transaction([&, this]() { + const std::string& qualType = GetParam().typeName; + double loc, locHS; + ASSERT_TRUE(queryRecordMetric(qualType, Type::LACK_OF_COHESION, loc)); + ASSERT_TRUE(queryRecordMetric(qualType, Type::LACK_OF_COHESION_HS, locHS)); + + constexpr double tolerance = 1e-8; + EXPECT_EQF(GetParam().loc, loc, tolerance); + EXPECT_EQF(GetParam().locHS, locHS, tolerance); + }); +} + +INSTANTIATE_TEST_SUITE_P( + ParameterizedLackOfCohesionTestSuite, + ParameterizedLackOfCohesionTest, + ::testing::ValuesIn(paramLackOfCohesion) +); diff --git a/scripts/install_latest_build2.sh b/scripts/install_latest_build2.sh old mode 100644 new mode 100755 index b895f0fe7..2cc8cfa78 --- a/scripts/install_latest_build2.sh +++ b/scripts/install_latest_build2.sh @@ -9,10 +9,23 @@ fi install_dir=$1 toolchain_file="toolchain.sha256" -wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +if [ "$1" = "--version" ]; then + wget -q --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +else + wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +fi + version_line=$(grep -m 1 '' "$toolchain_file") version_number=$(echo "$version_line" | awk '{print $2}') + +### Return with version string only without actually installing build2 if "--version" flag is specified. +if [ "$1" = "--version" ]; then + echo "${version_number}" + rm -f "${toolchain_file}" + exit 0 +fi + version_to_install=build2-install-${version_number}.sh download_url=https://download.build2.org/${version_number}/${version_to_install} wget --no-verbose --no-clobber "${download_url}" -O "${version_to_install}" diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt index 21b32b2ae..a482ff7bf 100644 --- a/service/CMakeLists.txt +++ b/service/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(authentication) add_subdirectory(language) +add_subdirectory(lsp) add_subdirectory(plugin) add_subdirectory(project) add_subdirectory(workspace) diff --git a/service/lsp/CMakeLists.txt b/service/lsp/CMakeLists.txt new file mode 100644 index 000000000..b7ad6ac60 --- /dev/null +++ b/service/lsp/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(include) + +add_library(lspservice STATIC + src/lspservice.cpp + src/lsp_types.cpp) + +target_compile_options(lspservice PUBLIC -fPIC) + +target_link_libraries(lspservice + ${Boost_LIBRARIES}) diff --git a/service/lsp/include/lspservice/lsp_types.h b/service/lsp/include/lspservice/lsp_types.h new file mode 100644 index 000000000..5722ef767 --- /dev/null +++ b/service/lsp/include/lspservice/lsp_types.h @@ -0,0 +1,277 @@ +#ifndef CC_MODEL_LSP_TYPES_H +#define CC_MODEL_LSP_TYPES_H + +#include + +#include +#include + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +namespace pt = boost::property_tree; + +typedef std::string DocumentUri; +typedef std::string Diagram; + +/** + * LSP error codes. + */ +enum class ErrorCode +{ + // Defined by JSON RPC + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + ServerErrorStart = -32099, + ServerErrorEnd = -32000, + ServerNotInitialized = -32002, + UnknownError = -32001, + + // Defined by the protocol + RequestCancelled = -32800 +}; + +/** + * Represents an abstract base class for readable LSP structures. + */ +struct Readable +{ + virtual void readNode(const pt::ptree& node) = 0; +}; + +/** + * Represents an abstract base class for writeable LSP structures. + */ +struct Writeable +{ + virtual void writeNode(pt::ptree& node) const = 0; + + inline pt::ptree createNode() const + { + pt::ptree node; + writeNode(node); + return node; + } +}; + +/** + * Represents an LSP response error message. + */ +struct ResponseError : public Writeable +{ + /** + * A number indicating the error type that occurred. + */ + ErrorCode code; + /** + * A string providing a short description of the error. + */ + std::string message; + + void writeNode(pt::ptree& node) const override; +}; + +/** + * Text documents are identified using a URI. + * + * On the protocol level, URIs are passed as strings. + */ +struct TextDocumentIdentifier : public Readable, public Writeable +{ + /** + * The text document's URI. + */ + DocumentUri uri; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * Position in a text document expressed as zero-based line and zero-based + * character offset. + * + * A position is between two characters like an ‘insert’ cursor in a editor. + * Special values like for example -1 to denote the end of a line are not + * supported. + */ +struct Position : public Readable, public Writeable +{ + /** + * Line position in a document (zero-based). + */ + int line; + /** + * Character offset on a line in a document (zero-based). Assuming that the + * line is represented as a string, the `character` value represents the gap + * between the `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back to + * the line length. + */ + int character; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * A range in a text document expressed as (zero-based) start and end positions. + * + * A range is comparable to a selection in an editor. Therefore the end position + * is exclusive. + * If you want to specify a range that contains a line including the line ending + * character(s) then use an end position denoting the start of the next line. + */ +struct Range : public Readable, public Writeable +{ + /** + * The range's start position. + */ + Position start; + /** + * The range's end position. + */ + Position end; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * Represents a location inside a resource, such as a line inside a text file. + */ +struct Location final : public Readable, public Writeable +{ + DocumentUri uri; + Range range; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * A parameter literal used in requests to pass a text document and a position + * inside that document. + */ +struct TextDocumentPositionParams : public Readable, public Writeable +{ + TextDocumentIdentifier textDocument; + Position position; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * Represents th context used in requests to retrieve the references. + */ +struct ReferenceContext : public Readable, public Writeable +{ + bool includeDeclaration; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * A parameter literal used in requests to retrieve the references. + */ +struct ReferenceParams : public TextDocumentPositionParams +{ + ReferenceContext context; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * A parameter literal used in requests to retrieve the type of diagrams + * available for a document and optionally a selected position inside it. + */ +struct DiagramTypeParams : public Readable, public Writeable +{ + TextDocumentIdentifier textDocument; + boost::optional position; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * A parameter literal used in requests to retrieve the a specific diagram + * for a document and optionally a selected position inside it. + */ +struct DiagramParams : DiagramTypeParams +{ + std::string diagramType; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * Represents a possible auto-complete or context menu item. + */ +struct CompletionItem final : public Readable, public Writeable +{ + /** + * The label of this completion item. By default + * also the text that is inserted when selecting + * this completion. + */ + std::string label; + /** + * The kind of this completion item. Based of the kind + * an icon is chosen by the editor. + */ + boost::optional kind; + /** + * A human-readable string with additional information + * about this item, like type or symbol information. + */ + boost::optional detail; + /** + * A human-readable string that represents a doc-comment. + */ + boost::optional documentation; + /** + * A data entry field that is preserved on a completion item between + * a completion and a completion resolve request. + */ + boost::optional data; + + void readNode(const pt::ptree& node) override; + void writeNode(pt::ptree& node) const override; +}; + +/** + * Represents a list of completion items. + */ +struct CompletionList : public Writeable +{ + /** + * This list it not complete. Further typing should result in recomputing + * this list. + */ + bool isIncomplete; + /** + * The completion items. + */ + std::vector items; + + void writeNode(pt::ptree& node) const override; +}; + +} // lsp +} // service +} // cc + +#endif // CC_MODEL_LSP_TYPES_H diff --git a/service/lsp/include/lspservice/lspservice.h b/service/lsp/include/lspservice/lspservice.h new file mode 100644 index 000000000..931502e00 --- /dev/null +++ b/service/lsp/include/lspservice/lspservice.h @@ -0,0 +1,152 @@ +#ifndef CC_SERVICE_LSP_LSPSERVICE_H +#define CC_SERVICE_LSP_LSPSERVICE_H + +#include + +#include + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +namespace pt = boost::property_tree; + +class LspServiceHandler +{ +public: + virtual ~LspServiceHandler() = default; + + // Standard LSP methods + void virtual getDefinition( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getDeclaration( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getImplementation( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getReferences( + pt::ptree& responseTree_, + const pt::ptree& params_); + + // Extended LSP methods + void virtual getDiagramTypes( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getModuleDiagram( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getSignature( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getParameters( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getLocalVariables( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getOverridden( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getOverrider( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getRead( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getWrite( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getMethods( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getFriends( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getEnumConstants( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getExpansion( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getUndefinition( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getThisCalls( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getCallsOfThis( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getCallee( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getCaller( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getVirtualCall( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getFunctionPointerCall( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getAlias( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getImplements( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getDataMember( + pt::ptree& responseTree_, + const pt::ptree& params_); + + void virtual getUnderlyingType( + pt::ptree& responseTree_, + const pt::ptree& params_); + + // Errors + void getMethodNotFound(pt::ptree& responseTree_, const std::string& method_); + void getParseError(pt::ptree& responseTree_, const std::exception& ex_); + void getInternalError(pt::ptree& responseTree_, const std::exception& ex_); + void getUnknownError(pt::ptree& responseTree_); + +}; + +} // lsp +} // service +} // cc + +#endif // CC_SERVICE_LSP_LSPSERVICE_H diff --git a/service/lsp/src/lsp_types.cpp b/service/lsp/src/lsp_types.cpp new file mode 100644 index 000000000..af1b7bd48 --- /dev/null +++ b/service/lsp/src/lsp_types.cpp @@ -0,0 +1,190 @@ +#include + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +//--- ResponseError ---// + +void ResponseError::writeNode(pt::ptree& node) const +{ + node.put("code", static_cast(code)); + node.put("message", message); +} + +//--- TextDocumentIdentifier ---// + +void TextDocumentIdentifier::readNode(const pt::ptree& node) +{ + uri = node.get("uri"); +} + +void TextDocumentIdentifier::writeNode(pt::ptree& node) const +{ + node.put("uri", uri); +} + +//--- Position ---// + +void Position::readNode(const pt::ptree& node) +{ + line = node.get("line"); + character = node.get("character"); +} + +void Position::writeNode(pt::ptree& node) const +{ + node.put("line", line); + node.put("character", character); +} + +//--- Range ---// + +void Range::readNode(const pt::ptree& node) +{ + start.readNode(node.get_child("start")); + end.readNode(node.get_child("end")); +} + +void Range::writeNode(pt::ptree& node) const +{ + node.put_child("start", start.createNode()); + node.put_child("end", end.createNode()); +} + +//--- Location ---// + +void Location::readNode(const pt::ptree& node) +{ + uri = node.get("uri"); + range.readNode(node.get_child("range")); +} + +void Location::writeNode(pt::ptree& node) const +{ + node.put("uri", uri); + node.put_child("range", range.createNode()); +} + +//--- TextDocumentPositionParams ---// + +void TextDocumentPositionParams::readNode(const pt::ptree& node) +{ + textDocument.readNode(node.get_child("textDocument")); + position.readNode(node.get_child("position")); +} + +void TextDocumentPositionParams::writeNode(pt::ptree& node) const +{ + node.put_child("textDocument", textDocument.createNode()); + node.put_child("position", position.createNode()); +} + +//--- ReferenceContext ---// + +void ReferenceContext::readNode(const pt::ptree& node) +{ + includeDeclaration = node.get("includeDeclaration"); +} + +void ReferenceContext::writeNode(pt::ptree& node) const +{ + node.put("includeDeclaration", includeDeclaration); +} + +//--- ReferenceParams ---// + +void ReferenceParams::readNode(const pt::ptree& node) +{ + TextDocumentPositionParams::readNode(node); + context.readNode(node.get_child("context")); +} + +void ReferenceParams::writeNode(pt::ptree& node) const +{ + TextDocumentPositionParams::writeNode(node); + node.put_child("context", context.createNode()); +} + +//--- DiagramTypeParams ---// + +void DiagramTypeParams::readNode(const pt::ptree& node) +{ + textDocument.readNode(node.get_child("textDocument")); + + if (auto item = node.get_child_optional("position")) + { + position = Position(); + position->readNode(item.get()); + } +} + +void DiagramTypeParams::writeNode(pt::ptree& node) const +{ + node.put_child("textDocument", textDocument.createNode()); + if (position) + node.put_child("position", position->createNode()); +} + +//--- DiagramParams ---// + +void DiagramParams::readNode(const pt::ptree& node) +{ + DiagramTypeParams::readNode(node); + diagramType = node.get("diagramType"); +} + +void DiagramParams::writeNode(pt::ptree& node) const +{ + DiagramTypeParams::writeNode(node); + node.put("diagramType", diagramType); +} + +//--- CompletionItem ---// + +void CompletionItem::readNode(const pt::ptree& node) +{ + label = node.get("label"); + if (auto item = node.get_optional("kind")) + kind = item; + if (auto item = node.get_optional("detail")) + detail = item; + if (auto item = node.get_optional("documentation")) + documentation = item; + if (auto item = node.get_optional("data")) + data = item; +} + +void CompletionItem::writeNode(pt::ptree& node) const +{ + node.put("label", label); + if (kind) + node.put("kind", kind); + if (detail) + node.put("detail", detail); + if (documentation) + node.put("documentation", documentation); + if (data) + node.put("data", data); +} + +//--- CompletionList ---// + +void CompletionList::writeNode(pt::ptree& node) const +{ + node.put("isIncomplete", isIncomplete); + + pt::ptree itemsNode; + for (const CompletionItem& item : items) + { + itemsNode.push_back(std::make_pair("", item.createNode())); + } + node.put_child("items", itemsNode); +} + +} // lsp +} // service +} // cc diff --git a/service/lsp/src/lspservice.cpp b/service/lsp/src/lspservice.cpp new file mode 100644 index 000000000..21f4edc0c --- /dev/null +++ b/service/lsp/src/lspservice.cpp @@ -0,0 +1,258 @@ +#include + +namespace cc +{ +namespace service +{ +namespace lsp +{ + +// Standard LSP methods + +void LspServiceHandler::getDefinition( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/definition"); +} + +void LspServiceHandler::getDeclaration( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/declaration"); +} + +void LspServiceHandler::getImplementation( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/implementation"); +} + +void LspServiceHandler::getReferences( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/references"); +} + +// Extended LSP methods + +void LspServiceHandler::getDiagramTypes( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/diagramTypes"); +} + +void LspServiceHandler::getDiagram( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/diagram"); +} + +void LspServiceHandler::getModuleDiagram( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "directory/diagram"); +} + +void LspServiceHandler::getSignature( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/signature"); +} + +void LspServiceHandler::getParameters( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/parameters"); +} + +void LspServiceHandler::getLocalVariables( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/localVariables"); +} + +void LspServiceHandler::getOverridden( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/overridden"); +} + +void LspServiceHandler::getOverrider( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/overriders"); +} + +void LspServiceHandler::getRead( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/read"); +} + +void LspServiceHandler::getWrite( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/write"); +} + +void LspServiceHandler::getMethods( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/methods"); +} + +void LspServiceHandler::getFriends( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/friends"); +} + +void LspServiceHandler::getEnumConstants( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/enumConstants"); +} + +void LspServiceHandler::getExpansion( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/expansion"); +} + +void LspServiceHandler::getUndefinition( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/undefinition"); +} + +void LspServiceHandler::getThisCalls( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/thisCalls"); +} + +void LspServiceHandler::getCallsOfThis( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/callsOfThis"); +} + +void LspServiceHandler::getCallee( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/callee"); +} + +void LspServiceHandler::getCaller( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/caller"); +} + +void LspServiceHandler::getVirtualCall( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/virtualCall"); +} + +void LspServiceHandler::getFunctionPointerCall( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/functionPointerCall"); +} + +void LspServiceHandler::getAlias( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/alias"); +} + +void LspServiceHandler::getImplements( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/implements"); +} + +void LspServiceHandler::getDataMember( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/dataMember"); +} + +void LspServiceHandler::getUnderlyingType( + pt::ptree& responseTree_, + const pt::ptree&) +{ + getMethodNotFound(responseTree_, "textDocument/underlyingType"); +} + +// Errors + +void LspServiceHandler::getMethodNotFound( + pt::ptree& responseTree_, + const std::string& method_) +{ + ResponseError error; + error.code = ErrorCode::MethodNotFound; + error.message = std::string("Unsupported method: ").append(method_); + responseTree_.put_child("error", error.createNode()); +} + +void LspServiceHandler::getParseError( + pt::ptree& responseTree_, + const std::exception& ex_) +{ + ResponseError error; + error.code = ErrorCode::ParseError; + error.message = std::string("JSON RPC parsing error: ").append(ex_.what()); + responseTree_.put_child("error", error.createNode()); +} + +void LspServiceHandler::getInternalError( + pt::ptree& responseTree_, + const std::exception& ex_) +{ + ResponseError error; + error.code = ErrorCode::InternalError; + error.message = ex_.what(); + responseTree_.put_child("error", error.createNode()); +} + +void LspServiceHandler::getUnknownError(pt::ptree& responseTree_) +{ + ResponseError error; + error.code = ErrorCode::UnknownError; + responseTree_.put_child("error", error.createNode()); +} + +} // lsp +} // service +} // cc diff --git a/util/include/util/filesystem.h b/util/include/util/filesystem.h index 7454b16c5..66f6f6369 100644 --- a/util/include/util/filesystem.h +++ b/util/include/util/filesystem.h @@ -22,6 +22,19 @@ std::string binaryPathToInstallDir(const char* path); */ std::string findCurrentExecutableDir(); +/** + * @brief Determines if the given path is rooted under + * any of the given other paths. + * + * @param paths_ A list of canonical paths. + * @param path_ A canonical path to match against the given paths. + * @return True if any of the paths in paths_ is a prefix of path_, + * otherwise false. +*/ +bool isRootedUnderAnyOf( + const std::vector& paths_, + const std::string& path_); + } // namespace util } // namespace cc diff --git a/util/include/util/graph.h b/util/include/util/graph.h index af93a9921..c58ae5914 100644 --- a/util/include/util/graph.h +++ b/util/include/util/graph.h @@ -11,9 +11,9 @@ #include -namespace cc +namespace cc { -namespace util +namespace util { struct GraphPimpl; @@ -46,6 +46,8 @@ class Graph bool directed_ = true, bool strict_ = false); + Graph(Graph&& other) noexcept; + ~Graph(); /** @@ -246,7 +248,7 @@ class Graph std::unordered_set _ids; std::string _currentId; - GraphPimpl* _graphPimpl; + GraphPimpl* _graphPimpl = nullptr; bool _directed; bool _strict; diff --git a/util/src/filesystem.cpp b/util/src/filesystem.cpp index d18c16b8d..e459102af 100644 --- a/util/src/filesystem.cpp +++ b/util/src/filesystem.cpp @@ -64,5 +64,16 @@ std::string findCurrentExecutableDir() return fs::path(exePath).parent_path().string(); } +bool isRootedUnderAnyOf( + const std::vector& paths_, + const std::string& path_) +{ + auto it = paths_.begin(); + const auto end = paths_.end(); + while (it != end && path_.rfind(*it, 0) != 0) + ++it; + return it != end; +} + } // namespace util } // namespace cc diff --git a/util/src/graph.cpp b/util/src/graph.cpp index e26f4ff96..7d15c5936 100644 --- a/util/src/graph.cpp +++ b/util/src/graph.cpp @@ -13,6 +13,15 @@ Graph::Graph(const std::string name_, bool directed_, bool strict_) setAttribute("fontsize", "11"); } +Graph::Graph(Graph&& other) noexcept + : _ids(std::move(other._ids)), + _directed(other._directed), + _strict(other._strict), + _isSubgraph(other._isSubgraph) +{ + std::swap(this->_graphPimpl, other._graphPimpl); +} + Graph::~Graph() { delete _graphPimpl; diff --git a/webgui-new/package-lock.json b/webgui-new/package-lock.json index 72a381508..be8d12c26 100644 --- a/webgui-new/package-lock.json +++ b/webgui-new/package-lock.json @@ -51,7 +51,7 @@ "express": "^4.18.2", "http-proxy-middleware": "^3.0.0-beta.1", "ts-node": "^10.9.1", - "typescript": "^4.9.4" + "typescript": "^5.3.3" }, "engines": { "node": ">=18.17.0" @@ -247,9 +247,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -258,9 +258,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -271,9 +271,9 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.13.0.tgz", + "integrity": "sha512-SuDrho1klTINfbcMPnyro1ZxU9xJtwDMtb62R8TjL/tOl71IoOsvBo1a9x+hDvHhIzkTcJHy2VC+rmpGgYkRSw==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -331,9 +331,9 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.5.tgz", - "integrity": "sha512-PIEN3Ke1buPod2EHbJsoQwlbpkz30qGZKcnmH1eihq9+bPQx8gelauUwLYaY4vBOuBAuEhmpDLii4rj/uO0yMA==", + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -341,9 +341,9 @@ } }, "node_modules/@codemirror/state": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", - "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" }, "node_modules/@codemirror/theme-one-dark": { "version": "6.1.2", @@ -357,9 +357,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.1.tgz", - "integrity": "sha512-J2Xnn5lFYT1ZN/5ewEoMBCmLlL71lZ3mBdb7cUEuHhX2ESoSrNEucpsDXpX22EuTGm9LOgC9v4Z0wx+Ez8QmGA==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz", + "integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==", "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -464,9 +464,9 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", "dependencies": { "@emotion/memoize": "^0.8.1" } @@ -477,9 +477,9 @@ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { - "version": "11.11.3", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.3.tgz", - "integrity": "sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==", + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -609,9 +609,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -626,12 +626,12 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz", - "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.1" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react-dom": { @@ -685,9 +685,9 @@ "dev": true }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -773,18 +773,18 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.7.tgz", - "integrity": "sha512-AuF+Wo2Mp/edaO6vJnWjg+gj4tzEz5ChMZnAQpc22DXpSvM8ddgGcZvM7D7F99pIBoSv8ub+Iz0viL+yuGVmhg==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.12.tgz", + "integrity": "sha512-brRO+tMFLpGyjEYHrX97bzqeF6jZmKpqqe1rY0LyIHAwP6xRVzh++zSecOQorDOCaZJg4XkGT9xfD+RWOWxZBA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.7.tgz", - "integrity": "sha512-EDAc8TVJGIA/imAvR3u4nANl2W5h3QeHieu2gK7Ypez/nIA55p08tHjf8UrMXEpxCAvfZO6piY9S9uaxETdicA==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.12.tgz", + "integrity": "sha512-3BXiDlOd3AexZoEXa/VqpIpVIvosCzjLHsdMWzKMXbZdnBiJjmb9ECdqfjn5SpTClO49qvkKLhkTqdBH3fSFGw==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -848,19 +848,19 @@ } }, "node_modules/@mui/material": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.7.tgz", - "integrity": "sha512-l6+AiKZH3iOJmZCnlpel8ghYQe9Lq0BEuKP8fGj3g5xz4arO9GydqYAtLPMvuHKtArj8lJGNuT2yHYxmejincA==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.12.tgz", + "integrity": "sha512-vXJGg6KNKucsvbW6l7w9zafnpOp0CWc0Wx4mDykuABTpQ5QQBnZxP7+oB4yAS1hDZQ1WobbeIl0CjxK4EEahkA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.34", - "@mui/core-downloads-tracker": "^5.15.7", - "@mui/system": "^5.15.7", + "@mui/base": "5.0.0-beta.38", + "@mui/core-downloads-tracker": "^5.15.12", + "@mui/system": "^5.15.12", "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", + "@mui/utils": "^5.15.12", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1", "react-is": "^18.2.0", "react-transition-group": "^4.4.5" @@ -892,14 +892,14 @@ } }, "node_modules/@mui/material/node_modules/@mui/base": { - "version": "5.0.0-beta.34", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.34.tgz", - "integrity": "sha512-e2mbTGTtReD/y5RFwnhkl1Tgl3XwgJhY040IlfkTVaU9f5LWrVhEnpRsYXu3B1CtLrwiWs4cu7aMHV9yRd4jpw==", + "version": "5.0.0-beta.38", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.38.tgz", + "integrity": "sha512-AsjD6Y1X5A1qndxz8xCcR8LDqv31aiwlgWMPxFAX/kCKiIGKlK65yMeVZ62iQr/6LBz+9hSKLiD1i4TZdAHKcQ==", "dependencies": { "@babel/runtime": "^7.23.9", "@floating-ui/react-dom": "^2.0.8", "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", + "@mui/utils": "^5.15.12", "@popperjs/core": "^2.11.8", "clsx": "^2.1.0", "prop-types": "^15.8.1" @@ -931,12 +931,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.7.tgz", - "integrity": "sha512-bcEeeXm7GyQCQvN9dwo8htGv8/6tP05p0i02Z7GXm5EoDPlBcqTNGugsjNLoGq6B0SsdyanjJGw0Jw00o1yAOA==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.12.tgz", + "integrity": "sha512-cqoSo9sgA5HE+8vZClbLrq9EkyOnYysooepi5eKaKvJ41lReT2c5wOZAeDDM1+xknrMDos+0mT2zr3sZmUiRRA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.7", + "@mui/utils": "^5.15.12", "prop-types": "^15.8.1" }, "engines": { @@ -957,13 +957,13 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.7.tgz", - "integrity": "sha512-ixSdslOjK1kzdGcxqj7O3d14By/LPQ7EWknsViQ8RaeT863EAQemS+zvUJDTcOpkfJh6q6gPnYMIb2TJCs9eWA==", + "version": "5.15.11", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.11.tgz", + "integrity": "sha512-So21AhAngqo07ces4S/JpX5UaMU2RHXpEA6hNzI6IQjd/1usMPxpgK8wkGgTe3JKmC2KDmH8cvoycq5H3Ii7/w==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -988,17 +988,17 @@ } }, "node_modules/@mui/system": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.7.tgz", - "integrity": "sha512-9alZ4/dLxsTwUOdqakgzxiL5YW6ntqj0CfzWImgWnBMTZhgGcPsbYpBLniNkkk7/jptma4/bykWXHwju/ls/pg==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.12.tgz", + "integrity": "sha512-/pq+GO6yN3X7r3hAwFTrzkAh7K1bTF5r8IzS79B9eyKJg7v6B/t4/zZYMR6OT9qEPtwf6rYN2Utg1e6Z7F1OgQ==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.7", - "@mui/styled-engine": "^5.15.7", + "@mui/private-theming": "^5.15.12", + "@mui/styled-engine": "^5.15.11", "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", + "@mui/utils": "^5.15.12", "clsx": "^2.1.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -1048,9 +1048,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.7.tgz", - "integrity": "sha512-8qhsxQRNV6aEOjjSk6YQIYJxkF5klhj8oG1FEEU4z6HV78TjNqRxMP08QGcdsibEbez+nihAaz6vu83b4XqbAg==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.12.tgz", + "integrity": "sha512-8SDGCnO2DY9Yy+5bGzu00NZowSDtuyHP4H8gunhHGQoIlhlY2Z3w64wBzAOLpYw/ZhJNzksDTnS/i8qdJvxuow==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -1075,9 +1075,9 @@ } }, "node_modules/@next/env": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.0.tgz", - "integrity": "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw==" + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.3.tgz", + "integrity": "sha512-VhgXTvrgeBRxNPjyfBsDIMvgsKDxjlpw4IAUsHCX8Gjl1vtHUYRT3+xfQ/wwvLPDd/6kqfLqk9Pt4+7gysuCKQ==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.5.6", @@ -1109,9 +1109,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz", - "integrity": "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.3.tgz", + "integrity": "sha512-LALu0yIBPRiG9ANrD5ncB3pjpO0Gli9ZLhxdOu6ZUNf3x1r3ea1rd9Q+4xxUkGrUXLqKVK9/lDkpYIJaCJ6AHQ==", "cpu": [ "arm64" ], @@ -1124,9 +1124,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz", - "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.3.tgz", + "integrity": "sha512-E/9WQeXxkqw2dfcn5UcjApFgUq73jqNKaE5bysDm58hEUdUGedVrnRhblhJM7HbCZNhtVl0j+6TXsK0PuzXTCg==", "cpu": [ "x64" ], @@ -1139,9 +1139,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz", - "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.3.tgz", + "integrity": "sha512-USArX9B+3rZSXYLFvgy0NVWQgqh6LHWDmMt38O4lmiJNQcwazeI6xRvSsliDLKt+78KChVacNiwvOMbl6g6BBw==", "cpu": [ "arm64" ], @@ -1154,9 +1154,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz", - "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.3.tgz", + "integrity": "sha512-esk1RkRBLSIEp1qaQXv1+s6ZdYzuVCnDAZySpa62iFTMGTisCyNQmqyCTL9P+cLJ4N9FKCI3ojtSfsyPHJDQNw==", "cpu": [ "arm64" ], @@ -1169,9 +1169,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz", - "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.3.tgz", + "integrity": "sha512-8uOgRlYEYiKo0L8YGeS+3TudHVDWDjPVDUcST+z+dUzgBbTEwSSIaSgF/vkcC1T/iwl4QX9iuUyUdQEl0Kxalg==", "cpu": [ "x64" ], @@ -1184,9 +1184,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz", - "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.3.tgz", + "integrity": "sha512-DX2zqz05ziElLoxskgHasaJBREC5Y9TJcbR2LYqu4r7naff25B4iXkfXWfcp69uD75/0URmmoSgT8JclJtrBoQ==", "cpu": [ "x64" ], @@ -1199,9 +1199,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz", - "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.3.tgz", + "integrity": "sha512-HjssFsCdsD4GHstXSQxsi2l70F/5FsRTRQp8xNgmQs15SxUfUJRvSI9qKny/jLkY3gLgiCR3+6A7wzzK0DBlfA==", "cpu": [ "arm64" ], @@ -1214,9 +1214,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz", - "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.3.tgz", + "integrity": "sha512-DRuxD5axfDM1/Ue4VahwSxl1O5rn61hX8/sF0HY8y0iCbpqdxw3rB3QasdHn/LJ6Wb2y5DoWzXcz3L1Cr+Thrw==", "cpu": [ "ia32" ], @@ -1229,9 +1229,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz", - "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.3.tgz", + "integrity": "sha512-uC2DaDoWH7h1P/aJ4Fok3Xiw6P0Lo4ez7NbowW2VGNXw/Xv6tOuLUcxhBYZxsSUJtpeknCi8/fvnSpyCFp4Rcg==", "cpu": [ "x64" ], @@ -1288,11 +1288,11 @@ } }, "node_modules/@reactflow/background": { - "version": "11.3.8", - "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.8.tgz", - "integrity": "sha512-U4aI54F7PwqgYI0Knv72QFRI/wXeipPmIYAlDsA0j51+tlPxs3Nk2z7G1/4pC11GxEZkgQVfcIXro4l1Fk+bIQ==", + "version": "11.3.9", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.9.tgz", + "integrity": "sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -1302,11 +1302,11 @@ } }, "node_modules/@reactflow/controls": { - "version": "11.2.8", - "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.8.tgz", - "integrity": "sha512-Y9YVx38sRjYtbPsI/xa+B1FGN73FV1GqqajlmGfrc1TmqhJaX+gaMXMvVazT/N5haK1hMJvOApUTLQ2V/5Rdbg==", + "version": "11.2.9", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.9.tgz", + "integrity": "sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -1316,9 +1316,9 @@ } }, "node_modules/@reactflow/core": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.10.3.tgz", - "integrity": "sha512-nV3nep4fjBy3h8mYSnJcclGcQtj8fkUBmNkEwCZCK4ps+n3HNkXFB0BRisSnQz6GRQlYboSsi0cThEl3KdNITw==", + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.10.4.tgz", + "integrity": "sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==", "dependencies": { "@types/d3": "^7.4.0", "@types/d3-drag": "^3.0.1", @@ -1336,11 +1336,11 @@ } }, "node_modules/@reactflow/minimap": { - "version": "11.7.8", - "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.8.tgz", - "integrity": "sha512-MwyP5q3VomC91Dhd4P6YcxEfnjDbREGYV6rRxbSJSTHiG0x7ETQCcPelYDGy7JvQej77Pa2yJ4g0FDwP7CsQEA==", + "version": "11.7.9", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.9.tgz", + "integrity": "sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "@types/d3-selection": "^3.0.3", "@types/d3-zoom": "^3.0.1", "classcat": "^5.0.3", @@ -1354,11 +1354,11 @@ } }, "node_modules/@reactflow/node-resizer": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.8.tgz", - "integrity": "sha512-u/EXLpvOfAmq1sGoPYwoX4gi0PnCi0mH3eHVClHNc8JQD0WCqcV1UeVV7H3PF+1SGhhg/aOv/vPG1PcQ5fu4jQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.9.tgz", + "integrity": "sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.4", "d3-drag": "^3.0.0", "d3-selection": "^3.0.0", @@ -1370,11 +1370,11 @@ } }, "node_modules/@reactflow/node-toolbar": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.8.tgz", - "integrity": "sha512-cfvlTPeJa/ciQTosx2bGrjHT8K/UL9kznpvpOzeZFnJm5UQXmbwAYt4Vo6GfkD51mORcIL7ujQJvB9ym3ZI9KA==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.9.tgz", + "integrity": "sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -1585,9 +1585,9 @@ } }, "node_modules/@types/d3-path": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.2.tgz", - "integrity": "sha512-WAIEVlOCdd/NKRYTsqCpOMHQHemKBEINf8YXMYOtXH0GA7SY0dqMB78P3Uhgfy+4X+/Mlw2wDtlETkN6kQUCMA==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" }, "node_modules/@types/d3-polygon": { "version": "3.0.2", @@ -1740,9 +1740,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1774,9 +1774,9 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "version": "6.9.12", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", + "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==", "dev": true }, "node_modules/@types/range-parser": { @@ -1786,9 +1786,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.2.52", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.52.tgz", - "integrity": "sha512-E/YjWh3tH+qsLKaUzgpZb5AY0ChVa+ZJzF7ogehVILrFpdQk6nC/WXOv0bfFEABbXbgNxLBGU7IIZByPKb6eBw==", + "version": "18.2.64", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.64.tgz", + "integrity": "sha512-MlmPvHgjj2p3vZaxbQgFUQFvD8QiZwACfGqEdDSWou5yISWxDQ4/74nCAwsUiX7UFLKZz3BbVSPj+YxeoGGCfg==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -1796,9 +1796,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", - "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "version": "18.2.21", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.21.tgz", + "integrity": "sha512-gnvBA/21SA4xxqNXEwNiVcP0xSGHh/gi1VhWv9Bl46a0ItbTT5nFY+G9VSQpaG/8N/qdJpJ+vftQ4zflTtnjLw==", "dev": true, "dependencies": { "@types/react": "*" @@ -1818,9 +1818,9 @@ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { @@ -2044,9 +2044,9 @@ } }, "node_modules/@uiw/codemirror-extensions-basic-setup": { - "version": "4.21.21", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.21.tgz", - "integrity": "sha512-+0i9dPrRSa8Mf0CvyrMvnAhajnqwsP3IMRRlaHDRgsSGL8igc4z7MhvUPn+7cWFAAqWzQRhMdMSWzo6/TEa3EA==", + "version": "4.21.24", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.24.tgz", + "integrity": "sha512-TJYKlPxNAVJNclW1EGumhC7I02jpdMgBon4jZvb5Aju9+tUzS44IwORxUx8BD8ZtH2UHmYS+04rE3kLk/BtnCQ==", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -2070,20 +2070,20 @@ } }, "node_modules/@uiw/codemirror-theme-github": { - "version": "4.21.21", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.21.21.tgz", - "integrity": "sha512-msrpNrKk/CZQHk58TshI8aH7FpEyL404m/vWlGUdL2jGW7IRKm0nXn1lXXQ/snzk65h88GO6u9fiiv0pxRuZfQ==", + "version": "4.21.24", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.21.24.tgz", + "integrity": "sha512-BggG0qiLpg5j9ijY4DJDnANefLADKh8FseH28J1ljvwtnvlR1GGnO+RZzOl11gLpDqb2DUM5xIaxmbLcKWljUg==", "dependencies": { - "@uiw/codemirror-themes": "4.21.21" + "@uiw/codemirror-themes": "4.21.24" }, "funding": { "url": "https://jaywcjlove.github.io/#/sponsor" } }, "node_modules/@uiw/codemirror-themes": { - "version": "4.21.21", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.21.tgz", - "integrity": "sha512-ljVcMGdaxo75UaH+EqxJ+jLyMVVgeSfW2AKyT1VeLy+4SDpuqNQ7wq5XVxktsG6LH+OvgSFndWXgPANf4+gQcA==", + "version": "4.21.24", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.24.tgz", + "integrity": "sha512-InY24KWP8YArDBACWHKFZ6ZU+WCvRHf3ZB2cCVxMVN35P1ANUmRzpAP2ernZQ5OIriL1/A/kXgD0Zg3Y65PNgg==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -2099,15 +2099,15 @@ } }, "node_modules/@uiw/react-codemirror": { - "version": "4.21.21", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.21.tgz", - "integrity": "sha512-PaxBMarufMWoR0qc5zuvBSt76rJ9POm9qoOaJbqRmnNL2viaF+d+Paf2blPSlm1JSnqn7hlRjio+40nZJ9TKzw==", + "version": "4.21.24", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.24.tgz", + "integrity": "sha512-8zs5OuxbhikHocHBsVBMuW1vqlv4ccZAkt4rFwr7ebLP2Q6RwHsjpsR9GeGyAigAqonKRoeHugqF78UMrkaTgg==", "dependencies": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.21.21", + "@uiw/codemirror-extensions-basic-setup": "4.21.24", "codemirror": "^6.0.0" }, "funding": { @@ -2246,13 +2246,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2292,17 +2295,55 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz", + "integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2347,31 +2388,44 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.tosorted": { + "node_modules/array.prototype.toreversed": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", - "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -2402,10 +2456,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2432,9 +2489,9 @@ } }, "node_modules/b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" }, "node_modules/babel-plugin-macros": { "version": "3.1.0", @@ -2456,6 +2513,39 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bare-events": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", + "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.2.1.tgz", + "integrity": "sha512-+CjmZANQDFZWy4PGbVdmALIwmt33aJg8qTkVjClU6X4WmZkTPBDxRHiBn7fpqEWEfF3AC2io++erpViAIQbSjg==", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-os": "^2.0.0", + "bare-path": "^2.0.0", + "streamx": "^2.13.0" + } + }, + "node_modules/bare-os": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.0.tgz", + "integrity": "sha512-hD0rOPfYWOMpVirTACt4/nK8mC55La12K5fY1ij8HAdfQakD62M+H4o4tpfKzVGLgRDTuk3vjA4GqGXXCeFbag==", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz", + "integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==", + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2494,13 +2584,13 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -2508,7 +2598,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -2602,14 +2692,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2624,9 +2719,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001583", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz", - "integrity": "sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==", + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", "funding": [ { "type": "opencollective", @@ -2659,15 +2754,9 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2680,6 +2769,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -3103,17 +3195,20 @@ "dev": true }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -3170,17 +3265,17 @@ } }, "node_modules/devicons-react": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/devicons-react/-/devicons-react-1.2.6.tgz", - "integrity": "sha512-C9mnEcT13HLiVOKk+xeO1jDJ5LPFv3xE13yvtrxaJ9zpNIa91xVUORkqK12GTyvSP8R4RhU0woBpFjRxNUVEKA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/devicons-react/-/devicons-react-1.3.0.tgz", + "integrity": "sha512-uNrT0+t19A9iAxIidx1kj1rNF12TOh0cZ3A/JxrLuk19YBqo/M0TaMggwoaibLjNVP/VT+9nxGyYKbKAg0bgWA==", "peerDependencies": { "react": "*" } }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "engines": { "node": ">=0.3.1" } @@ -3219,15 +3314,15 @@ } }, "node_modules/dotenv": { - "version": "16.4.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", - "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/ee-first": { @@ -3260,9 +3355,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", + "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -3281,50 +3376,52 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.8", "string.prototype.trimend": "^1.0.7", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -3333,37 +3430,68 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", - "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", + "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", "dev": true, "dependencies": { "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.1", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", + "es-abstract": "^1.22.4", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", + "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.0.1" + "safe-array-concat": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -3413,16 +3541,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -3539,9 +3667,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -3656,27 +3784,29 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "version": "7.34.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.0.tgz", + "integrity": "sha512-MeVXdReleBTdkz/bvcQMSnCXGi+c9kvy51IpinjnJgutl3YTHWsDdke7Z1ufZpGfDG8xduBDKyjtB9JH1eBKIQ==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", + "es-iterator-helpers": "^1.0.17", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", + "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" + "string.prototype.matchall": "^4.0.10" }, "engines": { "node": ">=4" @@ -3867,14 +3997,14 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -3983,9 +4113,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4083,9 +4213,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/follow-redirects": { @@ -4209,28 +4339,33 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -4240,9 +4375,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -4388,21 +4523,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -4439,9 +4574,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dependencies": { "function-bind": "^1.1.2" }, @@ -4518,9 +4653,9 @@ } }, "node_modules/i18next": { - "version": "23.8.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.8.2.tgz", - "integrity": "sha512-Z84zyEangrlERm0ZugVy4bIt485e/H8VecGUZkZWrH7BDePG6jT73QdL9EA1tRTTVVMpry/MgWIP1FjEn0DRXA==", + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", "funding": [ { "type": "individual", @@ -4629,12 +4764,12 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -4828,9 +4963,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -4909,12 +5044,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5377,11 +5515,11 @@ } }, "node_modules/next": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/next/-/next-14.1.0.tgz", - "integrity": "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.3.tgz", + "integrity": "sha512-oexgMV2MapI0UIWiXKkixF8J8ORxpy64OuJ/J9oVUmIthXOUCcuVEZX+dtpgq7wIfIqtBwQsKEDXejcjTsan9g==", "dependencies": { - "@next/env": "14.1.0", + "@next/env": "14.1.3", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -5396,15 +5534,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.1.0", - "@next/swc-darwin-x64": "14.1.0", - "@next/swc-linux-arm64-gnu": "14.1.0", - "@next/swc-linux-arm64-musl": "14.1.0", - "@next/swc-linux-x64-gnu": "14.1.0", - "@next/swc-linux-x64-musl": "14.1.0", - "@next/swc-win32-arm64-msvc": "14.1.0", - "@next/swc-win32-ia32-msvc": "14.1.0", - "@next/swc-win32-x64-msvc": "14.1.0" + "@next/swc-darwin-arm64": "14.1.3", + "@next/swc-darwin-x64": "14.1.3", + "@next/swc-linux-arm64-gnu": "14.1.3", + "@next/swc-linux-arm64-musl": "14.1.3", + "@next/swc-linux-x64-gnu": "14.1.3", + "@next/swc-linux-x64-musl": "14.1.3", + "@next/swc-win32-arm64-msvc": "14.1.3", + "@next/swc-win32-ia32-msvc": "14.1.3", + "@next/swc-win32-x64-msvc": "14.1.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -5422,9 +5560,9 @@ } }, "node_modules/node-abi": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.54.0.tgz", - "integrity": "sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", + "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", "dependencies": { "semver": "^7.3.5" }, @@ -5526,15 +5664,16 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" } }, "node_modules/object.hasown": { @@ -5733,6 +5872,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -5761,9 +5909,9 @@ } }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -5925,9 +6073,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -6042,46 +6190,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, - "node_modules/react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" - }, "node_modules/react-smooth": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.5.tgz", - "integrity": "sha512-BMP2Ad42tD60h0JW6BFaib+RJuV5dsXJK9Baxiv/HlNFjvRLqA9xrNKxVWnUIZPQfzUwGXIlU/dSYLU+54YGQA==", - "dependencies": { - "fast-equals": "^5.0.0", - "react-transition-group": "2.9.0" - }, - "peerDependencies": { - "prop-types": "^15.6.0", - "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-smooth/node_modules/dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, - "node_modules/react-smooth/node_modules/react-transition-group": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", - "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.0.tgz", + "integrity": "sha512-2NMXOBY1uVUQx1jBeENGA497HK20y6CPGYL1ZnJLeoQ8rrc3UfmOM82sRxtzpcoCkUMy4CS0RGylfuVhuFjBgg==", "dependencies": { - "dom-helpers": "^3.4.0", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2", - "react-lifecycles-compat": "^3.0.4" + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" }, "peerDependencies": { - "react": ">=15.0.0", - "react-dom": ">=15.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-toastify": { @@ -6112,9 +6232,9 @@ } }, "node_modules/react-zoom-pan-pinch": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.2.tgz", - "integrity": "sha512-Gg44aKCmfO4d19TmPaswwUeBtJkizR45YXxRd3MMK7FIINuSyqBF5/jDYPMZbMSjTvOI3v1p0FfKtebkTamP+w==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.3.tgz", + "integrity": "sha512-x5MFlfAx2D6NTpZu8OISqc2nYn4p+YEaM1p21w7S/VE1wbVzK8vRzTo9Bj1ydufa649MuP7JBRM3vvj1RftFZw==", "engines": { "node": ">=8", "npm": ">=5" @@ -6125,16 +6245,16 @@ } }, "node_modules/reactflow": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.10.3.tgz", - "integrity": "sha512-DGNrTdkWjZtPOhj5MV8fiWWGkJo+otMVdoJ9l67bQL+Xf+8NkJ4AHmRXoYIxtgcENzwTr5WTAIJlswV9i91cyw==", + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.10.4.tgz", + "integrity": "sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==", "dependencies": { - "@reactflow/background": "11.3.8", - "@reactflow/controls": "11.2.8", - "@reactflow/core": "11.10.3", - "@reactflow/minimap": "11.7.8", - "@reactflow/node-resizer": "2.2.8", - "@reactflow/node-toolbar": "1.3.8" + "@reactflow/background": "11.3.9", + "@reactflow/controls": "11.2.9", + "@reactflow/core": "11.10.4", + "@reactflow/minimap": "11.7.9", + "@reactflow/node-resizer": "2.2.9", + "@reactflow/node-toolbar": "1.3.9" }, "peerDependencies": { "react": ">=17", @@ -6166,15 +6286,15 @@ } }, "node_modules/recharts": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.11.0.tgz", - "integrity": "sha512-5s+u1m5Hwxb2nh0LABkE3TS/lFqFHyWl7FnPbQhHobbQQia4ih1t3o3+ikPYr31Ns+kYe4FASIthKeKi/YYvMg==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.2.tgz", + "integrity": "sha512-9bpxjXSF5g81YsKkTSlaX7mM4b6oYI1mIYck6YkUcWuL3tomADccI51/6thY4LmvhYuRTwpfrOvE80Zc3oBRfQ==", "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", - "lodash": "^4.17.19", + "lodash": "^4.17.21", "react-is": "^16.10.2", - "react-smooth": "^2.0.5", + "react-smooth": "^4.0.0", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" @@ -6183,7 +6303,6 @@ "node": ">=14" }, "peerDependencies": { - "prop-types": "^15.6.0", "react": "^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } @@ -6210,15 +6329,16 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/reflect.getprototypeof": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", - "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", + "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0", + "get-intrinsic": "^1.2.3", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" }, @@ -6235,14 +6355,15 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -6376,13 +6497,13 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", - "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, "engines": { @@ -6399,9 +6520,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", - "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -6423,9 +6544,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6497,14 +6618,15 @@ } }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dev": true, "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.1" }, @@ -6513,14 +6635,15 @@ } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6576,14 +6699,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6688,12 +6815,15 @@ } }, "node_modules/streamx": { - "version": "2.15.7", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.7.tgz", - "integrity": "sha512-NPEKS5+yjyo597eafGbKW5ujh7Sm6lDLHZQd/lRSz6S0VarpADBJItqfB4PnwpS+472oob1GX5cCY9vzfJpHUA==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", + "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" } }, "node_modules/string_decoder": { @@ -6803,9 +6933,9 @@ } }, "node_modules/style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" }, "node_modules/styled-jsx": { "version": "5.1.1", @@ -6867,13 +6997,16 @@ } }, "node_modules/tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.5.tgz", + "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "dependencies": { - "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" } }, "node_modules/tar-stream": { @@ -6908,9 +7041,9 @@ } }, "node_modules/tiny-invariant": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", - "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, "node_modules/to-fast-properties": { "version": "2.0.0", @@ -7079,29 +7212,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -7111,16 +7245,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -7130,30 +7265,36 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -7242,9 +7383,9 @@ } }, "node_modules/victory-vendor": { - "version": "36.8.6", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.8.6.tgz", - "integrity": "sha512-PH8Wj9b0xIZ4AVfyn0c1SJrOhtxDJ5PNxj1ZDABPg1Gw1vJr1mJVqESPhvsFj7mXLQohVdiKqp4kWZkXlPcRcA==", + "version": "36.9.1", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.1.tgz", + "integrity": "sha512-+pZIP+U3pEJdDCeFmsXwHzV7vNHQC/eIbHklfe2ZCZqayYRH7lQbHcVgsJ0XOOv27hWs4jH4MONgXxHMObTMSA==", "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", @@ -7414,9 +7555,9 @@ } }, "node_modules/zustand": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.0.tgz", - "integrity": "sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz", + "integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==", "dependencies": { "use-sync-external-store": "1.2.0" }, diff --git a/webgui-new/package.json b/webgui-new/package.json index e681d328d..c0dc2674d 100644 --- a/webgui-new/package.json +++ b/webgui-new/package.json @@ -26,7 +26,7 @@ "express": "^4.18.2", "http-proxy-middleware": "^3.0.0-beta.1", "ts-node": "^10.9.1", - "typescript": "^4.9.4" + "typescript": "^5.3.3" }, "dependencies": { "@codemirror/lang-cpp": "^6.0.2", diff --git a/webgui-new/src/components/codemirror-editor/codemirror-editor.tsx b/webgui-new/src/components/codemirror-editor/codemirror-editor.tsx index cb66a9c4b..4bcc0e928 100644 --- a/webgui-new/src/components/codemirror-editor/codemirror-editor.tsx +++ b/webgui-new/src/components/codemirror-editor/codemirror-editor.tsx @@ -1,9 +1,9 @@ -import ReactCodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror'; +import ReactCodeMirror, { Decoration, EditorView, ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { AccordionLabel } from 'enums/accordion-enum'; import { ThemeContext } from 'global-context/theme-context'; import React, { useContext, useRef, useState, useEffect, MouseEvent } from 'react'; -import { getCppAstNodeInfoByPosition } from 'service/cpp-service'; -import { FileInfo, Position, Range } from '@thrift-generated'; +import { getCppAstNodeInfoByPosition, getCppReferenceTypes, getCppReferences } from 'service/cpp-service'; +import { AstNodeInfo, FileInfo, Position, Range } from '@thrift-generated'; import { cpp } from '@codemirror/lang-cpp'; import { githubDark, githubLight } from '@uiw/codemirror-theme-github'; import { EditorContextMenu } from 'components/editor-context-menu/editor-context-menu'; @@ -20,6 +20,14 @@ import * as SC from './styled-components'; import { useTranslation } from 'react-i18next'; import { sendGAEvent } from 'utils/analytics'; +type HighlightPosition = { + startpos: {line: number, column: number} + endpos: {line: number, column: number} +} + +const HIGHLIGHT_FOR_DARK = 'rgba(187, 181, 255, 0.3)'; +const HIGHLIGHT_FOR_LIGHT = '#f0d8a8'; + export const CodeMirrorEditor = (): JSX.Element => { const { t } = useTranslation(); const router = useRouter(); @@ -34,6 +42,9 @@ export const CodeMirrorEditor = (): JSX.Element => { mouseX: number; mouseY: number; } | null>(null); + const [highlightRanges, setHighlightRanges] = useState([]); + const [visitedLastAstNode, setVisitedLastAstNode] = useState(null); + const [highlightColor, setHighlightColor] = useState(theme === 'dark' ? HIGHLIGHT_FOR_DARK : HIGHLIGHT_FOR_LIGHT); useEffect(() => { if (!appCtx.workspaceId) return; @@ -57,6 +68,59 @@ export const CodeMirrorEditor = (): JSX.Element => { dispatchSelection(convertSelectionStringToRange(appCtx.editorSelection)); }, [appCtx.editorSelection, fileContent]); + useEffect(() => { + setHighlightColor(theme === 'dark' ? HIGHLIGHT_FOR_DARK : HIGHLIGHT_FOR_LIGHT); + }, [theme]) + + useEffect(() => { + if(!editorRef.current || !editorRef.current.view) return; + setHighlightRanges([]); + }, [appCtx.workspaceId, fileInfo, fileContent]) + + const createHighlightDecoration = (view: EditorView, highlightPosition: HighlightPosition, highlightColor: string) => { + if (!editorRef.current || !editorRef.current.state || !editorRef.current.view) return; + + const startPos = highlightPosition.startpos as Position; + const endPos = highlightPosition.endpos as Position; + + const from = + view.state.doc.line(startPos.line as number).from + + (startPos.column as number) - + 1; + const to = + view.state.doc.line(endPos.line as number).from + (endPos.column as number) - 1; + + return Decoration.mark({ + attributes: { style: `background-color:${highlightColor}` }, + }).range(from, to); + }; + + const highlightExtension = () => {return EditorView.decorations.of((view) => { + const decorations = highlightRanges.map((pos) => createHighlightDecoration(view, pos, highlightColor)) as never; + return Decoration.set(decorations, true); + })} + + const updateHighlights = async (astNode : AstNodeInfo) => { + const refTypes = await getCppReferenceTypes(astNode.id as string) + if(visitedLastAstNode?.id !== astNode.id){ + const allReferences = await getCppReferences(astNode.id as string, refTypes.get('Usage') as number, []); + const referencesInFile = allReferences.filter(ref => ref.range?.file === fileInfo?.id); + setHighlightRanges(referencesInFile.map(nodeInfo => { + const startpos = nodeInfo?.range?.range?.startpos as { line: number, column: number }; + const endpos = nodeInfo?.range?.range?.endpos as { line: number, column: number }; + return { + startpos: { line: startpos.line, column: startpos.column }, + endpos: { line: endpos.line, column: endpos.column } + }; + })); + setVisitedLastAstNode(astNode); + + }else{ + setHighlightRanges([]); + setVisitedLastAstNode(null); + } + } + const dispatchSelection = (range: Range) => { if (!range || !range.startpos || !range.endpos) return; @@ -117,12 +181,14 @@ export const CodeMirrorEditor = (): JSX.Element => { event_category: appCtx.workspaceId, event_label: `${fileInfo?.name}: ${astNodeInfo.astNodeValue}`, }); - dispatchSelection(astNodeInfo?.range?.range as Range); + const nodeRange = astNodeInfo?.range?.range as Range; + await updateHighlights(astNodeInfo); + dispatchSelection(nodeRange); router.push({ pathname: '/project', query: { ...router.query, - editorSelection: convertSelectionRangeToString(astNodeInfo?.range?.range), + editorSelection: convertSelectionRangeToString(nodeRange), languageNodeId: astNodeInfo?.id as string, activeAccordion: AccordionLabel.INFO_TREE, } as RouterQueryType, @@ -143,6 +209,8 @@ export const CodeMirrorEditor = (): JSX.Element => { event_category: appCtx.workspaceId, event_label: `${fileInfo?.name}: ${convertSelectionRangeToString(range)}`, }); + setHighlightRanges([]); + setVisitedLastAstNode(null); dispatchSelection(range); router.push({ pathname: '/project', @@ -250,8 +318,13 @@ export const CodeMirrorEditor = (): JSX.Element => { { gitBlameContainer.scrollTop = cmScroller.scrollTop; }); }} + onChange={(_, update) => { + editorRef.current = { view: update.view, state: update.state }; + }} onClick={() => handleAstNodeSelect()} onContextMenu={(e) => handleContextMenu(e)} /> diff --git a/webserver/include/webserver/lsphandler.h b/webserver/include/webserver/lsphandler.h new file mode 100644 index 000000000..77bb6a467 --- /dev/null +++ b/webserver/include/webserver/lsphandler.h @@ -0,0 +1,350 @@ +#ifndef CC_WEBSERVER_LSPHANDLER_H +#define CC_WEBSERVER_LSPHANDLER_H + +#include +#include + +#include +#include + +#include +#include + +namespace cc +{ +namespace webserver +{ + +namespace pt = boost::property_tree; + +/** + * Support methods of the Language Server Protocol. + */ +enum class LspMethod +{ + Unknown = 0, + Signature, + Definition, + Declaration, + Implementation, + References, + DiagramTypes, + Diagram, + ModuleDiagram, + Parameters, + LocalVariables, + Overridden, + Overriders, + Read, + Write, + Methods, + Friends, + EnumConstants, + Expansion, + Undefinition, + ThisCalls, + CallsOfThis, + Callee, + Caller, + VirtualCall, + FunctionPointerCall, + Alias, + Implements, + DataMember, + UnderlyingType, +}; + +template +class LspHandler : public RequestHandler +{ +public: + std::string key() const override + { + return "LspHandler"; + } + + LspHandler(std::unique_ptr&& service_) + : lspService(std::move(service_)) + { + } + + LspHandler(LspServiceT *service_) : lspService(service_) + { + } + + int beginRequest(struct mg_connection *conn_) override + { + try + { + std::string request = getContent(conn_); + LOG(debug) << "[LSP] Request content:\n" << request; + + pt::ptree responseTree; + responseTree.put("jsonrpc", "2.0"); + + try + { + pt::ptree requestTree; + std::stringstream requestStream(request); + pt::read_json(requestStream, requestTree); + + std::string requestId = requestTree.get("id"); + responseTree.put("id", requestId); + + std::string method = requestTree.get("method"); + pt::ptree& params = requestTree.get_child("params"); + + switch (parseMethod(method)) + { + case LspMethod::Signature: + { + lspService->getSignature(responseTree, params); + break; + } + case LspMethod::Definition: + { + lspService->getDefinition(responseTree, params); + break; + } + case LspMethod::Declaration: + { + lspService->getDeclaration(responseTree, params); + break; + } + case LspMethod::Implementation: + { + lspService->getImplementation(responseTree, params); + break; + } + case LspMethod::References: + { + lspService->getReferences(responseTree, params); + break; + } + case LspMethod::DiagramTypes: + { + lspService->getDiagramTypes(responseTree, params); + break; + } + case LspMethod::Diagram: + { + lspService->getDiagram(responseTree, params); + break; + } + case LspMethod::ModuleDiagram: + { + lspService->getModuleDiagram(responseTree, params); + break; + } + case LspMethod::Parameters: + { + lspService->getParameters(responseTree, params); + break; + } + case LspMethod::LocalVariables: + { + lspService->getLocalVariables(responseTree, params); + break; + } + case LspMethod::Overridden: + { + lspService->getOverridden(responseTree, params); + break; + } + case LspMethod::Overriders: + { + lspService->getOverrider(responseTree, params); + break; + } + case LspMethod::Read: + { + lspService->getRead(responseTree, params); + break; + } + case LspMethod::Write: + { + lspService->getWrite(responseTree, params); + break; + } + case LspMethod::Methods: + { + lspService->getMethods(responseTree, params); + break; + } + case LspMethod::Friends: + { + lspService->getFriends(responseTree, params); + break; + } + case LspMethod::EnumConstants: + { + lspService->getEnumConstants(responseTree, params); + break; + } + case LspMethod::Expansion: + { + lspService->getExpansion(responseTree, params); + break; + } + case LspMethod::Undefinition: + { + lspService->getUndefinition(responseTree, params); + break; + } + case LspMethod::ThisCalls: + { + lspService->getThisCalls(responseTree, params); + break; + } + case LspMethod:: CallsOfThis: + { + lspService->getCallsOfThis(responseTree, params); + break; + } + case LspMethod::Callee: + { + lspService->getCallee(responseTree, params); + break; + } + case LspMethod::Caller: + { + lspService->getCaller(responseTree, params); + break; + } + case LspMethod::VirtualCall: + { + lspService->getVirtualCall(responseTree, params); + break; + } + case LspMethod::FunctionPointerCall: + { + lspService->getFunctionPointerCall(responseTree, params); + break; + } + case LspMethod::Alias: + { + lspService->getAlias(responseTree, params); + break; + } + case LspMethod::Implements: + { + lspService->getImplements(responseTree, params); + break; + } + case LspMethod::DataMember: + { + lspService->getDataMember(responseTree, params); + break; + } + case LspMethod::UnderlyingType: + { + lspService->getUnderlyingType(responseTree, params); + break; + } + default: + { + LOG(warning) << "[LSP] Unsupported method: '" << method << "'"; + lspService->getMethodNotFound(responseTree, method); + } + } + } + catch (const pt::ptree_error& ex) + { + LOG(warning) << ex.what(); + lspService->getParseError(responseTree, ex); + } + catch (const std::exception& ex) + { + LOG(warning) << ex.what(); + lspService->getInternalError(responseTree, ex); + } + catch (...) + { + LOG(warning) << "Unknown exception has been caught"; + lspService->getUnknownError(responseTree); + } + + std::stringstream responseStream; + pt::write_json(responseStream, responseTree); + std::string response = responseStream.str(); + + LOG(debug) << "[LSP] Response content:\n" << response << std::endl; + + // Send HTTP reply to the client create headers + mg_send_header(conn_, "Content-Type", "application/json"); + mg_send_header( + conn_, "Content-Length", std::to_string(response.length()).c_str()); + + // Terminate headers + mg_write(conn_, "\r\n", 2); + + // Send content + mg_write(conn_, response.c_str(), response.length()); + } + catch (const std::exception& ex) + { + LOG(warning) << ex.what(); + } + catch (...) + { + LOG(warning) << "Unknown exception has been caught"; + } + + // Returning non-zero tells mongoose that our function has replied to + // the client, and mongoose should not send client any more data. + return MG_TRUE; + } + +private: + inline std::string getContent(mg_connection* conn_) + { + return std::string(conn_->content, conn_->content + conn_->content_len); + } + + LspMethod parseMethod(const std::string& method) const + { + const static std::unordered_map methodMap = { + { "textDocument/signature", LspMethod::Signature }, + { "textDocument/definition", LspMethod::Definition }, + { "textDocument/declaration", LspMethod::Declaration }, + { "textDocument/implementation", LspMethod::Implementation }, + { "textDocument/references", LspMethod::References }, + { "textDocument/diagramTypes", LspMethod::DiagramTypes }, + { "textDocument/diagram", LspMethod::Diagram}, + { "directory/diagram", LspMethod::ModuleDiagram}, + { "textDocument/parameters", LspMethod::Parameters}, + { "textDocument/localVariables", LspMethod::LocalVariables}, + { "textDocument/overridden", LspMethod::Overridden}, + { "textDocument/overriders", LspMethod::Overriders}, + { "textDocument/read", LspMethod::Read}, + { "textDocument/write", LspMethod::Write}, + { "textDocument/methods", LspMethod::Methods}, + { "textDocument/friends", LspMethod::Friends}, + { "textDocument/enumConstants", LspMethod::EnumConstants}, + { "textDocument/expansion", LspMethod::Expansion}, + { "textDocument/undefinition", LspMethod::Undefinition}, + { "textDocument/thisCalls", LspMethod::ThisCalls}, + { "textDocument/callsOfThis", LspMethod::CallsOfThis}, + { "textDocument/callee", LspMethod::Callee}, + { "textDocument/caller", LspMethod::Caller}, + { "textDocument/virtualCall", LspMethod::VirtualCall}, + { "textDocument/functionPointerCall", LspMethod::FunctionPointerCall}, + { "textDocument/alias", LspMethod::Alias}, + { "textDocument/implements", LspMethod::Implements}, + { "textDocument/dataMember", LspMethod::DataMember}, + { "textDocument/underlyingType", LspMethod::UnderlyingType}, + }; + + auto it = methodMap.find(method); + if (it != methodMap.end()) + return it->second; + return LspMethod::Unknown; + } + + std::unique_ptr lspService; +}; + +} // webserver +} // cc + +#endif diff --git a/webserver/include/webserver/pluginhelper.h b/webserver/include/webserver/pluginhelper.h index 4096c45f5..3807ed363 100644 --- a/webserver/include/webserver/pluginhelper.h +++ b/webserver/include/webserver/pluginhelper.h @@ -15,8 +15,8 @@ #include #include -#include "requesthandler.h" #include "thrifthandler.h" +#include "lsphandler.h" namespace cc { @@ -31,7 +31,6 @@ inline void registerPluginSimple( const std::string& serviceName_) { namespace fs = boost::filesystem; - namespace po = boost::program_options; namespace pt = boost::property_tree; for (fs::directory_iterator it(ctx_.options["workspace"].as()); @@ -115,6 +114,16 @@ inline void registerPluginSimple( db_, datadir_, ctx_)); \ } +#define CODECOMPASS_LSP_SERVICE_FACTORY_WITH_CFG(serviceName, nspace) \ + [](std::shared_ptr& db_, \ + std::shared_ptr datadir_, \ + const cc::webserver::ServerContext& ctx_) { \ + return new cc::webserver::LspHandler< \ + cc::service::nspace::serviceName##LspServiceHandler>( \ + new cc::service::nspace::serviceName##LspServiceHandler( \ + db_, datadir_, ctx_)); \ + } + #define CODECOMPASS_LANGUAGE_SERVICE_FACTORY_WITH_CFG(serviceName) \ [](std::shared_ptr& db_, \ std::shared_ptr datadir_, \ diff --git a/webserver/include/webserver/thrifthandler.h b/webserver/include/webserver/thrifthandler.h index 173e850db..a91b96fdb 100644 --- a/webserver/include/webserver/thrifthandler.h +++ b/webserver/include/webserver/thrifthandler.h @@ -10,6 +10,7 @@ #include #include +#include #include "mongoose.h"