diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5aaba19b..c793cda1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,20 +5,17 @@ on: required: true type: string description: "yarn workspace name" - command: + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: required: true - type: string - description: "yarn command to run" workflow_dispatch: inputs: workspace: required: true type: string description: "yarn workspace name" - command: - required: true - type: string - description: "yarn command to run" jobs: build: @@ -50,42 +47,13 @@ jobs: - os: macos-11 target: aarch64-apple-darwin code-target: darwin-arm64 - runs-on: ${{ matrix.os }} - #container: ${{ matrix.container }} - - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - - - name: Setup yarn - id: setup-yarn - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn set version stable - yarn -v - - - name: Setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - override: true - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - - run: yarn workspace ${{ inputs.workspace }} run ${{ inputs.command }} - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} + uses: ./.github/workflows/execute-yarn-workspace-command.yml + with: + workspace: ${{ inputs.workspace }} + command: build + os: ${{ matrix.os }} + target: ${{ matrix.target }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.github/workflows/cd-auto.yml b/.github/workflows/cd-auto.yml new file mode 100644 index 00000000..05ffb2f2 --- /dev/null +++ b/.github/workflows/cd-auto.yml @@ -0,0 +1,74 @@ +name: Auto CD + +on: + workflow_call: + + +jobs: + find-last-commit: + runs-on: ubuntu-latest + outputs: + commit: ${{ steps.last-commit.outputs.commit }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Get Last Commit + id: last-commit + run: echo "commit=$(git log --oneline HEAD~1 -1 --format=format:%H)" >> $GITHUB_OUTPUT + + setup: + needs: find-last-commit + uses: ./.github/workflows/detect-workspace-changes.yml + with: + from: ${{ github.sha }} + since: ${{ needs.find-last-commit.outputs.commit }} + + publish-libraries: + if : ${{ needs.setup.outputs.libraries != '[]' && github.ref_name == 'main' }} + needs: setup + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.libraries)}} + uses: ./.github/workflows/publish-library.yml + with: + workspace: ${{ matrix.workspace.name }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + + + publish-core: + if: ${{ needs.setup.outputs.extensions != '[]' && github.ref_name == 'main' }} + needs: + - setup + - publish-libraries + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.extensions)}} + uses: ./.github/workflows/publish-core.yml + with: + workspace: ${{ matrix.workspace.name }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + publish-extensions: + if : ${{ needs.setup.outputs.extensions != '[]' }} + needs: + - setup + - publish-libraries + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.extensions)}} + uses: ./.github/workflows/publish-extension-auto.yml + with: + workspace: ${{ matrix.workspace.name }} + pre-release: ${{ github.ref_name != 'main' }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.github/workflows/cd-manual.yml b/.github/workflows/cd-manual.yml new file mode 100644 index 00000000..fc2a4e34 --- /dev/null +++ b/.github/workflows/cd-manual.yml @@ -0,0 +1,68 @@ +name: Manual CD + +on: + workflow_dispatch: + inputs: + from: + description: 'From commit' + required: true + type: string + since: + description: 'Since commit' + required: true + type: string + +jobs: + setup: + uses: ./.github/workflows/detect-workspace-changes.yml + with: + from: ${{ github.sha }} + since: ${{ inputs.since }} + + publish-libraries: + if : ${{ needs.setup.outputs.libraries != '[]' && github.ref_name == 'main' }} + needs: setup + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.libraries)}} + uses: ./.github/workflows/publish-library.yml + with: + workspace: ${{ matrix.workspace.name }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + + + publish-core: + if: ${{ needs.setup.outputs.extensions != '[]' && github.ref_name == 'main' }} + needs: + - setup + - publish-libraries + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.extensions)}} + uses: ./.github/workflows/publish-core.yml + with: + workspace: ${{ matrix.workspace.name }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + publish-extensions: + if : ${{ needs.setup.outputs.extensions != '[]' }} + needs: + - setup + - publish-libraries + strategy: + fail-fast: false + matrix: + workspace: ${{ fromJson(needs.setup.outputs.extensions)}} + uses: ./.github/workflows/publish-extension-auto.yml + with: + workspace: ${{ matrix.workspace.name }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml deleted file mode 100644 index 9fd553ad..00000000 --- a/.github/workflows/cd.yml +++ /dev/null @@ -1,211 +0,0 @@ -name: Tag and publish - -on: - push: - branches: - - main - - dev - workflow_dispatch: - -jobs: - find-last-commit: - runs-on: ubuntu-latest - outputs: - commit: ${{ steps.last-commit.outputs.commit }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Get Last Commit - id: last-commit - run: echo "commit=$(git log --oneline HEAD~1 -1 --format=format:%H)" >> $GITHUB_OUTPUT - - setup: - needs: find-last-commit - uses: ./.github/workflows/detect-workspace-changes.yml - with: - from: ${{ github.sha }} - since: ${{ needs.find-last-commit.outputs.commit }} - - publish-libraries: - if : ${{ needs.setup.outputs.libraries != '[]' }} - runs-on: ubuntu-latest - continue-on-error: true - needs: setup - strategy: - fail-fast: false - matrix: - workspace: ${{ fromJson(needs.setup.outputs.libraries)}} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: '18.16.1' - - - id: setup-yarn - # Install yarn 3 & workspace-tools - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn -v - - - name: Install dependencies - run: | - yarn install --immutable - - - name: Build - run: | - yarn workspace ${{ matrix.workspace.name }} build - - - name: Publish - run: yarn workspace ${{ matrix.workspace.name }} run publish - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - - compute-version: - if : ${{ needs.setup.outputs.extensions != '[]' }} - strategy: - fail-fast: false - matrix: - workspace: ${{ fromJson(needs.setup.outputs.extensions)}} - runs-on: ubuntu-latest - needs: - - setup - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - uses: actions/setup-node@v3 - with: - node-version: '18.16.1' - - - id: setup-yarn - # Install yarn 3 & workspace-tools - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn -v - - - name: Get workspace path - id: workspace-path - run: | - echo "workspace-path=$(yarn workspaces info ${{ matrix.workspace.name }} --json | jq -r '.data[0].location')" >> $GITHUB_OUTPUT - - - name: Check .unstable - id: check-unstable - run: | - cd ${{ steps.workspace-path.outputs.workspace-path }} - if [ -f ".unstable" ]; then - echo "is-unstable=true" >> $GITHUB_OUTPUT - else - echo "is-unstable=false" >> $GITHUB_OUTPUT - fi - - - name: Get tag prefix - id: get-tag-prefix - uses: actions/github-script@v6 - with: - result-encoding: string - script: | - const workspace = "${{ matrix.workspace.name }}"; - const language = workspace.split('-')[1]; - return language; - - - uses: paulhatch/semantic-version@d43966692519e4a5d4423b3da1b4b903c58c8f6b - id: find-new-version - with: - # The prefix to use to identify tags - tag_prefix: "${{ steps.get-tag-prefix.outputs.result }}-" - # A string which, if present in a git commit, indicates that a change represents a - # major (breaking) change, supports regular expressions wrapped with '/' - major_pattern: "!:" - # Same as above except indicating a minor change, supports regular expressions wrapped with '/' - minor_pattern: "/feat\\(?/" - # A string to determine the format of the version output - version_format: "${major}.${minor}.${patch}" - # If this is set to true, *every* commit will be treated as a new version. - bump_each_commit: false - # If true, the body of commits will also be searched for major/minor patterns to determine the version type. - search_commit_body: false - # Prevents pre-v1.0.0 version from automatically incrementing the major version. - # If enabled, when the major version is 0, major releases will be treated as minor and minor as patch. Note that the version_type output is unchanged. - enable_prerelease_mode: ${{ steps.check-unstable.outputs.is-unstable }} - - - name: Normalize version - uses: actions/github-script@v6 - id: tag - with: - result-encoding: string - script: | - const fs = require('fs') - console.log("Change type is : ", "${{ steps.find-new-version.outputs.version_type}}") - if (fs.existsSync('.unstable') && "${{ steps.find-new-version.outputs.version_type}}" == "patch") { - const patch = parseInt('${{steps.find-new-version.outputs.patch}}', 10); - return "${{steps.find-new-version.outputs.major}}.${{steps.find-new-version.outputs.minor}}." + (patch + 1).toString(); - } else - return "${{steps.find-new-version.outputs.major}}.${{steps.find-new-version.outputs.minor}}.${{steps.find-new-version.outputs.patch}}" - - - name: Set tag - run: | - git tag "${{ steps.get-tag-prefix.outputs.result }}-${{ steps.tag.outputs.result }}" - git push origin "${{ steps.get-tag-prefix.outputs.result }}-${{ steps.tag.outputs.result }}" - - publish-core: - if: ${{ needs.setup.outputs.extensions != '[]' }} - needs: - - setup - - publish-libraries - - compute-version - strategy: - fail-fast: false - matrix: - workspace: ${{ fromJson(needs.setup.outputs.extensions)}} - runs-on: ubuntu-latest - continue-on-error: true - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: '18.16.1' - - - id: setup-yarn - # Install yarn 3 & workspace-tools - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn -v - - - name: Install dependencies - run: | - yarn install --immutable - - - name: Build - run: | - yarn workspace ${{ matrix.workspace.name }} core:build - - - name: Publish - run: yarn workspace ${{ matrix.workspace.name }} run core:publish - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - - publish-extensions: - if : ${{ needs.setup.outputs.extensions != '[]' }} - needs: - - setup - - publish-libraries - - compute-version - strategy: - fail-fast: false - matrix: - workspace: ${{ fromJson(needs.setup.outputs.extensions)}} - uses: ./.github/workflows/publish-extension.yml - with: - workspace: ${{ matrix.workspace.name }} - secrets: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9b241c3..0ae2e8bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: lint: runs-on: ubuntu-latest needs: flatten-deps + if: ${{ needs.flatten-deps.outputs.dependencies != '[]' }} strategy: fail-fast: false matrix: @@ -62,7 +63,7 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - - run: yarn install --frozen-lockfile + - run: yarn install --immutable if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn workspace ${{ matrix.workspace.name }} run lint @@ -73,6 +74,7 @@ jobs: format: runs-on: ubuntu-latest needs: flatten-deps + if: ${{ needs.flatten-deps.outputs.dependencies != '[]' }} strategy: fail-fast: false matrix: @@ -97,13 +99,14 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - - run: yarn install --frozen-lockfile + - run: yarn install --immutable if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn workspace ${{ matrix.workspace.name }} run format build: needs: flatten-deps + if: ${{ needs.flatten-deps.outputs.dependencies != '[]' }} strategy: fail-fast: false matrix: @@ -111,11 +114,14 @@ jobs: uses: ./.github/workflows/build.yml with: workspace: ${{ matrix.workspace.name }} - command: build + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} test: needs: flatten-deps + if: ${{ needs.flatten-deps.outputs.dependencies != '[]' }} strategy: fail-fast: false matrix: @@ -123,4 +129,6 @@ jobs: uses: ./.github/workflows/test.yml with: workspace: ${{ matrix.workspace.name }} - command: test \ No newline at end of file + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.github/workflows/compute-version.yml b/.github/workflows/compute-version.yml new file mode 100644 index 00000000..31d57f19 --- /dev/null +++ b/.github/workflows/compute-version.yml @@ -0,0 +1,171 @@ +name: Compute version + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + compute-version: + required: false + type: boolean + description: | + Whether to compute a new version if the version already exists o the marketplace. + outputs: + version: + description: | + The version to publish the extension with. + value: ${{ jobs.compute-version.outputs.result }} + workflow_dispatch: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + compute-version: + required: false + type: boolean + description: | + Whether to compute a new version if the version already exists o the marketplace. + +jobs: + compute-version: + outputs: + result: ${{ steps.normalize-version.outputs.result }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Setup yarn + id: setup-yarn + run: | + corepack enable + corepack prepare yarn@stable --activate + yarn set version stable + yarn -v + + + + + - name: Get tag prefix + id: get-language + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const workspace = '${{ inputs.workspace }}'; + const language = workspace.split('-')[1]; + return language; + + - name: Get tag prefix + id: get-tag-prefix + run: | + echo "result=${{ steps.get-language.outputs.result }}-" >> $GITHUB_OUTPUT + + - name: Retrieve tag version + id: retrieve-version + uses: "WyriHaximus/github-action-get-previous-tag@v1" + with: + prefix: ${{ steps.get-tag-prefix.outputs.result }} + + - name: Extract tag semver + uses: actions/github-script@v6 + id: tag + with: + result-encoding: string + script: | + const tag = '${{ steps.retrieve-version.outputs.tag }}'; + const semver = tag.split('-')[1]; + return semver; + + - name: Get workspace path + id: workspace-path + run: | + echo workspace-path=$(yarn workspaces list --json | jq -r 'select(.name == "${{ inputs.workspace }}") | .location') >> $GITHUB_OUTPUT + + - name: Extract package.json version + id: package-version + run: | + ls + echo "version=$(jq -r '.version' '${{steps.workspace-path.outputs.workspace-path}}/package.json')" >> $GITHUB_OUTPUT + + - name: Extension id + id: extension-id + run: echo "id=osmiumtoolchains.osmium-${{ steps.get-language.outputs.result}}-extension" >> $GITHUB_OUTPUT + + # Request the marketplace api for the latest version + - name: Get latest version from marketplace + id: get-marketplace-version + uses: fjogeleit/http-request-action@v1 + with: + url: 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery' + method: 'POST' + customHeaders: '{"Content-Type": "application/json", "Accept": "application/json;api-version=6.0-preview.1"}' + data: '{ + "filters": [ + { + "criteria": [ + { + "filterType": 8, + "value": "Microsoft.VisualStudio.Code" + }, + { + "filterType": 10, + "value": "${{ steps.extension-id.outputs.id }}" + } + ], + "pageNumber": 1, + "pageSize": 100, + "sortBy": 0, + "sortOrder": 0 + } + ], + "assetTypes": [], + "flags": 0 + }' + + - name: Extract marketplace version + id: marketplace-version + uses: actions/github-script@v6 + with: + result-encoding: string + script: | + const response = JSON.parse('${{ steps.get-marketplace-version.outputs.response }}'); + const version = response.results[0].extensions[0].versions[0].version; + return version; + + - name: Normalize version + id: normalize-version + uses: "actions/github-script@v6" + with: + script: | + const packageVersion = '${{ steps.package-version.outputs.version }}'; + const marketplaceVersion = '${{ steps.marketplace-version.outputs.result }}'; + const tag = '${{ steps.tag.outputs.result }}'; + + if (${{inputs.compute-version}}) { + if (packageVersion === marketplaceVersion && packageVersion === tag) { + return packageVersion.split('.').map((v, i) => i === 2 ? parseInt(v) + 1 : v).join('.'); + } else if (packageVersion !== marketplaceVersion) { + return packageVersion; + } else { + return packageVersion.split('.').map((v, i) => i === 2 ? parseInt(v) + 1 : v).join('.'); + } + } else { + return packageVersion; + } + + - name: Debug + run: | + echo "package-version=${{ steps.package-version.outputs.version }}" + echo "marketplace-version=${{ steps.marketplace-version.outputs.result }}" + echo "tag=${{ steps.tag.outputs.result }}" + echo "result=${{ steps.normalize-version.outputs.result }}" + +# tr command to remove " in stirng diff --git a/.github/workflows/create-branch-and-draft.yml b/.github/workflows/create-branch-and-draft.yml index bfe5afa1..0aae356c 100644 --- a/.github/workflows/create-branch-and-draft.yml +++ b/.github/workflows/create-branch-and-draft.yml @@ -53,7 +53,6 @@ jobs: REMOVE_UUID: ${{ steps.generate-uuid.outputs.uuid }} - name: Create pull request - if: steps.check-pr-exists.outputs.result.prExists != 'true' continue-on-error: true env: GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/detect-workspace-changes.yml b/.github/workflows/detect-workspace-changes.yml index 3234f164..ef70d545 100644 --- a/.github/workflows/detect-workspace-changes.yml +++ b/.github/workflows/detect-workspace-changes.yml @@ -1,3 +1,5 @@ +name: Detect workspaces changes + on: workflow_call: inputs: diff --git a/.github/workflows/execute-yarn-workspace-command.yml b/.github/workflows/execute-yarn-workspace-command.yml new file mode 100644 index 00000000..9a466fb6 --- /dev/null +++ b/.github/workflows/execute-yarn-workspace-command.yml @@ -0,0 +1,124 @@ +name: Execute yarn workspace command + +on: + workflow_call: + inputs: + workspace: + description: 'The yarn workspace to execute the command in' + required: true + type: string + command: + required: true + type: string + description: 'The command to execute in the workspace' + os: + required: false + type: string + description: 'The operating system to execute the command in' + target: + required: false + type: string + description: 'The rust target to setup rust with' + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + description: 'The yarn workspace to execute the command in' + required: true + type: string + command: + required: true + type: string + description: 'The command to execute in the workspace' + os: + required: false + type: string + description: 'The operating system to execute the command in' + target: + required: false + type: string + description: 'The rust target to setup rust with' + +jobs: + determine-os: + runs-on: ubuntu-latest + outputs: + os: ${{ steps.determine-os.outputs.os }} + steps: + - name: Determine OS + id: determine-os + env: + OS_INPUT: ${{ inputs.os }} + run: | + if [[ -z OS_INPUT ]]; then + echo "os=ubuntu-latest" >> $GITHUB_OUTPUT + else + echo "os=${{inputs.os}}" >> $GITHUB_OUTPUT + fi + + main: + needs: determine-os + runs-on: ${{ needs.determine-os.outputs.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.16.1' + + - name: Setup yarn + id: setup-yarn + run: | + corepack enable + corepack prepare yarn@stable --activate + yarn set version stable + yarn -v + + - name: Setup rust + if: ${{ inputs.target }} + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ inputs.target }} + override: true + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install dependencies + run: yarn install --immutable + if: steps.yarn-cache.outputs.cache-hit != 'true' + + - name: Run command (with target) + if: ${{ inputs.target }} + run: yarn workspace ${{ inputs.workspace }} run ${{ inputs.command }} + env: + CARGO_BUILD_TARGET: ${{ inputs.target }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + - name: Run command (without target) + if: ${{ !inputs.target }} + run: yarn workspace ${{ inputs.workspace }} run ${{ inputs.command }} + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + \ No newline at end of file diff --git a/.github/workflows/publish-core.yml b/.github/workflows/publish-core.yml new file mode 100644 index 00000000..b663827e --- /dev/null +++ b/.github/workflows/publish-core.yml @@ -0,0 +1,33 @@ +name: Publish core + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The extension's yarn workspace the extension core is part of. + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + description: | + The extension's yarn workspace the extension core is part of. + required: true + type: string + +jobs: + publish: + uses: ./.github/workflows/execute-yarn-workspace-command.yml + with: + workspace: ${{ inputs.workspace }}-core + command: core:publish + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + \ No newline at end of file diff --git a/.github/workflows/publish-extension-auto.yml b/.github/workflows/publish-extension-auto.yml new file mode 100644 index 00000000..64157c69 --- /dev/null +++ b/.github/workflows/publish-extension-auto.yml @@ -0,0 +1,122 @@ +name: Publish extension auto + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + pre-release: + required: false + type: boolean + description: | + Whether this is a pre-release. + compute-version: + required: false + type: boolean + description: | + Whether to compute a new version if the version already exists o the marketplace. + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + pre-release: + required: false + type: boolean + description: | + Whether this is a pre-release. + compute-version: + required: false + type: boolean + description: | + Whether to compute a new version if the version already exists o the marketplace. + +jobs: + compute-version: + uses: ./.github/workflows/compute-version.yml + with: + workspace: ${{ inputs.workspace }} + compute-version: ${{ inputs.compute-version }} + + + + + publish: + needs: + - compute-version + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + target: x86_64-pc-windows-msvc + code-target: win32-x64 + - os: windows-latest + target: i686-pc-windows-msvc + code-target: win32-ia32 + - os: windows-latest + target: aarch64-pc-windows-msvc + code-target: win32-arm64 + - os: ubuntu-20.04 + target: x86_64-unknown-linux-gnu + code-target: linux-x64 + #container: ubuntu:18.04 + #- os: ubuntu-20.04 + # target: aarch64-unknown-linux-gnu + # code-target: linux-arm64 + #- os: ubuntu-20.04 + # target: arm-unknown-linux-gnueabihf + # code-target: linux-armhf + - os: macos-11 + target: x86_64-apple-darwin + code-target: darwin-x64 + - os: macos-11 + target: aarch64-apple-darwin + code-target: darwin-arm64 + uses: ./.github/workflows/publish-targeted-extension.yml + with: + workspace: ${{ inputs.workspace }} + os: ${{ matrix.os }} + target: ${{ matrix.target }} + code-target: ${{ matrix.code-target }} + version: ${{ needs.compute-version.outputs.version }} + pre-release: ${{ inputs.pre-release }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + commit-and-tag: + needs: + - compute-version + - publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Get tag prefix + id: get-tag-prefix + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const workspace = '${{ inputs.workspace }}'; + const language = workspace.split('-')[1]; + return language; + - name: Setup git config + run: | + git config --local user.email "ci@astrodevslabs.io" + git config --local user.name "Astrodevs CI" + - name: tag + run: | + git tag -a "${{steps.get-tag-prefix.outputs.result}}-${{ needs.compute-version.outputs.version }}" -m "Release ${{ steps.get-tag-prefix.outputs.result }}-${{ needs.compute-version.outputs.version }}" + git push origin "${{steps.get-tag-prefix.outputs.result}}-${{ needs.compute-version.outputs.version }}" + \ No newline at end of file diff --git a/.github/workflows/publish-extension-manual.yml b/.github/workflows/publish-extension-manual.yml new file mode 100644 index 00000000..aaf4534d --- /dev/null +++ b/.github/workflows/publish-extension-manual.yml @@ -0,0 +1,127 @@ +name: Publish extension manual + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + pre-release: + required: false + type: boolean + description: | + Whether this is a pre-release. + version: + required: true + type: string + description: | + The version to publish. + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the extension is in. + pre-release: + required: false + type: boolean + description: | + Whether this is a pre-release. + version: + required: true + type: string + description: | + The version to publish. + +jobs: + publish: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + target: x86_64-pc-windows-msvc + code-target: win32-x64 + - os: windows-latest + target: i686-pc-windows-msvc + code-target: win32-ia32 + - os: windows-latest + target: aarch64-pc-windows-msvc + code-target: win32-arm64 + - os: ubuntu-20.04 + target: x86_64-unknown-linux-gnu + code-target: linux-x64 + #container: ubuntu:18.04 + #- os: ubuntu-20.04 + # target: aarch64-unknown-linux-gnu + # code-target: linux-arm64 + #- os: ubuntu-20.04 + # target: arm-unknown-linux-gnueabihf + # code-target: linux-armhf + - os: macos-11 + target: x86_64-apple-darwin + code-target: darwin-x64 + - os: macos-11 + target: aarch64-apple-darwin + code-target: darwin-arm64 + uses: ./.github/workflows/publish-targeted-extension.yml + with: + workspace: ${{ inputs.workspace }} + os: ${{ matrix.os }} + target: ${{ matrix.target }} + code-target: ${{ matrix.code-target }} + version: ${{ inputs.version }} + pre-release: ${{ inputs.pre-release }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + + commit-and-tag: + needs: publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup yarn + id: setup-yarn + run: | + corepack enable + corepack prepare yarn@stable --activate + yarn set version stable + yarn -v + + - name: Install + run: | + yarn install --immutable + + - name: Get tag prefix + id: get-tag-prefix + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const workspace = '${{ inputs.workspace }}'; + const language = workspace.split('-')[1]; + return language; + + - name: Setup git config + run: | + git config --local user.email "ci@astrodevslabs.io" + git config --local user.name "Astrodevs CI" + + - name: update package.json, commit and tag + run: | + yarn workspace ${{ inputs.workspace }}-extension version ${{ inputs.version }} + git add . + git commit -m "chore: release ${{ steps.get-tag-prefix.outputs.result }} ${{ inputs.version }}" + git tag -a "${{steps.get-tag-prefix.outputs.result}}-${{ inputs.version }}" -m "Release ${{ steps.get-tag-prefix.outputs.result }} ${{ inputs.version }}" + git push origin ${{ github.ref }} --follow-tags + \ No newline at end of file diff --git a/.github/workflows/publish-extension.yml b/.github/workflows/publish-extension.yml deleted file mode 100644 index f686961c..00000000 --- a/.github/workflows/publish-extension.yml +++ /dev/null @@ -1,121 +0,0 @@ -on: - workflow_call: - inputs: - workspace: - required: true - type: string - description: "yarn workspace name" - secrets: - CARGO_REGISTRY_TOKEN: - required: true - VSCE_PAT: - required: true - workflow_dispatch: - inputs: - workspace: - required: true - type: string - description: "yarn workspace name" - -jobs: - build: - strategy: - fail-fast: false - matrix: - include: - - os: windows-latest - target: x86_64-pc-windows-msvc - code-target: win32-x64 - - os: windows-latest - target: i686-pc-windows-msvc - code-target: win32-ia32 - - os: windows-latest - target: aarch64-pc-windows-msvc - code-target: win32-arm64 - - os: ubuntu-20.04 - target: x86_64-unknown-linux-gnu - code-target: linux-x64 - #container: ubuntu:18.04 - #- os: ubuntu-20.04 - # target: aarch64-unknown-linux-gnu - # code-target: linux-arm64 - #- os: ubuntu-20.04 - # target: arm-unknown-linux-gnueabihf - # code-target: linux-armhf - - os: macos-11 - target: x86_64-apple-darwin - code-target: darwin-x64 - - os: macos-11 - target: aarch64-apple-darwin - code-target: darwin-arm64 - runs-on: ${{ matrix.os }} - #container: ${{ matrix.container }} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Get tags - run: git fetch --tags origin - - - uses: actions/setup-node@v3 - with: - node-version: '18.16.1' - - - id: setup-yarn - # Install yarn 3 & workspace-tools - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn -v - - - name: Setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - override: true - - - name: Get tag prefix - id: get-tag-prefix - uses: actions/github-script@v6 - with: - result-encoding: string - script: | - const workspace = "${{ inputs.workspace }}"; - const language = workspace.split('-')[1]; - return language; - - - name: Retrieve version - id: retrieve-version - uses: "WyriHaximus/github-action-get-previous-tag@v1" - with: - prefix: "${{ steps.get-tag-prefix.outputs.result }}-" - - - name: Extract semver - uses: actions/github-script@v6 - id: tag - with: - result-encoding: string - script: | - const tag = '${{ steps.retrieve-version.outputs.tag }}'; - const semver = tag.split('-')[1]; - return semver; - - name: Install dependencies - run: | - yarn install --immutable - - - name: Build - run: | - yarn workspace ${{ inputs.workspace }} build - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} - - - name: Publish - run: yarn workspace ${{ inputs.workspace }} run extension:publish ${{ github.ref_name == 'dev' && '--pre-release' || '' }} ${{ steps.tag.outputs.result }} --target ${{matrix.code-target}} - env: - VSCE_PAT: ${{ secrets.VSCE_PAT }} - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - \ No newline at end of file diff --git a/.github/workflows/publish-library.yml b/.github/workflows/publish-library.yml new file mode 100644 index 00000000..d5408dd0 --- /dev/null +++ b/.github/workflows/publish-library.yml @@ -0,0 +1,33 @@ +name: Publish library + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The yarn workspace the library is in. + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + description: | + The yarn workspace the library is in. + required: true + type: string + +jobs: + publish: + uses: ./.github/workflows/execute-yarn-workspace-command.yml + with: + workspace: ${{ inputs.workspace }} + command: publish + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} + \ No newline at end of file diff --git a/.github/workflows/publish-targeted-extension.yml b/.github/workflows/publish-targeted-extension.yml new file mode 100644 index 00000000..473713e3 --- /dev/null +++ b/.github/workflows/publish-targeted-extension.yml @@ -0,0 +1,129 @@ +name: Publish targeted extension + +on: + workflow_call: + inputs: + workspace: + required: true + type: string + description: | + The extension's yarn workspace the extension is part of. + os: + required: true + type: string + description: | + The operating system to run the publish on. + target: + required: true + type: string + description: | + The rust target to build with to publish. + code-target: + required: true + type: string + description: | + The vscode target to publish to. + version: + required: true + type: string + description: | + The version to publish. + pre-release: + required: false + type: boolean + description: | + Whether to publish as a pre-release. + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: + required: true + workflow_dispatch: + inputs: + workspace: + required: true + type: string + description: | + The extension's yarn workspace the extension is part of. + os: + required: true + type: string + description: | + The operating system to run the publish on. + target: + required: true + type: string + description: | + The rust target to build with to publish. + code-target: + required: true + type: string + description: | + The vscode target to publish to. + version: + required: true + type: string + description: | + The version to publish. + pre-release: + required: false + type: boolean + description: | + Whether to publish as a pre-release. + +jobs: + publish: + runs-on: ${{ inputs.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.16.1' + + - name: Setup yarn + id: setup-yarn + run: | + corepack enable + corepack prepare yarn@stable --activate + yarn set version stable + yarn -v + + - name: Setup rust + if: ${{ inputs.target }} + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ inputs.target }} + override: true + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install dependencies + run: yarn install --immutable + if: steps.yarn-cache.outputs.cache-hit != 'true' + + - name: Build + run: yarn workspace ${{ inputs.workspace }} run build + + - name: Publish + run: yarn workspace ${{ inputs.workspace }}-extension run extension:publish ${{ inputs.pre-release && '--pre-release' || '' }} ${{ inputs.version }} --target ${{ inputs.code-target }} + env: + VSCE_PAT: ${{ secrets.VSCE_PAT }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + \ No newline at end of file diff --git a/.github/workflows/retype-action.yml b/.github/workflows/retype-action.yml new file mode 100644 index 00000000..8f1c1112 --- /dev/null +++ b/.github/workflows/retype-action.yml @@ -0,0 +1,52 @@ +name: Publish Retype powered website to GitHub Pages +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + build_and_publish: + name: Build and get documentation + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + repository: 'astrodevs-labs/osmium' + ref: 'main' + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build with Cargo + run: | + cd toolchains/solidity/core + cargo build + + - name: Execute Binary to get documentation + run: | + cd toolchains/solidity/core + ./target/debug/solidhunter -d > ../../../doc/documentation.json + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Build md from json + run: | + cd ./doc + node createMarkdownFilesFromJsonArray.js documentation.json + + - uses: retypeapp/action-build@latest + with: + config: ./doc/retype.yml + + - uses: retypeapp/action-github-pages@latest + with: + update-branch: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 52c8b2ec..5479baee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,20 +5,17 @@ on: required: true type: string description: "yarn workspace name" - command: + secrets: + CARGO_REGISTRY_TOKEN: + required: true + VSCE_PAT: required: true - type: string - description: "yarn command to run" workflow_dispatch: inputs: workspace: required: true type: string description: "yarn workspace name" - command: - required: true - type: string - description: "yarn command to run" jobs: build: @@ -50,41 +47,12 @@ jobs: #- os: macos-11 # target: aarch64-apple-darwin # code-target: darwin-arm64 - runs-on: ${{ matrix.os }} - #container: ${{ matrix.container }} - - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - - - name: Setup yarn - id: setup-yarn - run: | - corepack enable - corepack prepare yarn@stable --activate - yarn set version stable - yarn -v - - - name: Setup rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - override: true - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - run: yarn install --frozen-lockfile - if: steps.yarn-cache.outputs.cache-hit != 'true' - - - run: yarn workspace ${{ inputs.workspace }} run ${{ inputs.command }} - env: - CARGO_BUILD_TARGET: ${{ matrix.target }} \ No newline at end of file + uses: ./.github/workflows/execute-yarn-workspace-command.yml + with: + workspace: ${{ inputs.workspace }} + command: test + os: ${{ matrix.os }} + target: ${{ matrix.target }} + secrets: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + VSCE_PAT: ${{ secrets.VSCE_PAT }} \ No newline at end of file diff --git a/.pnp.cjs b/.pnp.cjs index 8579e879..231346b7 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -13,10 +13,18 @@ const RAW_RUNTIME_STATE = "name": "osmium",\ "reference": "workspace:."\ },\ + {\ + "name": "doc",\ + "reference": "workspace:doc"\ + },\ {\ "name": "@osmium-libs/ast-extractor",\ "reference": "workspace:libs/ast-extractor"\ },\ + {\ + "name": "@osmium-libs/foundry-wrapper",\ + "reference": "workspace:libs/foundry-wrapper"\ + },\ {\ "name": "@osmium-libs/lsp-handler",\ "reference": "workspace:libs/lsp-handler"\ @@ -58,11 +66,13 @@ const RAW_RUNTIME_STATE = "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\ "fallbackExclusionList": [\ ["@osmium-libs/ast-extractor", ["workspace:libs/ast-extractor"]],\ + ["@osmium-libs/foundry-wrapper", ["workspace:libs/foundry-wrapper"]],\ ["@osmium-libs/lsp-handler", ["workspace:libs/lsp-handler"]],\ ["@osmium-libs/lsp-launcher", ["workspace:libs/lsp-launcher"]],\ ["@osmium-libs/lsp-server-wrapper", ["workspace:libs/lsp-server-wrapper"]],\ ["@osmium-packages/eslint-config", ["workspace:packages/eslint-config"]],\ ["@osmium-packages/prettier-config", ["workspace:packages/prettier-config"]],\ + ["doc", ["workspace:doc"]],\ ["osmium", ["workspace:."]],\ ["osmium-manager", ["workspace:manager"]],\ ["osmium-solidity", ["workspace:toolchains/solidity"]],\ @@ -107,12 +117,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:e7f048a4398cf12bbd1cde95eff45a3327b9fe42e04c31ed99d0e926830d0b78ff78b511118c2bd3bc6add84782ab97a5b001e972071d6fdbfe85a86c150922a#npm:4.4.0", {\ - "packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-a282c466c0/0/cache/@eslint-community-eslint-utils-npm-4.4.0-d1791bd5a3-8d70bcdcd8.zip/node_modules/@eslint-community/eslint-utils/",\ + ["virtual:7e84babe85e6b058f29b2789822aea4bf3e34b48391f8eba05629d50500f4f2dfbe6628418745cffc770a77f74f121288626b69dd676f57de93d3ca5c7553ce6#npm:4.4.0", {\ + "packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-f7c44dfe79/0/cache/@eslint-community-eslint-utils-npm-4.4.0-d1791bd5a3-8d70bcdcd8.zip/node_modules/@eslint-community/eslint-utils/",\ "packageDependencies": [\ - ["@eslint-community/eslint-utils", "virtual:e7f048a4398cf12bbd1cde95eff45a3327b9fe42e04c31ed99d0e926830d0b78ff78b511118c2bd3bc6add84782ab97a5b001e972071d6fdbfe85a86c150922a#npm:4.4.0"],\ + ["@eslint-community/eslint-utils", "virtual:7e84babe85e6b058f29b2789822aea4bf3e34b48391f8eba05629d50500f4f2dfbe6628418745cffc770a77f74f121288626b69dd676f57de93d3ca5c7553ce6#npm:4.4.0"],\ ["@types/eslint", null],\ - ["eslint", "npm:8.52.0"],\ + ["eslint", "npm:8.55.0"],\ ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ "packagePeers": [\ @@ -123,24 +133,24 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@eslint-community/regexpp", [\ - ["npm:4.9.1", {\ - "packageLocation": "./.yarn/cache/@eslint-community-regexpp-npm-4.9.1-7805f77eb5-8f1ba51fa5.zip/node_modules/@eslint-community/regexpp/",\ + ["npm:4.10.0", {\ + "packageLocation": "./.yarn/cache/@eslint-community-regexpp-npm-4.10.0-6bfb984c81-8c36169c81.zip/node_modules/@eslint-community/regexpp/",\ "packageDependencies": [\ - ["@eslint-community/regexpp", "npm:4.9.1"]\ + ["@eslint-community/regexpp", "npm:4.10.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@eslint/eslintrc", [\ - ["npm:2.1.2", {\ - "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-2.1.2-feb0771c9f-fa25638f26.zip/node_modules/@eslint/eslintrc/",\ + ["npm:2.1.4", {\ + "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-2.1.4-1ff4b5f908-7a3b14f4b4.zip/node_modules/@eslint/eslintrc/",\ "packageDependencies": [\ - ["@eslint/eslintrc", "npm:2.1.2"],\ + ["@eslint/eslintrc", "npm:2.1.4"],\ ["ajv", "npm:6.12.6"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["espree", "npm:9.6.1"],\ ["globals", "npm:13.23.0"],\ - ["ignore", "npm:5.2.4"],\ + ["ignore", "npm:5.3.0"],\ ["import-fresh", "npm:3.3.0"],\ ["js-yaml", "npm:4.1.0"],\ ["minimatch", "npm:3.1.2"],\ @@ -150,10 +160,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@eslint/js", [\ - ["npm:8.52.0", {\ - "packageLocation": "./.yarn/cache/@eslint-js-npm-8.52.0-801dbdf7b0-86beff213d.zip/node_modules/@eslint/js/",\ + ["npm:8.55.0", {\ + "packageLocation": "./.yarn/cache/@eslint-js-npm-8.55.0-ec5eb0638e-34b001a95b.zip/node_modules/@eslint/js/",\ "packageDependencies": [\ - ["@eslint/js", "npm:8.52.0"]\ + ["@eslint/js", "npm:8.55.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -164,7 +174,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@humanwhocodes/config-array", "npm:0.11.13"],\ ["@humanwhocodes/object-schema", "npm:2.0.1"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["minimatch", "npm:3.1.2"]\ ],\ "linkType": "HARD"\ @@ -304,6 +314,20 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@npmcli/agent", [\ + ["npm:2.2.0", {\ + "packageLocation": "./.yarn/cache/@npmcli-agent-npm-2.2.0-cf04e8a830-822ea07755.zip/node_modules/@npmcli/agent/",\ + "packageDependencies": [\ + ["@npmcli/agent", "npm:2.2.0"],\ + ["agent-base", "npm:7.1.0"],\ + ["http-proxy-agent", "npm:7.0.0"],\ + ["https-proxy-agent", "npm:7.0.2"],\ + ["lru-cache", "npm:10.1.0"],\ + ["socks-proxy-agent", "npm:8.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@npmcli/fs", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/@npmcli-fs-npm-3.1.0-0844a57978-f3a7ab3a31.zip/node_modules/@npmcli/fs/",\ @@ -323,6 +347,15 @@ const RAW_RUNTIME_STATE = "linkType": "SOFT"\ }]\ ]],\ + ["@osmium-libs/foundry-wrapper", [\ + ["workspace:libs/foundry-wrapper", {\ + "packageLocation": "./libs/foundry-wrapper/",\ + "packageDependencies": [\ + ["@osmium-libs/foundry-wrapper", "workspace:libs/foundry-wrapper"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@osmium-libs/lsp-handler", [\ ["workspace:libs/lsp-handler", {\ "packageLocation": "./libs/lsp-handler/",\ @@ -355,7 +388,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/eslint-config/",\ "packageDependencies": [\ ["@osmium-packages/eslint-config", "workspace:packages/eslint-config"],\ - ["eslint", "npm:8.52.0"]\ + ["eslint", "npm:8.55.0"]\ ],\ "linkType": "SOFT"\ }]\ @@ -365,7 +398,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/prettier-config/",\ "packageDependencies": [\ ["@osmium-packages/prettier-config", "workspace:packages/prettier-config"],\ - ["prettier", "npm:3.0.3"]\ + ["prettier", "npm:3.1.0"]\ ],\ "linkType": "SOFT"\ }]\ @@ -386,42 +419,35 @@ const RAW_RUNTIME_STATE = ["@tootallnate/once", "npm:1.1.2"]\ ],\ "linkType": "HARD"\ - }],\ - ["npm:2.0.0", {\ - "packageLocation": "./.yarn/cache/@tootallnate-once-npm-2.0.0-e36cf4f140-ad87447820.zip/node_modules/@tootallnate/once/",\ - "packageDependencies": [\ - ["@tootallnate/once", "npm:2.0.0"]\ - ],\ - "linkType": "HARD"\ }]\ ]],\ ["@types/eslint", [\ - ["npm:8.44.6", {\ - "packageLocation": "./.yarn/cache/@types-eslint-npm-8.44.6-5d79f5da7d-07ee27c180.zip/node_modules/@types/eslint/",\ + ["npm:8.44.8", {\ + "packageLocation": "./.yarn/cache/@types-eslint-npm-8.44.8-54a444f190-d6e0788eb7.zip/node_modules/@types/eslint/",\ "packageDependencies": [\ - ["@types/eslint", "npm:8.44.6"],\ - ["@types/estree", "npm:1.0.3"],\ - ["@types/json-schema", "npm:7.0.14"]\ + ["@types/eslint", "npm:8.44.8"],\ + ["@types/estree", "npm:1.0.5"],\ + ["@types/json-schema", "npm:7.0.15"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/eslint-scope", [\ - ["npm:3.7.6", {\ - "packageLocation": "./.yarn/cache/@types-eslint-scope-npm-3.7.6-21feb9c235-a2339e3129.zip/node_modules/@types/eslint-scope/",\ + ["npm:3.7.7", {\ + "packageLocation": "./.yarn/cache/@types-eslint-scope-npm-3.7.7-efa26592f6-e2889a124a.zip/node_modules/@types/eslint-scope/",\ "packageDependencies": [\ - ["@types/eslint-scope", "npm:3.7.6"],\ - ["@types/eslint", "npm:8.44.6"],\ - ["@types/estree", "npm:1.0.3"]\ + ["@types/eslint-scope", "npm:3.7.7"],\ + ["@types/eslint", "npm:8.44.8"],\ + ["@types/estree", "npm:1.0.5"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/estree", [\ - ["npm:1.0.3", {\ - "packageLocation": "./.yarn/cache/@types-estree-npm-1.0.3-716b9810bd-c51984ec30.zip/node_modules/@types/estree/",\ + ["npm:1.0.5", {\ + "packageLocation": "./.yarn/cache/@types-estree-npm-1.0.5-5b7faed3b4-7de6d928dd.zip/node_modules/@types/estree/",\ "packageDependencies": [\ - ["@types/estree", "npm:1.0.3"]\ + ["@types/estree", "npm:1.0.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -432,16 +458,16 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@types/glob", "npm:8.1.0"],\ ["@types/minimatch", "npm:5.1.2"],\ - ["@types/node", "npm:20.8.7"]\ + ["@types/node", "npm:20.9.3"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/json-schema", [\ - ["npm:7.0.14", {\ - "packageLocation": "./.yarn/cache/@types-json-schema-npm-7.0.14-7dad9e71b4-84b5efed51.zip/node_modules/@types/json-schema/",\ + ["npm:7.0.15", {\ + "packageLocation": "./.yarn/cache/@types-json-schema-npm-7.0.15-fd16381786-1a3c3e0623.zip/node_modules/@types/json-schema/",\ "packageDependencies": [\ - ["@types/json-schema", "npm:7.0.14"]\ + ["@types/json-schema", "npm:7.0.15"]\ ],\ "linkType": "HARD"\ }]\ @@ -456,10 +482,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@types/mocha", [\ - ["npm:10.0.3", {\ - "packageLocation": "./.yarn/cache/@types-mocha-npm-10.0.3-a45fafc70f-31d44b6a45.zip/node_modules/@types/mocha/",\ + ["npm:10.0.6", {\ + "packageLocation": "./.yarn/cache/@types-mocha-npm-10.0.6-a687c1962c-fc73626e81.zip/node_modules/@types/mocha/",\ "packageDependencies": [\ - ["@types/mocha", "npm:10.0.3"]\ + ["@types/mocha", "npm:10.0.6"]\ ],\ "linkType": "HARD"\ }]\ @@ -472,29 +498,29 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:20.8.7", {\ - "packageLocation": "./.yarn/cache/@types-node-npm-20.8.7-a09c56cd33-a347ac7e6a.zip/node_modules/@types/node/",\ + ["npm:20.9.3", {\ + "packageLocation": "./.yarn/cache/@types-node-npm-20.9.3-1bedd14426-5d2a3a6b2b.zip/node_modules/@types/node/",\ "packageDependencies": [\ - ["@types/node", "npm:20.8.7"],\ - ["undici-types", "npm:5.25.3"]\ + ["@types/node", "npm:20.9.3"],\ + ["undici-types", "npm:5.26.5"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/semver", [\ - ["npm:7.5.4", {\ - "packageLocation": "./.yarn/cache/@types-semver-npm-7.5.4-aa93e70844-e99c3edc8d.zip/node_modules/@types/semver/",\ + ["npm:7.5.6", {\ + "packageLocation": "./.yarn/cache/@types-semver-npm-7.5.6-9d2637fc95-e77282b17f.zip/node_modules/@types/semver/",\ "packageDependencies": [\ - ["@types/semver", "npm:7.5.4"]\ + ["@types/semver", "npm:7.5.6"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@types/vscode", [\ - ["npm:1.83.1", {\ - "packageLocation": "./.yarn/cache/@types-vscode-npm-1.83.1-1e622f7668-4acffc6586.zip/node_modules/@types/vscode/",\ + ["npm:1.84.2", {\ + "packageLocation": "./.yarn/cache/@types-vscode-npm-1.84.2-26a911e6a9-45687e6e26.zip/node_modules/@types/vscode/",\ "packageDependencies": [\ - ["@types/vscode", "npm:1.83.1"]\ + ["@types/vscode", "npm:1.84.2"]\ ],\ "linkType": "HARD"\ }]\ @@ -511,7 +537,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/__virtual__/@typescript-eslint-eslint-plugin-virtual-89014fb2f7/0/cache/@typescript-eslint-eslint-plugin-npm-5.62.0-c48b9a5492-9cc8319c6f.zip/node_modules/@typescript-eslint/eslint-plugin/",\ "packageDependencies": [\ ["@typescript-eslint/eslint-plugin", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.62.0"],\ - ["@eslint-community/regexpp", "npm:4.9.1"],\ + ["@eslint-community/regexpp", "npm:4.10.0"],\ ["@types/eslint", null],\ ["@types/typescript", null],\ ["@types/typescript-eslint__parser", null],\ @@ -519,14 +545,14 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/scope-manager", "npm:5.62.0"],\ ["@typescript-eslint/type-utils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:5.62.0"],\ ["@typescript-eslint/utils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:5.62.0"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ - ["eslint", "npm:8.52.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ + ["eslint", "npm:8.55.0"],\ ["graphemer", "npm:1.4.0"],\ - ["ignore", "npm:5.2.4"],\ + ["ignore", "npm:5.3.0"],\ ["natural-compare-lite", "npm:1.4.0"],\ ["semver", "npm:7.5.4"],\ ["tsutils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -556,9 +582,9 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/scope-manager", "npm:5.62.0"],\ ["@typescript-eslint/types", "npm:5.62.0"],\ ["@typescript-eslint/typescript-estree", "virtual:7f3bc25884a68a29ac4d296cb19161080b5427dc732e6412b6c8cd95f25543caace2cc48bfd515b6ed39d97808f3fde9257ccd25f2112571b23f01c85c15a049#npm:5.62.0"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ - ["eslint", "npm:8.52.0"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ + ["eslint", "npm:8.55.0"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -596,10 +622,10 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/typescript-estree", "virtual:7f3bc25884a68a29ac4d296cb19161080b5427dc732e6412b6c8cd95f25543caace2cc48bfd515b6ed39d97808f3fde9257ccd25f2112571b23f01c85c15a049#npm:5.62.0"],\ ["@typescript-eslint/utils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:5.62.0"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ - ["eslint", "npm:8.52.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ + ["eslint", "npm:8.55.0"],\ ["tsutils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -634,12 +660,12 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:5.62.0"],\ ["@typescript-eslint/visitor-keys", "npm:5.62.0"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["semver", "npm:7.5.4"],\ ["tsutils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:3.21.0"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -654,7 +680,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:5.62.0"],\ ["@typescript-eslint/visitor-keys", "npm:5.62.0"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["semver", "npm:7.5.4"],\ @@ -680,14 +706,14 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/__virtual__/@typescript-eslint-utils-virtual-b6c32928e3/0/cache/@typescript-eslint-utils-npm-5.62.0-907f2d579e-15ef13e439.zip/node_modules/@typescript-eslint/utils/",\ "packageDependencies": [\ ["@typescript-eslint/utils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:5.62.0"],\ - ["@eslint-community/eslint-utils", "virtual:e7f048a4398cf12bbd1cde95eff45a3327b9fe42e04c31ed99d0e926830d0b78ff78b511118c2bd3bc6add84782ab97a5b001e972071d6fdbfe85a86c150922a#npm:4.4.0"],\ + ["@eslint-community/eslint-utils", "virtual:7e84babe85e6b058f29b2789822aea4bf3e34b48391f8eba05629d50500f4f2dfbe6628418745cffc770a77f74f121288626b69dd676f57de93d3ca5c7553ce6#npm:4.4.0"],\ ["@types/eslint", null],\ - ["@types/json-schema", "npm:7.0.14"],\ - ["@types/semver", "npm:7.5.4"],\ + ["@types/json-schema", "npm:7.0.15"],\ + ["@types/semver", "npm:7.5.6"],\ ["@typescript-eslint/scope-manager", "npm:5.62.0"],\ ["@typescript-eslint/types", "npm:5.62.0"],\ ["@typescript-eslint/typescript-estree", "virtual:b6c32928e3a73473744c61c91597c46acb3aac39cfd0cb6fa763edd86d59abe50465a1795d8d98162d97d00db3b3f55ab682576f5b7c142340f4654751eec0b2#npm:5.62.0"],\ - ["eslint", "npm:8.52.0"],\ + ["eslint", "npm:8.55.0"],\ ["eslint-scope", "npm:5.1.1"],\ ["semver", "npm:7.5.4"]\ ],\ @@ -719,10 +745,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vscode/test-electron", [\ - ["npm:2.3.5", {\ - "packageLocation": "./.yarn/cache/@vscode-test-electron-npm-2.3.5-a094bdf2db-b0de89154f.zip/node_modules/@vscode/test-electron/",\ + ["npm:2.3.8", {\ + "packageLocation": "./.yarn/cache/@vscode-test-electron-npm-2.3.8-657ae8348f-044ce44866.zip/node_modules/@vscode/test-electron/",\ "packageDependencies": [\ - ["@vscode/test-electron", "npm:2.3.5"],\ + ["@vscode/test-electron", "npm:2.3.8"],\ ["http-proxy-agent", "npm:4.0.1"],\ ["https-proxy-agent", "npm:5.0.1"],\ ["jszip", "npm:3.10.1"],\ @@ -1033,19 +1059,19 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["abbrev", [\ - ["npm:1.1.1", {\ - "packageLocation": "./.yarn/cache/abbrev-npm-1.1.1-3659247eab-2d88294118.zip/node_modules/abbrev/",\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/abbrev-npm-2.0.0-0eb38a17e5-ca0a54e35b.zip/node_modules/abbrev/",\ "packageDependencies": [\ - ["abbrev", "npm:1.1.1"]\ + ["abbrev", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["acorn", [\ - ["npm:8.10.0", {\ - "packageLocation": "./.yarn/cache/acorn-npm-8.10.0-2230c9e83e-522310c20f.zip/node_modules/acorn/",\ + ["npm:8.11.2", {\ + "packageLocation": "./.yarn/cache/acorn-npm-8.11.2-a470f49bb6-ff559b8913.zip/node_modules/acorn/",\ "packageDependencies": [\ - ["acorn", "npm:8.10.0"]\ + ["acorn", "npm:8.11.2"]\ ],\ "linkType": "HARD"\ }]\ @@ -1063,7 +1089,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["acorn-import-assertions", "virtual:b98590e6182f1e3e809675a880704d2c50533e40386e60683f5d6ae6206f5e5e58cf33b625935351b9a4ef2066acd33ce7f25a0d7055a7a23f1ec398f2c56b3f#npm:1.9.0"],\ ["@types/acorn", null],\ - ["acorn", "npm:8.10.0"]\ + ["acorn", "npm:8.11.2"]\ ],\ "packagePeers": [\ "@types/acorn",\ @@ -1085,7 +1111,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["acorn-jsx", "virtual:a50722a5a9326b6a5f12350c494c4db3aa0f4caeac45e3e9e5fe071da20014ecfe738fe2ebe2c9c98abae81a4ea86b42f56d776b3bd5ec37f9ad3670c242b242#npm:5.3.2"],\ ["@types/acorn", null],\ - ["acorn", "npm:8.10.0"]\ + ["acorn", "npm:8.11.2"]\ ],\ "packagePeers": [\ "@types/acorn",\ @@ -1099,17 +1125,15 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/agent-base-npm-6.0.2-428f325a93-21fb903e09.zip/node_modules/agent-base/",\ "packageDependencies": [\ ["agent-base", "npm:6.0.2"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"]\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["agentkeepalive", [\ - ["npm:4.5.0", {\ - "packageLocation": "./.yarn/cache/agentkeepalive-npm-4.5.0-f237b580b2-dd210ba2a2.zip/node_modules/agentkeepalive/",\ + }],\ + ["npm:7.1.0", {\ + "packageLocation": "./.yarn/cache/agent-base-npm-7.1.0-4b12ba5111-f7828f9914.zip/node_modules/agent-base/",\ "packageDependencies": [\ - ["agentkeepalive", "npm:4.5.0"],\ - ["humanize-ms", "npm:1.2.1"]\ + ["agent-base", "npm:7.1.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -1221,26 +1245,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["aproba", [\ - ["npm:2.0.0", {\ - "packageLocation": "./.yarn/cache/aproba-npm-2.0.0-8716bcfde6-c2b9a63129.zip/node_modules/aproba/",\ - "packageDependencies": [\ - ["aproba", "npm:2.0.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["are-we-there-yet", [\ - ["npm:3.0.1", {\ - "packageLocation": "./.yarn/cache/are-we-there-yet-npm-3.0.1-3395b1512f-390731720e.zip/node_modules/are-we-there-yet/",\ - "packageDependencies": [\ - ["are-we-there-yet", "npm:3.0.1"],\ - ["delegates", "npm:1.0.0"],\ - ["readable-stream", "npm:3.6.2"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["argparse", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/argparse-npm-2.0.1-faff7999e6-18640244e6.zip/node_modules/argparse/",\ @@ -1357,14 +1361,14 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["browserslist", [\ - ["npm:4.22.1", {\ - "packageLocation": "./.yarn/cache/browserslist-npm-4.22.1-cccae6d74e-4a515168e0.zip/node_modules/browserslist/",\ + ["npm:4.22.2", {\ + "packageLocation": "./.yarn/cache/browserslist-npm-4.22.2-87e70d8021-e3590793db.zip/node_modules/browserslist/",\ "packageDependencies": [\ - ["browserslist", "npm:4.22.1"],\ - ["caniuse-lite", "npm:1.0.30001553"],\ - ["electron-to-chromium", "npm:1.4.565"],\ - ["node-releases", "npm:2.0.13"],\ - ["update-browserslist-db", "virtual:cccae6d74e613cbaceb4c608cb01004dea3f5ca235673f5c541d60f516ef320907d258256abf63eac9b8704e23cf5d52eb19f2a57a07471accc943ea645de308#npm:1.0.13"]\ + ["browserslist", "npm:4.22.2"],\ + ["caniuse-lite", "npm:1.0.30001565"],\ + ["electron-to-chromium", "npm:1.4.601"],\ + ["node-releases", "npm:2.0.14"],\ + ["update-browserslist-db", "virtual:87e70d802146e5a0e8f2a12b5ab64004040c6640441dba54229a7db766cb1b88edabd3d3c814ce33d6ba839c4e517b12e9b0a7febfca22ac2a64177042bf3ee6#npm:1.0.13"]\ ],\ "linkType": "HARD"\ }]\ @@ -1399,16 +1403,16 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["cacache", [\ - ["npm:17.1.4", {\ - "packageLocation": "./.yarn/cache/cacache-npm-17.1.4-51ef53d0a8-6e26c788bc.zip/node_modules/cacache/",\ + ["npm:18.0.1", {\ + "packageLocation": "./.yarn/cache/cacache-npm-18.0.1-11c6564db0-aecafd368f.zip/node_modules/cacache/",\ "packageDependencies": [\ - ["cacache", "npm:17.1.4"],\ + ["cacache", "npm:18.0.1"],\ ["@npmcli/fs", "npm:3.1.0"],\ ["fs-minipass", "npm:3.0.3"],\ ["glob", "npm:10.3.10"],\ - ["lru-cache", "npm:7.18.3"],\ + ["lru-cache", "npm:10.1.0"],\ ["minipass", "npm:7.0.4"],\ - ["minipass-collect", "npm:1.0.2"],\ + ["minipass-collect", "npm:2.0.1"],\ ["minipass-flush", "npm:1.0.5"],\ ["minipass-pipeline", "npm:1.2.4"],\ ["p-map", "npm:4.0.0"],\ @@ -1450,10 +1454,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["caniuse-lite", [\ - ["npm:1.0.30001553", {\ - "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001553-af33af7fcd-b14b512307.zip/node_modules/caniuse-lite/",\ + ["npm:1.0.30001565", {\ + "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001565-0b12d565d2-abc58bf350.zip/node_modules/caniuse-lite/",\ "packageDependencies": [\ - ["caniuse-lite", "npm:1.0.30001553"]\ + ["caniuse-lite", "npm:1.0.30001565"]\ ],\ "linkType": "HARD"\ }]\ @@ -1619,15 +1623,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["color-support", [\ - ["npm:1.1.3", {\ - "packageLocation": "./.yarn/cache/color-support-npm-1.1.3-3be5c53455-4bcfe30eea.zip/node_modules/color-support/",\ - "packageDependencies": [\ - ["color-support", "npm:1.1.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["colorette", [\ ["npm:2.0.20", {\ "packageLocation": "./.yarn/cache/colorette-npm-2.0.20-692d428726-0b8de48bfa.zip/node_modules/colorette/",\ @@ -1669,15 +1664,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["console-control-strings", [\ - ["npm:1.1.0", {\ - "packageLocation": "./.yarn/cache/console-control-strings-npm-1.1.0-e3160e5275-27b5fa302b.zip/node_modules/console-control-strings/",\ - "packageDependencies": [\ - ["console-control-strings", "npm:1.1.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["core-util-is", [\ ["npm:1.0.3", {\ "packageLocation": "./.yarn/cache/core-util-is-npm-1.0.3-ca74b76c90-9de8597363.zip/node_modules/core-util-is/",\ @@ -1730,13 +1716,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4", {\ - "packageLocation": "./.yarn/__virtual__/debug-virtual-762d08cbe9/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ + ["virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-1040418e3c/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ "packageDependencies": [\ - ["debug", "virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["@types/supports-color", null],\ ["ms", "npm:2.1.2"],\ - ["supports-color", "npm:8.1.1"]\ + ["supports-color", null]\ ],\ "packagePeers": [\ "@types/supports-color",\ @@ -1744,13 +1730,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4", {\ - "packageLocation": "./.yarn/__virtual__/debug-virtual-954df360d3/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ + ["virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-762d08cbe9/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ "packageDependencies": [\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4"],\ ["@types/supports-color", null],\ ["ms", "npm:2.1.2"],\ - ["supports-color", null]\ + ["supports-color", "npm:8.1.1"]\ ],\ "packagePeers": [\ "@types/supports-color",\ @@ -1808,15 +1794,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["delegates", [\ - ["npm:1.0.0", {\ - "packageLocation": "./.yarn/cache/delegates-npm-1.0.0-9b1942d75f-a51744d9b5.zip/node_modules/delegates/",\ - "packageDependencies": [\ - ["delegates", "npm:1.0.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["detect-libc", [\ ["npm:2.0.2", {\ "packageLocation": "./.yarn/cache/detect-libc-npm-2.0.2-03afa59137-6118f30c0c.zip/node_modules/detect-libc/",\ @@ -1845,6 +1822,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["doc", [\ + ["workspace:doc", {\ + "packageLocation": "./doc/",\ + "packageDependencies": [\ + ["doc", "workspace:doc"],\ + ["retypeapp", "npm:3.5.0"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["doctrine", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/doctrine-npm-3.0.0-c6f1615f04-b4b28f1df5.zip/node_modules/doctrine/",\ @@ -1908,10 +1895,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["electron-to-chromium", [\ - ["npm:1.4.565", {\ - "packageLocation": "./.yarn/cache/electron-to-chromium-npm-1.4.565-e46f4c4b3f-caee9af984.zip/node_modules/electron-to-chromium/",\ + ["npm:1.4.601", {\ + "packageLocation": "./.yarn/cache/electron-to-chromium-npm-1.4.601-e52ac99d09-6a7e510156.zip/node_modules/electron-to-chromium/",\ "packageDependencies": [\ - ["electron-to-chromium", "npm:1.4.565"]\ + ["electron-to-chromium", "npm:1.4.601"]\ ],\ "linkType": "HARD"\ }]\ @@ -1989,10 +1976,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["envinfo", [\ - ["npm:7.10.0", {\ - "packageLocation": "./.yarn/cache/envinfo-npm-7.10.0-cba8c054d4-d4db29c5a4.zip/node_modules/envinfo/",\ + ["npm:7.11.0", {\ + "packageLocation": "./.yarn/cache/envinfo-npm-7.11.0-5631444898-8cba09db18.zip/node_modules/envinfo/",\ "packageDependencies": [\ - ["envinfo", "npm:7.10.0"]\ + ["envinfo", "npm:7.11.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -2007,10 +1994,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["es-module-lexer", [\ - ["npm:1.3.1", {\ - "packageLocation": "./.yarn/cache/es-module-lexer-npm-1.3.1-9fc669f676-c6aa137c5f.zip/node_modules/es-module-lexer/",\ + ["npm:1.4.1", {\ + "packageLocation": "./.yarn/cache/es-module-lexer-npm-1.4.1-82f233cba4-cf45361346.zip/node_modules/es-module-lexer/",\ "packageDependencies": [\ - ["es-module-lexer", "npm:1.3.1"]\ + ["es-module-lexer", "npm:1.4.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -2041,14 +2028,14 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["eslint", [\ - ["npm:8.52.0", {\ - "packageLocation": "./.yarn/cache/eslint-npm-8.52.0-e7f048a439-01784ab153.zip/node_modules/eslint/",\ - "packageDependencies": [\ - ["eslint", "npm:8.52.0"],\ - ["@eslint-community/eslint-utils", "virtual:e7f048a4398cf12bbd1cde95eff45a3327b9fe42e04c31ed99d0e926830d0b78ff78b511118c2bd3bc6add84782ab97a5b001e972071d6fdbfe85a86c150922a#npm:4.4.0"],\ - ["@eslint-community/regexpp", "npm:4.9.1"],\ - ["@eslint/eslintrc", "npm:2.1.2"],\ - ["@eslint/js", "npm:8.52.0"],\ + ["npm:8.55.0", {\ + "packageLocation": "./.yarn/cache/eslint-npm-8.55.0-7e84babe85-afd016cfbe.zip/node_modules/eslint/",\ + "packageDependencies": [\ + ["eslint", "npm:8.55.0"],\ + ["@eslint-community/eslint-utils", "virtual:7e84babe85e6b058f29b2789822aea4bf3e34b48391f8eba05629d50500f4f2dfbe6628418745cffc770a77f74f121288626b69dd676f57de93d3ca5c7553ce6#npm:4.4.0"],\ + ["@eslint-community/regexpp", "npm:4.10.0"],\ + ["@eslint/eslintrc", "npm:2.1.4"],\ + ["@eslint/js", "npm:8.55.0"],\ ["@humanwhocodes/config-array", "npm:0.11.13"],\ ["@humanwhocodes/module-importer", "npm:1.0.1"],\ ["@nodelib/fs.walk", "npm:1.2.8"],\ @@ -2056,7 +2043,7 @@ const RAW_RUNTIME_STATE = ["ajv", "npm:6.12.6"],\ ["chalk", "npm:4.1.2"],\ ["cross-spawn", "npm:7.0.3"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["doctrine", "npm:3.0.0"],\ ["escape-string-regexp", "npm:4.0.0"],\ ["eslint-scope", "npm:7.2.2"],\ @@ -2070,7 +2057,7 @@ const RAW_RUNTIME_STATE = ["glob-parent", "npm:6.0.2"],\ ["globals", "npm:13.23.0"],\ ["graphemer", "npm:1.4.0"],\ - ["ignore", "npm:5.2.4"],\ + ["ignore", "npm:5.3.0"],\ ["imurmurhash", "npm:0.1.4"],\ ["is-glob", "npm:4.0.3"],\ ["is-path-inside", "npm:3.0.3"],\ @@ -2121,7 +2108,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/espree-npm-9.6.1-a50722a5a9-255ab260f0.zip/node_modules/espree/",\ "packageDependencies": [\ ["espree", "npm:9.6.1"],\ - ["acorn", "npm:8.10.0"],\ + ["acorn", "npm:8.11.2"],\ ["acorn-jsx", "virtual:a50722a5a9326b6a5f12350c494c4db3aa0f4caeac45e3e9e5fe071da20014ecfe738fe2ebe2c9c98abae81a4ea86b42f56d776b3bd5ec37f9ad3670c242b242#npm:5.3.2"],\ ["eslint-visitor-keys", "npm:3.4.3"]\ ],\ @@ -2210,10 +2197,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["fast-glob", [\ - ["npm:3.3.1", {\ - "packageLocation": "./.yarn/cache/fast-glob-npm-3.3.1-8045ff8f4d-51bcd15472.zip/node_modules/fast-glob/",\ + ["npm:3.3.2", {\ + "packageLocation": "./.yarn/cache/fast-glob-npm-3.3.2-0a8cb4f2ca-222512e931.zip/node_modules/fast-glob/",\ "packageDependencies": [\ - ["fast-glob", "npm:3.3.1"],\ + ["fast-glob", "npm:3.3.2"],\ ["@nodelib/fs.stat", "npm:2.0.5"],\ ["@nodelib/fs.walk", "npm:1.2.8"],\ ["glob-parent", "npm:5.1.2"],\ @@ -2275,7 +2262,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/file-entry-cache-npm-6.0.1-31965cf0af-099bb9d4ab.zip/node_modules/file-entry-cache/",\ "packageDependencies": [\ ["file-entry-cache", "npm:6.0.1"],\ - ["flat-cache", "npm:3.1.1"]\ + ["flat-cache", "npm:3.2.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -2320,10 +2307,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["flat-cache", [\ - ["npm:3.1.1", {\ - "packageLocation": "./.yarn/cache/flat-cache-npm-3.1.1-b79e22b54f-04b57c7cb4.zip/node_modules/flat-cache/",\ + ["npm:3.2.0", {\ + "packageLocation": "./.yarn/cache/flat-cache-npm-3.2.0-9a887f084e-02381c6ece.zip/node_modules/flat-cache/",\ "packageDependencies": [\ - ["flat-cache", "npm:3.1.1"],\ + ["flat-cache", "npm:3.2.0"],\ ["flatted", "npm:3.2.9"],\ ["keyv", "npm:4.5.4"],\ ["rimraf", "npm:3.0.2"]\ @@ -2392,7 +2379,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/unplugged/fsevents-patch-6b67494872/node_modules/fsevents/",\ "packageDependencies": [\ ["fsevents", "patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1"],\ - ["node-gyp", "npm:9.4.0"]\ + ["node-gyp", "npm:10.0.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -2406,23 +2393,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["gauge", [\ - ["npm:4.0.4", {\ - "packageLocation": "./.yarn/cache/gauge-npm-4.0.4-8f878385e9-09535dd53b.zip/node_modules/gauge/",\ - "packageDependencies": [\ - ["gauge", "npm:4.0.4"],\ - ["aproba", "npm:2.0.0"],\ - ["color-support", "npm:1.1.3"],\ - ["console-control-strings", "npm:1.1.0"],\ - ["has-unicode", "npm:2.0.1"],\ - ["signal-exit", "npm:3.0.7"],\ - ["string-width", "npm:4.2.3"],\ - ["strip-ansi", "npm:6.0.1"],\ - ["wide-align", "npm:1.1.5"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["get-caller-file", [\ ["npm:2.0.5", {\ "packageLocation": "./.yarn/cache/get-caller-file-npm-2.0.5-80e8a86305-b9769a836d.zip/node_modules/get-caller-file/",\ @@ -2550,8 +2520,8 @@ const RAW_RUNTIME_STATE = ["globby", "npm:11.1.0"],\ ["array-union", "npm:2.1.0"],\ ["dir-glob", "npm:3.0.1"],\ - ["fast-glob", "npm:3.3.1"],\ - ["ignore", "npm:5.2.4"],\ + ["fast-glob", "npm:3.3.2"],\ + ["ignore", "npm:5.3.0"],\ ["merge2", "npm:1.4.1"],\ ["slash", "npm:3.0.0"]\ ],\ @@ -2630,15 +2600,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["has-unicode", [\ - ["npm:2.0.1", {\ - "packageLocation": "./.yarn/cache/has-unicode-npm-2.0.1-893adb4747-041b4293ad.zip/node_modules/has-unicode/",\ - "packageDependencies": [\ - ["has-unicode", "npm:2.0.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["hasown", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/hasown-npm-2.0.0-78b794ceef-c330f8d93f.zip/node_modules/hasown/",\ @@ -2697,17 +2658,16 @@ const RAW_RUNTIME_STATE = ["http-proxy-agent", "npm:4.0.1"],\ ["@tootallnate/once", "npm:1.1.2"],\ ["agent-base", "npm:6.0.2"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"]\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:5.0.0", {\ - "packageLocation": "./.yarn/cache/http-proxy-agent-npm-5.0.0-7f1f121b83-5ee19423bc.zip/node_modules/http-proxy-agent/",\ + ["npm:7.0.0", {\ + "packageLocation": "./.yarn/cache/http-proxy-agent-npm-7.0.0-106a57cc8c-dbaaf3d9f3.zip/node_modules/http-proxy-agent/",\ "packageDependencies": [\ - ["http-proxy-agent", "npm:5.0.0"],\ - ["@tootallnate/once", "npm:2.0.0"],\ - ["agent-base", "npm:6.0.2"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"]\ + ["http-proxy-agent", "npm:7.0.0"],\ + ["agent-base", "npm:7.1.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -2718,17 +2678,16 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["https-proxy-agent", "npm:5.0.1"],\ ["agent-base", "npm:6.0.2"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"]\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["humanize-ms", [\ - ["npm:1.2.1", {\ - "packageLocation": "./.yarn/cache/humanize-ms-npm-1.2.1-e942bd7329-9c7a74a282.zip/node_modules/humanize-ms/",\ + }],\ + ["npm:7.0.2", {\ + "packageLocation": "./.yarn/cache/https-proxy-agent-npm-7.0.2-83ea6a5d42-9ec844f78f.zip/node_modules/https-proxy-agent/",\ "packageDependencies": [\ - ["humanize-ms", "npm:1.2.1"],\ - ["ms", "npm:2.1.3"]\ + ["https-proxy-agent", "npm:7.0.2"],\ + ["agent-base", "npm:7.1.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -2762,10 +2721,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["ignore", [\ - ["npm:5.2.4", {\ - "packageLocation": "./.yarn/cache/ignore-npm-5.2.4-fbe6e989e5-4f7caf5d20.zip/node_modules/ignore/",\ + ["npm:5.3.0", {\ + "packageLocation": "./.yarn/cache/ignore-npm-5.3.0-fb0f5fa062-51594355ce.zip/node_modules/ignore/",\ "packageDependencies": [\ - ["ignore", "npm:5.2.4"]\ + ["ignore", "npm:5.3.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -2985,6 +2944,13 @@ const RAW_RUNTIME_STATE = ["isexe", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.1.1", {\ + "packageLocation": "./.yarn/cache/isexe-npm-3.1.1-9c0061eead-7fe1931ee4.zip/node_modules/isexe/",\ + "packageDependencies": [\ + ["isexe", "npm:3.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["isobject", [\ @@ -3012,7 +2978,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/jest-worker-npm-27.5.1-1c110b5894-06c6e2a845.zip/node_modules/jest-worker/",\ "packageDependencies": [\ ["jest-worker", "npm:27.5.1"],\ - ["@types/node", "npm:20.8.7"],\ + ["@types/node", "npm:20.9.3"],\ ["merge-stream", "npm:2.0.0"],\ ["supports-color", "npm:8.1.1"]\ ],\ @@ -3093,7 +3059,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["keytar", "npm:7.9.0"],\ ["node-addon-api", "npm:4.3.0"],\ - ["node-gyp", "npm:9.4.0"],\ + ["node-gyp", "npm:10.0.1"],\ ["prebuild-install", "npm:7.1.1"]\ ],\ "linkType": "HARD"\ @@ -3206,10 +3172,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["lru-cache", [\ - ["npm:10.0.1", {\ - "packageLocation": "./.yarn/cache/lru-cache-npm-10.0.1-0e1abf4c13-5bb91a97a3.zip/node_modules/lru-cache/",\ + ["npm:10.1.0", {\ + "packageLocation": "./.yarn/cache/lru-cache-npm-10.1.0-f3d3a0f0ab-207278d6fa.zip/node_modules/lru-cache/",\ "packageDependencies": [\ - ["lru-cache", "npm:10.0.1"]\ + ["lru-cache", "npm:10.1.0"]\ ],\ "linkType": "HARD"\ }],\ @@ -3220,34 +3186,23 @@ const RAW_RUNTIME_STATE = ["yallist", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ - }],\ - ["npm:7.18.3", {\ - "packageLocation": "./.yarn/cache/lru-cache-npm-7.18.3-e68be5b11c-6029ca5aba.zip/node_modules/lru-cache/",\ - "packageDependencies": [\ - ["lru-cache", "npm:7.18.3"]\ - ],\ - "linkType": "HARD"\ }]\ ]],\ ["make-fetch-happen", [\ - ["npm:11.1.1", {\ - "packageLocation": "./.yarn/cache/make-fetch-happen-npm-11.1.1-f32b79aaaa-b4b442cfaa.zip/node_modules/make-fetch-happen/",\ + ["npm:13.0.0", {\ + "packageLocation": "./.yarn/cache/make-fetch-happen-npm-13.0.0-f87a92bb87-ded5a91a02.zip/node_modules/make-fetch-happen/",\ "packageDependencies": [\ - ["make-fetch-happen", "npm:11.1.1"],\ - ["agentkeepalive", "npm:4.5.0"],\ - ["cacache", "npm:17.1.4"],\ + ["make-fetch-happen", "npm:13.0.0"],\ + ["@npmcli/agent", "npm:2.2.0"],\ + ["cacache", "npm:18.0.1"],\ ["http-cache-semantics", "npm:4.1.1"],\ - ["http-proxy-agent", "npm:5.0.0"],\ - ["https-proxy-agent", "npm:5.0.1"],\ ["is-lambda", "npm:1.0.1"],\ - ["lru-cache", "npm:7.18.3"],\ - ["minipass", "npm:5.0.0"],\ + ["minipass", "npm:7.0.4"],\ ["minipass-fetch", "npm:3.0.4"],\ ["minipass-flush", "npm:1.0.5"],\ ["minipass-pipeline", "npm:1.2.4"],\ ["negotiator", "npm:0.6.3"],\ ["promise-retry", "npm:2.0.1"],\ - ["socks-proxy-agent", "npm:7.0.0"],\ ["ssri", "npm:10.0.5"]\ ],\ "linkType": "HARD"\ @@ -3410,11 +3365,11 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["minipass-collect", [\ - ["npm:1.0.2", {\ - "packageLocation": "./.yarn/cache/minipass-collect-npm-1.0.2-3b4676eab5-14df761028.zip/node_modules/minipass-collect/",\ + ["npm:2.0.1", {\ + "packageLocation": "./.yarn/cache/minipass-collect-npm-2.0.1-73d3907e40-b251bceea6.zip/node_modules/minipass-collect/",\ "packageDependencies": [\ - ["minipass-collect", "npm:1.0.2"],\ - ["minipass", "npm:3.3.6"]\ + ["minipass-collect", "npm:2.0.1"],\ + ["minipass", "npm:7.0.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -3615,46 +3570,45 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/unplugged/node-addon-api-npm-4.3.0-a07a1232df/node_modules/node-addon-api/",\ "packageDependencies": [\ ["node-addon-api", "npm:4.3.0"],\ - ["node-gyp", "npm:9.4.0"]\ + ["node-gyp", "npm:10.0.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["node-gyp", [\ - ["npm:9.4.0", {\ - "packageLocation": "./.yarn/unplugged/node-gyp-npm-9.4.0-ebf5f5573e/node_modules/node-gyp/",\ + ["npm:10.0.1", {\ + "packageLocation": "./.yarn/unplugged/node-gyp-npm-10.0.1-48708ce70b/node_modules/node-gyp/",\ "packageDependencies": [\ - ["node-gyp", "npm:9.4.0"],\ + ["node-gyp", "npm:10.0.1"],\ ["env-paths", "npm:2.2.1"],\ ["exponential-backoff", "npm:3.1.1"],\ - ["glob", "npm:7.2.3"],\ + ["glob", "npm:10.3.10"],\ ["graceful-fs", "npm:4.2.11"],\ - ["make-fetch-happen", "npm:11.1.1"],\ - ["nopt", "npm:6.0.0"],\ - ["npmlog", "npm:6.0.2"],\ - ["rimraf", "npm:3.0.2"],\ + ["make-fetch-happen", "npm:13.0.0"],\ + ["nopt", "npm:7.2.0"],\ + ["proc-log", "npm:3.0.0"],\ ["semver", "npm:7.5.4"],\ ["tar", "npm:6.2.0"],\ - ["which", "npm:2.0.2"]\ + ["which", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["node-releases", [\ - ["npm:2.0.13", {\ - "packageLocation": "./.yarn/cache/node-releases-npm-2.0.13-1f2e177887-c9bb813aab.zip/node_modules/node-releases/",\ + ["npm:2.0.14", {\ + "packageLocation": "./.yarn/cache/node-releases-npm-2.0.14-d39047cad8-0f7607ec7d.zip/node_modules/node-releases/",\ "packageDependencies": [\ - ["node-releases", "npm:2.0.13"]\ + ["node-releases", "npm:2.0.14"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["nopt", [\ - ["npm:6.0.0", {\ - "packageLocation": "./.yarn/cache/nopt-npm-6.0.0-5ea8050815-3c1128e07c.zip/node_modules/nopt/",\ + ["npm:7.2.0", {\ + "packageLocation": "./.yarn/cache/nopt-npm-7.2.0-dd734b678d-1e7489f17c.zip/node_modules/nopt/",\ "packageDependencies": [\ - ["nopt", "npm:6.0.0"],\ - ["abbrev", "npm:1.1.1"]\ + ["nopt", "npm:7.2.0"],\ + ["abbrev", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -3668,19 +3622,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["npmlog", [\ - ["npm:6.0.2", {\ - "packageLocation": "./.yarn/cache/npmlog-npm-6.0.2-e0e69455c7-82b123677e.zip/node_modules/npmlog/",\ - "packageDependencies": [\ - ["npmlog", "npm:6.0.2"],\ - ["are-we-there-yet", "npm:3.0.1"],\ - ["console-control-strings", "npm:1.1.0"],\ - ["gauge", "npm:4.0.4"],\ - ["set-blocking", "npm:2.0.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["nth-check", [\ ["npm:2.1.1", {\ "packageLocation": "./.yarn/cache/nth-check-npm-2.1.1-f97afc8169-5afc3dafcd.zip/node_modules/nth-check/",\ @@ -3768,18 +3709,18 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["osmium-solidity-extension", "workspace:toolchains/solidity/extension"],\ ["@types/glob", "npm:8.1.0"],\ - ["@types/mocha", "npm:10.0.3"],\ + ["@types/mocha", "npm:10.0.6"],\ ["@types/node", "npm:20.2.5"],\ - ["@types/vscode", "npm:1.83.1"],\ + ["@types/vscode", "npm:1.84.2"],\ ["@typescript-eslint/eslint-plugin", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.62.0"],\ ["@typescript-eslint/parser", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.62.0"],\ - ["@vscode/test-electron", "npm:2.3.5"],\ + ["@vscode/test-electron", "npm:2.3.8"],\ ["@vscode/vsce", "npm:2.21.1"],\ - ["eslint", "npm:8.52.0"],\ + ["eslint", "npm:8.55.0"],\ ["glob", "npm:8.1.0"],\ ["mocha", "npm:10.2.0"],\ - ["ts-loader", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.0"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"],\ + ["ts-loader", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.1"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"],\ ["vscode-languageclient", "npm:8.1.0"],\ ["vscode-languageserver", "npm:8.1.0"],\ ["vscode-languageserver-textdocument", "npm:1.0.11"],\ @@ -3935,7 +3876,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/path-scurry-npm-1.10.1-52bd946f2e-eebfb8304f.zip/node_modules/path-scurry/",\ "packageDependencies": [\ ["path-scurry", "npm:1.10.1"],\ - ["lru-cache", "npm:10.0.1"],\ + ["lru-cache", "npm:10.1.0"],\ ["minipass", "npm:7.0.4"]\ ],\ "linkType": "HARD"\ @@ -4018,10 +3959,19 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["prettier", [\ - ["npm:3.0.3", {\ - "packageLocation": "./.yarn/unplugged/prettier-npm-3.0.3-fced695dae/node_modules/prettier/",\ + ["npm:3.1.0", {\ + "packageLocation": "./.yarn/unplugged/prettier-npm-3.1.0-708d6027b1/node_modules/prettier/",\ "packageDependencies": [\ - ["prettier", "npm:3.0.3"]\ + ["prettier", "npm:3.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["proc-log", [\ + ["npm:3.0.0", {\ + "packageLocation": "./.yarn/cache/proc-log-npm-3.0.0-a8c21c2f0f-02b64e1b39.zip/node_modules/proc-log/",\ + "packageDependencies": [\ + ["proc-log", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -4058,10 +4008,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["punycode", [\ - ["npm:2.3.0", {\ - "packageLocation": "./.yarn/cache/punycode-npm-2.3.0-df4bdce06b-d4e7fbb96f.zip/node_modules/punycode/",\ + ["npm:2.3.1", {\ + "packageLocation": "./.yarn/cache/punycode-npm-2.3.1-97543c420d-febdc4362b.zip/node_modules/punycode/",\ "packageDependencies": [\ - ["punycode", "npm:2.3.0"]\ + ["punycode", "npm:2.3.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -4220,6 +4170,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["retypeapp", [\ + ["npm:3.5.0", {\ + "packageLocation": "./.yarn/unplugged/retypeapp-npm-3.5.0-c6e4adf3d1/node_modules/retypeapp/",\ + "packageDependencies": [\ + ["retypeapp", "npm:3.5.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["reusify", [\ ["npm:1.0.4", {\ "packageLocation": "./.yarn/cache/reusify-npm-1.0.4-95ac4aec11-14222c9e1d.zip/node_modules/reusify/",\ @@ -4288,7 +4247,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/schema-utils-npm-3.3.0-f2b36937f1-2c7bbb1da9.zip/node_modules/schema-utils/",\ "packageDependencies": [\ ["schema-utils", "npm:3.3.0"],\ - ["@types/json-schema", "npm:7.0.14"],\ + ["@types/json-schema", "npm:7.0.15"],\ ["ajv", "npm:6.12.6"],\ ["ajv-keywords", "virtual:f2b36937f163b579815d3163513b3330d7a31aaf0599eea66346382b8838395c613f4204e9809cc2ff6bba09c17ab0c34b37deadcb147de7e2f5e535d6ccc245#npm:3.5.2"]\ ],\ @@ -4330,15 +4289,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["set-blocking", [\ - ["npm:2.0.0", {\ - "packageLocation": "./.yarn/cache/set-blocking-npm-2.0.0-49e2cffa24-8980ebf7ae.zip/node_modules/set-blocking/",\ - "packageDependencies": [\ - ["set-blocking", "npm:2.0.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["set-function-length", [\ ["npm:1.1.1", {\ "packageLocation": "./.yarn/cache/set-function-length-npm-1.1.1-d362bf8221-745ed1d7dc.zip/node_modules/set-function-length/",\ @@ -4403,13 +4353,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["signal-exit", [\ - ["npm:3.0.7", {\ - "packageLocation": "./.yarn/cache/signal-exit-npm-3.0.7-bd270458a3-a2f098f247.zip/node_modules/signal-exit/",\ - "packageDependencies": [\ - ["signal-exit", "npm:3.0.7"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:4.1.0", {\ "packageLocation": "./.yarn/cache/signal-exit-npm-4.1.0-61fb957687-c9fa63bbbd.zip/node_modules/signal-exit/",\ "packageDependencies": [\ @@ -4469,12 +4412,12 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["socks-proxy-agent", [\ - ["npm:7.0.0", {\ - "packageLocation": "./.yarn/cache/socks-proxy-agent-npm-7.0.0-7aacf32ea0-26c75d9c62.zip/node_modules/socks-proxy-agent/",\ + ["npm:8.0.2", {\ + "packageLocation": "./.yarn/cache/socks-proxy-agent-npm-8.0.2-df165543cf-ea727734bd.zip/node_modules/socks-proxy-agent/",\ "packageDependencies": [\ - ["socks-proxy-agent", "npm:7.0.0"],\ - ["agent-base", "npm:6.0.2"],\ - ["debug", "virtual:feb0771c9f8eadaf509cfed41e14a8bebbea5442233275c1c87085111077a08ef71eb773b899665b154d8203a55a489610a54117ae059fce5f5b8b844493b1b1#npm:4.3.4"],\ + ["socks-proxy-agent", "npm:8.0.2"],\ + ["agent-base", "npm:7.1.0"],\ + ["debug", "virtual:1ff4b5f90832ba0a9c93ba1223af226e44ba70c1126a3740d93562b97bc36544e896a5e95908196f7458713e6a6089a34bfc67362fc6df7fa093bd06c878be47#npm:4.3.4"],\ ["socks", "npm:2.7.1"]\ ],\ "linkType": "HARD"\ @@ -4678,12 +4621,12 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["terser", [\ - ["npm:5.22.0", {\ - "packageLocation": "./.yarn/cache/terser-npm-5.22.0-e83cb45628-e5407f9a14.zip/node_modules/terser/",\ + ["npm:5.24.0", {\ + "packageLocation": "./.yarn/cache/terser-npm-5.24.0-0761eb3a43-bd7ba6bfef.zip/node_modules/terser/",\ "packageDependencies": [\ - ["terser", "npm:5.22.0"],\ + ["terser", "npm:5.24.0"],\ ["@jridgewell/source-map", "npm:0.3.5"],\ - ["acorn", "npm:8.10.0"],\ + ["acorn", "npm:8.11.2"],\ ["commander", "npm:2.20.3"],\ ["source-map-support", "npm:0.5.21"]\ ],\ @@ -4712,7 +4655,7 @@ const RAW_RUNTIME_STATE = ["jest-worker", "npm:27.5.1"],\ ["schema-utils", "npm:3.3.0"],\ ["serialize-javascript", "npm:6.0.1"],\ - ["terser", "npm:5.22.0"],\ + ["terser", "npm:5.24.0"],\ ["uglify-js", null],\ ["webpack", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.89.0"]\ ],\ @@ -4759,17 +4702,17 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["ts-loader", [\ - ["npm:9.5.0", {\ - "packageLocation": "./.yarn/cache/ts-loader-npm-9.5.0-9514617263-8ffc6411ec.zip/node_modules/ts-loader/",\ + ["npm:9.5.1", {\ + "packageLocation": "./.yarn/cache/ts-loader-npm-9.5.1-c8a0456e30-a85d43bb6f.zip/node_modules/ts-loader/",\ "packageDependencies": [\ - ["ts-loader", "npm:9.5.0"]\ + ["ts-loader", "npm:9.5.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.0", {\ - "packageLocation": "./.yarn/__virtual__/ts-loader-virtual-08d411a35a/0/cache/ts-loader-npm-9.5.0-9514617263-8ffc6411ec.zip/node_modules/ts-loader/",\ + ["virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.1", {\ + "packageLocation": "./.yarn/__virtual__/ts-loader-virtual-d5e66fccdc/0/cache/ts-loader-npm-9.5.1-c8a0456e30-a85d43bb6f.zip/node_modules/ts-loader/",\ "packageDependencies": [\ - ["ts-loader", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.0"],\ + ["ts-loader", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:9.5.1"],\ ["@types/typescript", null],\ ["@types/webpack", null],\ ["chalk", "npm:4.1.2"],\ @@ -4777,7 +4720,7 @@ const RAW_RUNTIME_STATE = ["micromatch", "npm:4.0.5"],\ ["semver", "npm:7.5.4"],\ ["source-map", "npm:0.7.4"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"],\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"],\ ["webpack", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.89.0"]\ ],\ "packagePeers": [\ @@ -4826,7 +4769,7 @@ const RAW_RUNTIME_STATE = ["tsutils", "virtual:89014fb2f72da20eb87d54c80bac37610b57a73485dee5ebf9333bf5c4bce0d972953cbf0f48420b275d3bc40f36aded8d47d2d24281f85e903e5d354ec64e4e#npm:3.21.0"],\ ["@types/typescript", null],\ ["tslib", "npm:1.14.1"],\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -4886,10 +4829,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["typescript", [\ - ["patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441", {\ - "packageLocation": "./.yarn/cache/typescript-patch-3914634c3a-f79cc2ba80.zip/node_modules/typescript/",\ + ["patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7", {\ + "packageLocation": "./.yarn/cache/typescript-patch-71fdfda6a2-1b45cdfb57.zip/node_modules/typescript/",\ "packageDependencies": [\ - ["typescript", "patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441"]\ + ["typescript", "patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7"]\ ],\ "linkType": "HARD"\ }]\ @@ -4913,10 +4856,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["undici-types", [\ - ["npm:5.25.3", {\ - "packageLocation": "./.yarn/cache/undici-types-npm-5.25.3-2ac9eafc9e-9a57f2dd6f.zip/node_modules/undici-types/",\ + ["npm:5.26.5", {\ + "packageLocation": "./.yarn/cache/undici-types-npm-5.26.5-de4f7c7bb9-0097779d94.zip/node_modules/undici-types/",\ "packageDependencies": [\ - ["undici-types", "npm:5.25.3"]\ + ["undici-types", "npm:5.26.5"]\ ],\ "linkType": "HARD"\ }]\ @@ -4949,12 +4892,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:cccae6d74e613cbaceb4c608cb01004dea3f5ca235673f5c541d60f516ef320907d258256abf63eac9b8704e23cf5d52eb19f2a57a07471accc943ea645de308#npm:1.0.13", {\ - "packageLocation": "./.yarn/__virtual__/update-browserslist-db-virtual-1935275eaa/0/cache/update-browserslist-db-npm-1.0.13-ea7b8ee24d-9074b4ef34.zip/node_modules/update-browserslist-db/",\ + ["virtual:87e70d802146e5a0e8f2a12b5ab64004040c6640441dba54229a7db766cb1b88edabd3d3c814ce33d6ba839c4e517b12e9b0a7febfca22ac2a64177042bf3ee6#npm:1.0.13", {\ + "packageLocation": "./.yarn/__virtual__/update-browserslist-db-virtual-1f2a8df3c3/0/cache/update-browserslist-db-npm-1.0.13-ea7b8ee24d-9074b4ef34.zip/node_modules/update-browserslist-db/",\ "packageDependencies": [\ - ["update-browserslist-db", "virtual:cccae6d74e613cbaceb4c608cb01004dea3f5ca235673f5c541d60f516ef320907d258256abf63eac9b8704e23cf5d52eb19f2a57a07471accc943ea645de308#npm:1.0.13"],\ + ["update-browserslist-db", "virtual:87e70d802146e5a0e8f2a12b5ab64004040c6640441dba54229a7db766cb1b88edabd3d3c814ce33d6ba839c4e517b12e9b0a7febfca22ac2a64177042bf3ee6#npm:1.0.13"],\ ["@types/browserslist", null],\ - ["browserslist", "npm:4.22.1"],\ + ["browserslist", "npm:4.22.2"],\ ["escalade", "npm:3.1.1"],\ ["picocolors", "npm:1.0.0"]\ ],\ @@ -4970,7 +4913,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/uri-js-npm-4.4.1-66d11cbcaf-b271ca7e3d.zip/node_modules/uri-js/",\ "packageDependencies": [\ ["uri-js", "npm:4.4.1"],\ - ["punycode", "npm:2.3.0"]\ + ["punycode", "npm:2.3.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -5076,18 +5019,18 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/__virtual__/webpack-virtual-b98590e618/0/cache/webpack-npm-5.89.0-3800e9efd0-ee19b07027.zip/node_modules/webpack/",\ "packageDependencies": [\ ["webpack", "virtual:2b9e7e7d573ed38308251d9cfa9bcac1c01394d20ff25d4a07b4a0345be370b65803551137c4363442bf76c7d6f9363387c180207a65457c6616ca7fd9b2a56b#npm:5.89.0"],\ - ["@types/eslint-scope", "npm:3.7.6"],\ - ["@types/estree", "npm:1.0.3"],\ + ["@types/eslint-scope", "npm:3.7.7"],\ + ["@types/estree", "npm:1.0.5"],\ ["@types/webpack-cli", null],\ ["@webassemblyjs/ast", "npm:1.11.6"],\ ["@webassemblyjs/wasm-edit", "npm:1.11.6"],\ ["@webassemblyjs/wasm-parser", "npm:1.11.6"],\ - ["acorn", "npm:8.10.0"],\ + ["acorn", "npm:8.11.2"],\ ["acorn-import-assertions", "virtual:b98590e6182f1e3e809675a880704d2c50533e40386e60683f5d6ae6206f5e5e58cf33b625935351b9a4ef2066acd33ce7f25a0d7055a7a23f1ec398f2c56b3f#npm:1.9.0"],\ - ["browserslist", "npm:4.22.1"],\ + ["browserslist", "npm:4.22.2"],\ ["chrome-trace-event", "npm:1.0.3"],\ ["enhanced-resolve", "npm:5.15.0"],\ - ["es-module-lexer", "npm:1.3.1"],\ + ["es-module-lexer", "npm:1.4.1"],\ ["eslint-scope", "npm:5.1.1"],\ ["events", "npm:3.3.0"],\ ["glob-to-regexp", "npm:0.4.1"],\ @@ -5134,7 +5077,7 @@ const RAW_RUNTIME_STATE = ["colorette", "npm:2.0.20"],\ ["commander", "npm:10.0.1"],\ ["cross-spawn", "npm:7.0.3"],\ - ["envinfo", "npm:7.10.0"],\ + ["envinfo", "npm:7.11.0"],\ ["fastest-levenshtein", "npm:1.0.16"],\ ["import-local", "npm:3.1.0"],\ ["interpret", "npm:3.1.1"],\ @@ -5186,14 +5129,12 @@ const RAW_RUNTIME_STATE = ["isexe", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ - }]\ - ]],\ - ["wide-align", [\ - ["npm:1.1.5", {\ - "packageLocation": "./.yarn/cache/wide-align-npm-1.1.5-889d77e592-d5f8027b9a.zip/node_modules/wide-align/",\ + }],\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/which-npm-4.0.0-dd31cd4928-f17e84c042.zip/node_modules/which/",\ "packageDependencies": [\ - ["wide-align", "npm:1.1.5"],\ - ["string-width", "npm:4.2.3"]\ + ["which", "npm:4.0.0"],\ + ["isexe", "npm:3.1.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -6757,6 +6698,12 @@ class ProxiedFS extends FakeFS { } } +function direntToPortable(dirent) { + const portableDirent = dirent; + if (typeof dirent.path === `string`) + portableDirent.path = npath.toPortablePath(dirent.path); + return portableDirent; +} class NodeFS extends BasePortableFakeFS { constructor(realFs = fs__default.default) { super(); @@ -7083,15 +7030,31 @@ class NodeFS extends BasePortableFakeFS { async readdirPromise(p, opts) { return await new Promise((resolve, reject) => { if (opts) { - this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + if (opts.recursive && process.platform === `win32`) { + if (opts.withFileTypes) { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback((results) => resolve(results.map(direntToPortable)), reject)); + } else { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback((results) => resolve(results.map(npath.toPortablePath)), reject)); + } + } else { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } } else { - this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); + this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); } }); } readdirSync(p, opts) { if (opts) { - return this.realFs.readdirSync(npath.fromPortablePath(p), opts); + if (opts.recursive && process.platform === `win32`) { + if (opts.withFileTypes) { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts).map(direntToPortable); + } else { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts).map(npath.toPortablePath); + } + } else { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts); + } } else { return this.realFs.readdirSync(npath.fromPortablePath(p)); } diff --git a/.pnp.loader.mjs b/.pnp.loader.mjs index 928eae83..fe96ee1d 100644 --- a/.pnp.loader.mjs +++ b/.pnp.loader.mjs @@ -902,6 +902,12 @@ class ProxiedFS extends FakeFS { } } +function direntToPortable(dirent) { + const portableDirent = dirent; + if (typeof dirent.path === `string`) + portableDirent.path = npath.toPortablePath(dirent.path); + return portableDirent; +} class NodeFS extends BasePortableFakeFS { constructor(realFs = fs) { super(); @@ -1228,15 +1234,31 @@ class NodeFS extends BasePortableFakeFS { async readdirPromise(p, opts) { return await new Promise((resolve, reject) => { if (opts) { - this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + if (opts.recursive && process.platform === `win32`) { + if (opts.withFileTypes) { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback((results) => resolve(results.map(direntToPortable)), reject)); + } else { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback((results) => resolve(results.map(npath.toPortablePath)), reject)); + } + } else { + this.realFs.readdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } } else { - this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); + this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); } }); } readdirSync(p, opts) { if (opts) { - return this.realFs.readdirSync(npath.fromPortablePath(p), opts); + if (opts.recursive && process.platform === `win32`) { + if (opts.withFileTypes) { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts).map(direntToPortable); + } else { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts).map(npath.toPortablePath); + } + } else { + return this.realFs.readdirSync(npath.fromPortablePath(p), opts); + } } else { return this.realFs.readdirSync(npath.fromPortablePath(p)); } @@ -1372,7 +1394,7 @@ class VirtualFS extends ProxiedFS { const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10)); const WATCH_MODE_MESSAGE_USES_ARRAYS = major > 19 || major === 19 && minor >= 2 || major === 18 && minor >= 13; -const HAS_LAZY_LOADED_TRANSLATORS = major > 19 || major === 19 && minor >= 3; +const HAS_LAZY_LOADED_TRANSLATORS = major === 20 && minor < 6 || major === 19 && minor >= 3; function readPackageScope(checkPath) { const rootSeparatorIndex = checkPath.indexOf(npath.sep); @@ -2020,31 +2042,46 @@ async function resolve$1(originalSpecifier, context, nextResolve) { if (!HAS_LAZY_LOADED_TRANSLATORS) { const binding = process.binding(`fs`); - const originalfstat = binding.fstat; - const ZIP_MASK = 4278190080; - const ZIP_MAGIC = 704643072; - binding.fstat = function(...args) { - const [fd, useBigint, req] = args; - if ((fd & ZIP_MASK) === ZIP_MAGIC && useBigint === false && req === void 0) { + const originalReadFile = binding.readFileUtf8 || binding.readFileSync; + if (originalReadFile) { + binding[originalReadFile.name] = function(...args) { try { - const stats = fs.fstatSync(fd); - return new Float64Array([ - stats.dev, - stats.mode, - stats.nlink, - stats.uid, - stats.gid, - stats.rdev, - stats.blksize, - stats.ino, - stats.size, - stats.blocks - ]); + return fs.readFileSync(args[0], { + encoding: `utf8`, + flag: args[1] + }); } catch { } - } - return originalfstat.apply(this, args); - }; + return originalReadFile.apply(this, args); + }; + } else { + const binding2 = process.binding(`fs`); + const originalfstat = binding2.fstat; + const ZIP_MASK = 4278190080; + const ZIP_MAGIC = 704643072; + binding2.fstat = function(...args) { + const [fd, useBigint, req] = args; + if ((fd & ZIP_MASK) === ZIP_MAGIC && useBigint === false && req === void 0) { + try { + const stats = fs.fstatSync(fd); + return new Float64Array([ + stats.dev, + stats.mode, + stats.nlink, + stats.uid, + stats.gid, + stats.rdev, + stats.blksize, + stats.ino, + stats.size, + stats.blocks + ]); + } catch { + } + } + return originalfstat.apply(this, args); + }; + } } const resolve = resolve$1; diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000..41360351 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +*/**.md diff --git a/doc/createMarkdownFilesFromJsonArray.js b/doc/createMarkdownFilesFromJsonArray.js new file mode 100644 index 00000000..732dd8bc --- /dev/null +++ b/doc/createMarkdownFilesFromJsonArray.js @@ -0,0 +1,106 @@ +import { promises as fs } from 'fs'; +import { dirname } from 'path'; + +async function readFileContent(filePath) { + try { + const content = await fs.readFile(filePath, 'utf8'); + return content; + } catch (error) { + throw error; + } +} + +async function saveToFile(filepath, content) { + try { + const directory = dirname(filepath); + await fs.mkdir(directory, { recursive: true }); + await fs.writeFile(filepath, content, 'utf8'); + } catch (err) { + console.error('Error creating the file:', err); + } +} + +const parseJson = (rule) => { + let content = ""; + + const categoryFormated = rule.category.replace("-", "_"); + content += `![](https://img.shields.io/badge/${categoryFormated}-green)\t`; + content += `![](https://img.shields.io/badge/Default%20Severity-${rule.severity}-yellow)\n\n`; + content += "## Description\n"; + content += `${rule.description}\n\n`; + content += "## Options\n"; + if (rule.options.length) { + content += "description | default\n"; + content += "------------ | -------------\n"; + for (const option of rule.options) { + content += `${option.description} | ${option.default}\n`; + } + } else { + content += "This rule does not require any options.\n"; + } + + content += "## Example Config\n"; + if (rule.example_config) { + const exampleConfig = JSON.stringify(JSON.parse(rule.example_config),null,2); + content += "```json\n"; + content += `${exampleConfig}\n`; + content += "```\n\n"; + } + content += "## Examples\n"; + content += "### Good\n"; + if (rule.examples.good.length) { + for (const example of rule.examples.good) { + content += `${example.description}\n`; + content += "```solidity\n"; + content += `${example.code}\n`; + content += "```\n\n"; + } + } else { + content += "This rule does not have good examples.\n"; + } + content += "### Bad\n"; + if (rule.examples.bad.length) { + for (const example of rule.examples.bad) { + content += `${example.description}\n`; + content += "```solidity\n"; + content += `${example.code}\n`; + content += "```\n\n"; + } + } else { + content += "This rule does not have bad examples.\n"; + } + content += "## References\n"; + content += `* [Rule source](${rule.source_link})\n`; + content += `* [Test](${rule.test_link})\n`; + return content; +} + +async function createMarkdownFilesFromJsonArray(path) { + const fileContent = await readFileContent(path); + const jsonContent = JSON.parse(fileContent); + for (const key in jsonContent) { + let content = ''; + const rule = jsonContent[key]; + const body = parseJson(rule); + content += `# ${rule.id}\n\n` + body; + saveToFile(`./${rule.category}/${rule.id}.md`, content); + } +} + +async function main() { + const args = process.argv.slice(2); + let filepath = "./docTree.json" + + if (args.length !== 0) { + filepath = args[0]; + } + + try { + await fs.access(filepath, fs.constants.F_OK); + createMarkdownFilesFromJsonArray(filepath); + } catch (err) { + console.error('The file does not exist.\n', err); + } +} + +main(); \ No newline at end of file diff --git a/doc/package.json b/doc/package.json new file mode 100644 index 00000000..5a6bc917 --- /dev/null +++ b/doc/package.json @@ -0,0 +1,8 @@ +{ + "name": "doc", + "packageManager": "yarn@4.0.1", + "type": "module", + "dependencies": { + "retypeapp": "^3.5.0" + } +} diff --git a/doc/readme.md b/doc/readme.md new file mode 100644 index 00000000..d95490f2 --- /dev/null +++ b/doc/readme.md @@ -0,0 +1,4 @@ +# Welcome + +Welcome to our Linter Rules Documentation. Here you will find all the rules implemented in our linter. + diff --git a/doc/retype.yml b/doc/retype.yml new file mode 100644 index 00000000..242ffd19 --- /dev/null +++ b/doc/retype.yml @@ -0,0 +1,8 @@ +input: . +output: .retype +url: # Add your website address here +branding: + title: Osmium Toolchain + label: Docs +footer: + copyright: "© Copyright {{ year }}. All rights reserved." \ No newline at end of file diff --git a/libs/foundry-wrapper/Cargo.lock b/libs/foundry-wrapper/Cargo.lock new file mode 100644 index 00000000..6fa66b36 --- /dev/null +++ b/libs/foundry-wrapper/Cargo.lock @@ -0,0 +1,419 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a318f1f38d2418400f8209655bfd825785afd25aa30bb7ba6cc792e4596748" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "clap" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "osmium-libs-foundry-wrapper" +version = "0.1.0" +dependencies = [ + "clap", + "glob", + "serde", + "serde_json", + "thiserror", + "which", +] + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustix" +version = "0.38.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "which" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/libs/foundry-wrapper/Cargo.toml b/libs/foundry-wrapper/Cargo.toml new file mode 100644 index 00000000..acc4194d --- /dev/null +++ b/libs/foundry-wrapper/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "osmium-libs-foundry-wrapper" +version = "0.1.0" +edition = "2021" +authors = ["Astrodevs-Labs"] +description = "Foundry abstractions for all extensions" +license = "GPL-3.0-or-later" +repository = "https://github.com/astrodevs-labs/osmium" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +glob = "0.3.1" +clap = "4.4.8" +thiserror = "1.0.50" +which = "5.0" +serde = { version = "1.0.149", features = ["derive"] } +serde_json = "1.0.108" diff --git a/libs/foundry-wrapper/LICENSE.txt b/libs/foundry-wrapper/LICENSE.txt new file mode 100644 index 00000000..5dc6b429 --- /dev/null +++ b/libs/foundry-wrapper/LICENSE.txt @@ -0,0 +1,675 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/libs/foundry-wrapper/package.json b/libs/foundry-wrapper/package.json new file mode 100644 index 00000000..995e5e7a --- /dev/null +++ b/libs/foundry-wrapper/package.json @@ -0,0 +1,10 @@ +{ + "name": "@osmium-libs/foundry-wrapper", + "scripts": { + "build": "cargo build --release", + "format": "cargo fmt --check --all", + "test": "cargo test", + "lint": "cargo clippy --all-targets --all-features -- -D warnings", + "publish": "cargo package && cargo publish" + } +} diff --git a/libs/foundry-wrapper/src/compiler.rs b/libs/foundry-wrapper/src/compiler.rs new file mode 100644 index 00000000..8dfbf367 --- /dev/null +++ b/libs/foundry-wrapper/src/compiler.rs @@ -0,0 +1,74 @@ +use crate::{ + error::Error, + types::ProjectCompileOutput, + utils::{ + check_executable_argument, find_forge_executable, find_projects_paths, normalize_path, + }, +}; +use std::process::Command; + +#[derive(Debug)] +struct CompilerInner { + root_path: String, + workspaces: Vec, + executable_path: String, +} + +#[derive(Debug)] +pub struct Compiler { + inner: CompilerInner, +} + +impl Compiler { + pub fn new_with_executable_check() -> Result { + let executable_path = find_forge_executable()?; + check_executable_argument(executable_path.to_str().unwrap_or_default())?; + Ok(Self { + inner: CompilerInner { + root_path: String::new(), + workspaces: Vec::new(), + executable_path: executable_path.to_str().unwrap_or_default().to_string(), + }, + }) + } + + fn find_closest_workspace(&self, file_path: &str) -> Option { + let filepath = normalize_path(file_path); + self.inner + .workspaces + .iter() + .filter(|path| filepath.starts_with(path.as_str())) + .max_by_key(|path| path.len()) + .map(|path| path.to_string()) + } + + pub fn load_workspace(&mut self, root_folder: String) -> Result<(), Error> { + let paths = find_projects_paths(&root_folder)?; + for path in paths { + if let Some(path) = path.to_str() { + self.inner.workspaces.push(normalize_path(path)); + } + } + self.inner.root_path = root_folder; + Ok(()) + } + + pub fn reload_project_for_file(&mut self, _: &str) -> Result<(), Error> { + Ok(()) + } + + pub fn compile(&mut self, file_path: &str) -> Result<(String, ProjectCompileOutput), Error> { + let workspace_path = self + .find_closest_workspace(file_path) + .ok_or_else(|| Error::InvalidFilePath(file_path.to_string()))?; + let json = Command::new(&self.inner.executable_path) + .current_dir(&workspace_path) + .arg("compile") + .arg("--format-json") + .output() + .map_err(Error::ExecutableError)?; + let output_str = String::from_utf8_lossy(&json.stdout); + let compile_output: ProjectCompileOutput = serde_json::from_str(&output_str)?; + Ok((workspace_path, compile_output)) + } +} diff --git a/libs/foundry-wrapper/src/error.rs b/libs/foundry-wrapper/src/error.rs new file mode 100644 index 00000000..13736e48 --- /dev/null +++ b/libs/foundry-wrapper/src/error.rs @@ -0,0 +1,25 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("Workspace loading error: {0}")] + InvalidRootPath(#[from] glob::PatternError), + + #[error("Invalid file path: {0}")] + InvalidFilePath(String), + + #[error("Executable error: foundry executable not found")] + FoundryExecutableNotFound, + + #[error("Invalid foundry version: does not support --format-json")] + InvalidFoundryVersion, + + #[error("Executable error: {0}")] + ExecutableError(std::io::Error), + + #[error("No executable build-info file: {0}")] + NoExecutableBuildInfoFile(String), + + #[error("Invalid json output: {0}")] + InvalidJsonOutput(#[from] serde_json::Error), +} diff --git a/libs/foundry-wrapper/src/lib.rs b/libs/foundry-wrapper/src/lib.rs new file mode 100644 index 00000000..e7db777d --- /dev/null +++ b/libs/foundry-wrapper/src/lib.rs @@ -0,0 +1,10 @@ +mod utils; + +mod types; +pub use types::*; + +mod compiler; +pub use compiler::*; + +mod error; +pub use error::*; diff --git a/libs/foundry-wrapper/src/types.rs b/libs/foundry-wrapper/src/types.rs new file mode 100644 index 00000000..cbd1b12c --- /dev/null +++ b/libs/foundry-wrapper/src/types.rs @@ -0,0 +1,123 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ProjectCompileOutput { + errors: Vec, +} + +impl ProjectCompileOutput { + pub fn get_errors(&self) -> &Vec { + self.errors.as_ref() + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CompilationError { + #[serde(rename = "sourceLocation")] + source_location: Option, + #[serde(rename = "type")] + typ: String, + component: String, + severity: String, + #[serde(rename = "errorCode")] + error_code: String, + message: String, + #[serde(rename = "formattedMessage")] + formatted_message: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +struct SourceLocation { + file: String, + start: i32, + end: i32, +} + +impl CompilationError { + pub fn get_message(&self) -> String { + self.message.clone() + } + + pub fn get_file_path(&self) -> Option { + Some(self.source_location.clone()?.file.clone()) + } + + pub fn get_start_idx(&self) -> Option { + Some(self.source_location.clone()?.start) + } + + pub fn get_end_idx(&self) -> Option { + Some(self.source_location.clone()?.end) + } + + pub fn get_start_position(&self, source_content: &str) -> Option { + let idx = self.get_start_idx()?; + Position::from_index(idx, source_content) + } + + pub fn get_end_position(&self, source_content: &str) -> Option { + let idx = self.get_end_idx()?; + Position::from_index(idx, source_content) + } + + pub fn get_range(&self, source_content: &str) -> Option { + Some(Range { + start: self.get_start_position(source_content)?, + end: self.get_end_position(source_content)?, + }) + } + + pub fn get_severity(&self) -> Severity { + self.severity.clone().into() + } +} + +/** + * Position of error, 0 based indexes + */ +#[derive(Clone, Debug)] +pub struct Position { + pub line: u32, + pub column: u32, +} + +impl Position { + pub fn from_index(idx: i32, source: &str) -> Option { + let mut idx: usize = idx as usize; + for (i, l) in source.split('\n').enumerate() { + let line_length = l.len() + if l.ends_with('\r') { 2 } else { 1 }; + if idx < line_length { + return Some(Self { + line: i as u32, + column: idx as u32, + }); + } + idx -= line_length + } + None + } +} + +#[derive(Clone, Debug)] +pub struct Range { + pub start: Position, + pub end: Position, +} + +#[derive(Clone, Debug)] +pub enum Severity { + Error, + Warning, + Info, +} + +impl From for Severity { + fn from(severity: String) -> Self { + match severity { + s if s.to_uppercase() == "ERROR" => Self::Error, + s if s.to_uppercase() == "WARNING" => Self::Warning, + s if s.to_uppercase() == "INFO" => Self::Info, + _ => Self::Info, + } + } +} diff --git a/libs/foundry-wrapper/src/utils.rs b/libs/foundry-wrapper/src/utils.rs new file mode 100644 index 00000000..da523b06 --- /dev/null +++ b/libs/foundry-wrapper/src/utils.rs @@ -0,0 +1,5 @@ +mod executable; +pub use executable::*; + +mod path; +pub use path::*; diff --git a/libs/foundry-wrapper/src/utils/executable.rs b/libs/foundry-wrapper/src/utils/executable.rs new file mode 100644 index 00000000..32fd70dc --- /dev/null +++ b/libs/foundry-wrapper/src/utils/executable.rs @@ -0,0 +1,20 @@ +use crate::Error; +use std::path::PathBuf; + +pub fn find_forge_executable() -> Result { + which::which("forge").map_err(|_| Error::FoundryExecutableNotFound) +} + +pub fn check_executable_argument(executable_path: &str) -> Result<(), Error> { + let output = std::process::Command::new(executable_path) + .arg("compile") + .arg("--format-json") + .output() + .map_err(Error::ExecutableError)?; + + let stderr_str = String::from_utf8_lossy(&output.stderr); + if stderr_str.contains("unexpected argument '--format-json'") { + return Err(Error::InvalidFoundryVersion); + } + Ok(()) +} diff --git a/libs/foundry-wrapper/src/utils/path.rs b/libs/foundry-wrapper/src/utils/path.rs new file mode 100644 index 00000000..87277f6b --- /dev/null +++ b/libs/foundry-wrapper/src/utils/path.rs @@ -0,0 +1,21 @@ +use glob::glob; +use std::path::PathBuf; + +pub fn find_projects_paths(root_path: &str) -> Result, glob::PatternError> { + let pattern = format!("{}/**/foundry.toml", root_path); + let filespaths = glob(&pattern)? + .filter_map(|path| path.ok()) + .collect::>(); + + // remove foundry.toml at the end of the filepath + Ok(filespaths + .iter() + .map(|path| path.parent().unwrap().to_path_buf()) + .collect()) +} + +pub fn normalize_path(path: &str) -> String { + path.replace('\\', "/") + .replace("//", "/") + .replace("\\\\", "/") +} diff --git a/libs/lsp-handler/src/dispatcher.rs b/libs/lsp-handler/src/dispatcher.rs index e1826e93..cd596129 100644 --- a/libs/lsp-handler/src/dispatcher.rs +++ b/libs/lsp-handler/src/dispatcher.rs @@ -988,11 +988,11 @@ impl Dispatcher { } impl Handler for Dispatcher { - fn initialize(&self, params: InitializeParams) -> Result { + fn initialize(&mut self, params: InitializeParams) -> Result { let mut res = vec![]; self.connection .log_message(MessageType::INFO, "Dispatcher initializing"); - for handler in &self.handlers { + for handler in &mut self.handlers { res.push(handler.initialize(params.clone())); } let res: Vec = res.iter().filter_map(|i| i.clone().ok()).collect(); @@ -1252,45 +1252,45 @@ impl Handler for Dispatcher { Ok(result) } - fn initialized(&self, params: InitializedParams) { + fn initialized(&mut self, params: InitializedParams) { self.connection .log_message(MessageType::INFO, "Dispatcher initialized"); - for handler in &self.handlers { + for handler in &mut self.handlers { handler.initialized(params); } } - fn shutdown(&self) -> Result<()> { - for handler in &self.handlers { + fn shutdown(&mut self) -> Result<()> { + for handler in &mut self.handlers { let _ = handler.shutdown(); } Ok(()) } - fn did_open(&self, params: DidOpenTextDocumentParams) { - for handler in &self.handlers { + fn did_open(&mut self, params: DidOpenTextDocumentParams) { + for handler in &mut self.handlers { handler.did_open(params.clone()); } } - fn did_change(&self, params: DidChangeTextDocumentParams) { - for handler in &self.handlers { + fn did_change(&mut self, params: DidChangeTextDocumentParams) { + for handler in &mut self.handlers { handler.did_change(params.clone()); } } - fn will_save(&self, params: WillSaveTextDocumentParams) { - for handler in &self.handlers { + fn will_save(&mut self, params: WillSaveTextDocumentParams) { + for handler in &mut self.handlers { handler.will_save(params.clone()); } } fn will_save_wait_until( - &self, + &mut self, params: WillSaveTextDocumentParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.will_save_wait_until(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1299,23 +1299,23 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn did_save(&self, params: DidSaveTextDocumentParams) { - for handler in &self.handlers { + fn did_save(&mut self, params: DidSaveTextDocumentParams) { + for handler in &mut self.handlers { handler.did_save(params.clone()); } } - fn did_close(&self, params: DidCloseTextDocumentParams) { - for handler in &self.handlers { + fn did_close(&mut self, params: DidCloseTextDocumentParams) { + for handler in &mut self.handlers { handler.did_close(params.clone()); } } fn goto_declaration( - &self, + &mut self, params: GotoDeclarationParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.goto_declaration(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1325,10 +1325,10 @@ impl Handler for Dispatcher { } fn goto_definition( - &self, + &mut self, params: GotoDefinitionParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.goto_definition(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1338,10 +1338,10 @@ impl Handler for Dispatcher { } fn goto_type_definition( - &self, + &mut self, params: GotoTypeDefinitionParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.goto_type_definition(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1351,10 +1351,10 @@ impl Handler for Dispatcher { } fn goto_implementation( - &self, + &mut self, params: GotoImplementationParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.goto_implementation(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1363,9 +1363,9 @@ impl Handler for Dispatcher { Ok(None) } - fn references(&self, params: ReferenceParams) -> Result>> { + fn references(&mut self, params: ReferenceParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.references(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1375,11 +1375,11 @@ impl Handler for Dispatcher { } fn prepare_call_hierarchy( - &self, + &mut self, params: CallHierarchyPrepareParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.prepare_call_hierarchy(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1389,11 +1389,11 @@ impl Handler for Dispatcher { } fn incoming_calls( - &self, + &mut self, params: CallHierarchyIncomingCallsParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.incoming_calls(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1403,11 +1403,11 @@ impl Handler for Dispatcher { } fn outgoing_calls( - &self, + &mut self, params: CallHierarchyOutgoingCallsParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.outgoing_calls(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1417,11 +1417,11 @@ impl Handler for Dispatcher { } fn prepare_type_hierarchy( - &self, + &mut self, params: TypeHierarchyPrepareParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.prepare_type_hierarchy(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1431,11 +1431,11 @@ impl Handler for Dispatcher { } fn supertypes( - &self, + &mut self, params: TypeHierarchySupertypesParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.supertypes(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1445,11 +1445,11 @@ impl Handler for Dispatcher { } fn subtypes( - &self, + &mut self, params: TypeHierarchySubtypesParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.subtypes(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1459,11 +1459,11 @@ impl Handler for Dispatcher { } fn document_highlight( - &self, + &mut self, params: DocumentHighlightParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.document_highlight(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1472,9 +1472,9 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn document_link(&self, params: DocumentLinkParams) -> Result>> { + fn document_link(&mut self, params: DocumentLinkParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.document_link(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1483,8 +1483,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn document_link_resolve(&self, params: DocumentLink) -> Result { - for handler in &self.handlers { + fn document_link_resolve(&mut self, params: DocumentLink) -> Result { + for handler in &mut self.handlers { let res = handler.document_link_resolve(params.clone()); if res.is_ok() { return res; @@ -1493,8 +1493,8 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn hover(&self, params: HoverParams) -> Result> { - for handler in &self.handlers { + fn hover(&mut self, params: HoverParams) -> Result> { + for handler in &mut self.handlers { let res = handler.hover(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1503,9 +1503,9 @@ impl Handler for Dispatcher { Ok(None) } - fn code_lens(&self, params: CodeLensParams) -> Result>> { + fn code_lens(&mut self, params: CodeLensParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.code_lens(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1514,8 +1514,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn code_lens_resolve(&self, params: CodeLens) -> Result { - for handler in &self.handlers { + fn code_lens_resolve(&mut self, params: CodeLens) -> Result { + for handler in &mut self.handlers { let res = handler.code_lens_resolve(params.clone()); if res.is_ok() { return res; @@ -1524,9 +1524,9 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn folding_range(&self, params: FoldingRangeParams) -> Result>> { + fn folding_range(&mut self, params: FoldingRangeParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.folding_range(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1535,9 +1535,12 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn selection_range(&self, params: SelectionRangeParams) -> Result>> { + fn selection_range( + &mut self, + params: SelectionRangeParams, + ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.selection_range(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1547,10 +1550,10 @@ impl Handler for Dispatcher { } fn document_symbol( - &self, + &mut self, params: DocumentSymbolParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.document_symbol(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1560,10 +1563,10 @@ impl Handler for Dispatcher { } fn semantic_tokens_full( - &self, + &mut self, params: SemanticTokensParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.semantic_tokens_full(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1573,10 +1576,10 @@ impl Handler for Dispatcher { } fn semantic_tokens_full_delta( - &self, + &mut self, params: SemanticTokensDeltaParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.semantic_tokens_full_delta(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1586,10 +1589,10 @@ impl Handler for Dispatcher { } fn semantic_tokens_range( - &self, + &mut self, params: SemanticTokensRangeParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.semantic_tokens_range(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1598,9 +1601,9 @@ impl Handler for Dispatcher { Ok(None) } - fn inline_value(&self, params: InlineValueParams) -> Result>> { + fn inline_value(&mut self, params: InlineValueParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.inline_value(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1609,9 +1612,9 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn inlay_hint(&self, params: InlayHintParams) -> Result>> { + fn inlay_hint(&mut self, params: InlayHintParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.inlay_hint(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1620,8 +1623,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn inlay_hint_resolve(&self, params: InlayHint) -> Result { - for handler in &self.handlers { + fn inlay_hint_resolve(&mut self, params: InlayHint) -> Result { + for handler in &mut self.handlers { let res = handler.inlay_hint_resolve(params.clone()); if res.is_ok() { return res; @@ -1630,9 +1633,9 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn moniker(&self, params: MonikerParams) -> Result>> { + fn moniker(&mut self, params: MonikerParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.moniker(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1641,8 +1644,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn completion(&self, params: CompletionParams) -> Result> { - for handler in &self.handlers { + fn completion(&mut self, params: CompletionParams) -> Result> { + for handler in &mut self.handlers { let res = handler.completion(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1651,8 +1654,8 @@ impl Handler for Dispatcher { Ok(None) } - fn completion_resolve(&self, params: CompletionItem) -> Result { - for handler in &self.handlers { + fn completion_resolve(&mut self, params: CompletionItem) -> Result { + for handler in &mut self.handlers { let res = handler.completion_resolve(params.clone()); if res.is_ok() { return res; @@ -1662,10 +1665,10 @@ impl Handler for Dispatcher { } fn diagnostic( - &self, + &mut self, params: DocumentDiagnosticParams, ) -> Result { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.diagnostic(params.clone()); if res.is_ok() { return res; @@ -1675,10 +1678,10 @@ impl Handler for Dispatcher { } fn workspace_diagnostic( - &self, + &mut self, params: WorkspaceDiagnosticParams, ) -> Result { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.workspace_diagnostic(params.clone()); if res.is_ok() { return res; @@ -1687,8 +1690,8 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn signature_help(&self, params: SignatureHelpParams) -> Result> { - for handler in &self.handlers { + fn signature_help(&mut self, params: SignatureHelpParams) -> Result> { + for handler in &mut self.handlers { let res = handler.signature_help(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1697,8 +1700,8 @@ impl Handler for Dispatcher { Ok(None) } - fn code_action(&self, params: CodeActionParams) -> Result> { - for handler in &self.handlers { + fn code_action(&mut self, params: CodeActionParams) -> Result> { + for handler in &mut self.handlers { let res = handler.code_action(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1707,8 +1710,8 @@ impl Handler for Dispatcher { Ok(None) } - fn code_action_resolve(&self, params: CodeAction) -> Result { - for handler in &self.handlers { + fn code_action_resolve(&mut self, params: CodeAction) -> Result { + for handler in &mut self.handlers { let res = handler.code_action_resolve(params.clone()); if res.is_ok() { return res; @@ -1717,9 +1720,9 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn document_color(&self, params: DocumentColorParams) -> Result> { + fn document_color(&mut self, params: DocumentColorParams) -> Result> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.document_color(params.clone()); if let Ok(val) = res { text_edit.extend(val); @@ -1729,11 +1732,11 @@ impl Handler for Dispatcher { } fn color_presentation( - &self, + &mut self, params: ColorPresentationParams, ) -> Result> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.color_presentation(params.clone()); if let Ok(val) = res { text_edit.extend(val); @@ -1742,9 +1745,9 @@ impl Handler for Dispatcher { Ok(text_edit) } - fn formatting(&self, params: DocumentFormattingParams) -> Result>> { + fn formatting(&mut self, params: DocumentFormattingParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.formatting(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1754,11 +1757,11 @@ impl Handler for Dispatcher { } fn range_formatting( - &self, + &mut self, params: DocumentRangeFormattingParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.range_formatting(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1768,11 +1771,11 @@ impl Handler for Dispatcher { } fn on_type_formatting( - &self, + &mut self, params: DocumentOnTypeFormattingParams, ) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.on_type_formatting(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1781,8 +1784,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn rename(&self, params: RenameParams) -> Result> { - for handler in &self.handlers { + fn rename(&mut self, params: RenameParams) -> Result> { + for handler in &mut self.handlers { let res = handler.rename(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1792,10 +1795,10 @@ impl Handler for Dispatcher { } fn prepare_rename( - &self, + &mut self, params: TextDocumentPositionParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.prepare_rename(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1805,10 +1808,10 @@ impl Handler for Dispatcher { } fn linked_editing_range( - &self, + &mut self, params: LinkedEditingRangeParams, ) -> Result> { - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.linked_editing_range(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1817,9 +1820,9 @@ impl Handler for Dispatcher { Ok(None) } - fn symbol(&self, params: WorkspaceSymbolParams) -> Result>> { + fn symbol(&mut self, params: WorkspaceSymbolParams) -> Result>> { let mut text_edit: Vec = vec![]; - for handler in &self.handlers { + for handler in &mut self.handlers { let res = handler.symbol(params.clone()); if let Ok(Some(val)) = res { text_edit.extend(val); @@ -1828,8 +1831,8 @@ impl Handler for Dispatcher { Ok(Some(text_edit)) } - fn symbol_resolve(&self, params: WorkspaceSymbol) -> Result { - for handler in &self.handlers { + fn symbol_resolve(&mut self, params: WorkspaceSymbol) -> Result { + for handler in &mut self.handlers { let res = handler.symbol_resolve(params.clone()); if res.is_ok() { return res; @@ -1838,20 +1841,20 @@ impl Handler for Dispatcher { Err(Error::new(ErrorCode::MethodNotFound)) } - fn did_change_configuration(&self, params: DidChangeConfigurationParams) { - for handler in &self.handlers { + fn did_change_configuration(&mut self, params: DidChangeConfigurationParams) { + for handler in &mut self.handlers { handler.did_change_configuration(params.clone()); } } - fn did_change_workspace_folders(&self, params: DidChangeWorkspaceFoldersParams) { - for handler in &self.handlers { + fn did_change_workspace_folders(&mut self, params: DidChangeWorkspaceFoldersParams) { + for handler in &mut self.handlers { handler.did_change_workspace_folders(params.clone()); } } - fn will_create_files(&self, params: CreateFilesParams) -> Result> { - for handler in &self.handlers { + fn will_create_files(&mut self, params: CreateFilesParams) -> Result> { + for handler in &mut self.handlers { let res = handler.will_create_files(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1860,14 +1863,14 @@ impl Handler for Dispatcher { Ok(None) } - fn did_create_files(&self, params: CreateFilesParams) { - for handler in &self.handlers { + fn did_create_files(&mut self, params: CreateFilesParams) { + for handler in &mut self.handlers { handler.did_create_files(params.clone()); } } - fn will_rename_files(&self, params: RenameFilesParams) -> Result> { - for handler in &self.handlers { + fn will_rename_files(&mut self, params: RenameFilesParams) -> Result> { + for handler in &mut self.handlers { let res = handler.will_rename_files(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1876,14 +1879,14 @@ impl Handler for Dispatcher { Ok(None) } - fn did_rename_files(&self, params: RenameFilesParams) { - for handler in &self.handlers { + fn did_rename_files(&mut self, params: RenameFilesParams) { + for handler in &mut self.handlers { handler.did_rename_files(params.clone()); } } - fn will_delete_files(&self, params: DeleteFilesParams) -> Result> { - for handler in &self.handlers { + fn will_delete_files(&mut self, params: DeleteFilesParams) -> Result> { + for handler in &mut self.handlers { let res = handler.will_delete_files(params.clone()); if let Ok(Some(_)) = res { return res; @@ -1892,20 +1895,20 @@ impl Handler for Dispatcher { Ok(None) } - fn did_delete_files(&self, params: DeleteFilesParams) { - for handler in &self.handlers { + fn did_delete_files(&mut self, params: DeleteFilesParams) { + for handler in &mut self.handlers { handler.did_delete_files(params.clone()); } } - fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams) { - for handler in &self.handlers { + fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams) { + for handler in &mut self.handlers { handler.did_change_watched_files(params.clone()); } } - fn execute_command(&self, params: ExecuteCommandParams) -> Result> { - for handler in &self.handlers { + fn execute_command(&mut self, params: ExecuteCommandParams) -> Result> { + for handler in &mut self.handlers { let res = handler.execute_command(params.clone()); if let Ok(Some(_)) = res { return res; diff --git a/libs/lsp-handler/src/handler.rs b/libs/lsp-handler/src/handler.rs index 75eaaea4..e534782d 100644 --- a/libs/lsp-handler/src/handler.rs +++ b/libs/lsp-handler/src/handler.rs @@ -21,7 +21,7 @@ pub trait Handler { /// /// This method is guaranteed to only execute once. If the client sends this request to the /// server again, the server will respond with JSON-RPC error code `-32600` (invalid request). - fn initialize(&self, params: InitializeParams) -> Result; + fn initialize(&mut self, params: InitializeParams) -> Result; /// The [`initialized`] notification is sent from the client to the server after the client /// received the result of the initialize request but before the client sends anything else. @@ -30,7 +30,7 @@ pub trait Handler { /// /// The server can use the `initialized` notification, for example, to dynamically register /// capabilities with the client. - fn initialized(&self, params: InitializedParams) { + fn initialized(&mut self, params: InitializedParams) { let _ = params; } @@ -45,7 +45,7 @@ pub trait Handler { /// /// This method is guaranteed to only execute once. If the client sends this request to the /// server again, the server will respond with JSON-RPC error code `-32600` (invalid request). - fn shutdown(&self) -> Result<()>; + fn shutdown(&mut self) -> Result<()>; // Document Synchronization @@ -57,7 +57,7 @@ pub trait Handler { /// The document's truth is now managed by the client and the server must not try to read the /// document’s truth using the document's URI. "Open" in this sense means it is managed by the /// client. It doesn't necessarily mean that its content is presented in an editor. - fn did_open(&self, params: DidOpenTextDocumentParams) { + fn did_open(&mut self, params: DidOpenTextDocumentParams) { let _ = params; log("Got a textDocument/didOpen notification, but it is not implemented"); } @@ -69,7 +69,7 @@ pub trait Handler { /// /// This notification will contain a distinct version tag and a list of edits made to the /// document for the server to interpret. - fn did_change(&self, params: DidChangeTextDocumentParams) { + fn did_change(&mut self, params: DidChangeTextDocumentParams) { let _ = params; log("Got a textDocument/didChange notification, but it is not implemented"); } @@ -78,7 +78,7 @@ pub trait Handler { /// document is actually saved. /// /// [`textDocument/willSave`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_willSave - fn will_save(&self, params: WillSaveTextDocumentParams) { + fn will_save(&mut self, params: WillSaveTextDocumentParams) { let _ = params; log("Got a textDocument/willSave notification, but it is not implemented"); } @@ -94,7 +94,7 @@ pub trait Handler { /// Please note that clients might drop results if computing the text edits took too long or if /// a server constantly fails on this request. This is done to keep the save fast and reliable. fn will_save_wait_until( - &self, + &mut self, params: WillSaveTextDocumentParams, ) -> Result>> { let _ = params; @@ -106,7 +106,7 @@ pub trait Handler { /// document was saved in the client. /// /// [`textDocument/didSave`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_didSave - fn did_save(&self, params: DidSaveTextDocumentParams) { + fn did_save(&mut self, params: DidSaveTextDocumentParams) { let _ = params; log("Got a textDocument/didSave notification, but it is not implemented"); } @@ -118,7 +118,7 @@ pub trait Handler { /// /// The document's truth now exists where the document's URI points to (e.g. if the document's /// URI is a file URI, the truth now exists on disk). - fn did_close(&self, params: DidCloseTextDocumentParams) { + fn did_close(&mut self, params: DidCloseTextDocumentParams) { let _ = params; log("Got a textDocument/didClose notification, but it is not implemented"); } @@ -143,7 +143,7 @@ pub trait Handler { /// InitializeParams::capabilities::text_document::declaration::link_support /// ``` fn goto_declaration( - &self, + &mut self, params: GotoDeclarationParams, ) -> Result> { let _ = params; @@ -167,7 +167,7 @@ pub trait Handler { /// InitializeParams::capabilities::text_document::definition::link_support /// ``` fn goto_definition( - &self, + &mut self, params: GotoDefinitionParams, ) -> Result> { let _ = params; @@ -193,7 +193,7 @@ pub trait Handler { /// InitializeParams::capabilities::text_document::type_definition::link_support /// ``` fn goto_type_definition( - &self, + &mut self, params: GotoTypeDefinitionParams, ) -> Result> { let _ = params; @@ -219,7 +219,7 @@ pub trait Handler { /// InitializeParams::capabilities::text_document::implementation::link_support /// ``` fn goto_implementation( - &self, + &mut self, params: GotoImplementationParams, ) -> Result> { let _ = params; @@ -232,7 +232,7 @@ pub trait Handler { /// /// [`textDocument/references`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_references - fn references(&self, params: ReferenceParams) -> Result>> { + fn references(&mut self, params: ReferenceParams) -> Result>> { let _ = params; log("Got a textDocument/references request, but it is not implemented"); Err(Error::method_not_found()) @@ -257,7 +257,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. fn prepare_call_hierarchy( - &self, + &mut self, params: CallHierarchyPrepareParams, ) -> Result>> { let _ = params; @@ -278,7 +278,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. fn incoming_calls( - &self, + &mut self, params: CallHierarchyIncomingCallsParams, ) -> Result>> { let _ = params; @@ -299,7 +299,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. fn outgoing_calls( - &self, + &mut self, params: CallHierarchyOutgoingCallsParams, ) -> Result>> { let _ = params; @@ -324,7 +324,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0. fn prepare_type_hierarchy( - &self, + &mut self, params: TypeHierarchyPrepareParams, ) -> Result>> { let _ = params; @@ -344,7 +344,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0. fn supertypes( - &self, + &mut self, params: TypeHierarchySupertypesParams, ) -> Result>> { let _ = params; @@ -364,7 +364,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0. fn subtypes( - &self, + &mut self, params: TypeHierarchySubtypesParams, ) -> Result>> { let _ = params; @@ -383,7 +383,7 @@ pub trait Handler { /// This request differs slightly from `textDocument/references` in that this one is allowed to /// be more fuzzy. fn document_highlight( - &self, + &mut self, params: DocumentHighlightParams, ) -> Result>> { let _ = params; @@ -408,7 +408,7 @@ pub trait Handler { /// ```text /// InitializeParams::capabilities::text_document::document_link::tooltip_support /// ``` - fn document_link(&self, params: DocumentLinkParams) -> Result>> { + fn document_link(&mut self, params: DocumentLinkParams) -> Result>> { let _ = params; log("Got a textDocument/documentLink request, but it is not implemented"); Err(Error::method_not_found()) @@ -421,7 +421,7 @@ pub trait Handler { /// /// A document link is a range in a text document that links to an internal or external /// resource, like another text document or a web site. - fn document_link_resolve(&self, params: DocumentLink) -> Result { + fn document_link_resolve(&mut self, params: DocumentLink) -> Result { let _ = params; log("Got a documentLink/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -434,7 +434,7 @@ pub trait Handler { /// /// Such hover information typically includes type signature information and inline /// documentation for the symbol at the given text document position. - fn hover(&self, params: HoverParams) -> Result> { + fn hover(&mut self, params: HoverParams) -> Result> { let _ = params; log("Got a textDocument/hover request, but it is not implemented"); Err(Error::method_not_found()) @@ -445,7 +445,7 @@ pub trait Handler { /// /// [`textDocument/codeLens`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens - fn code_lens(&self, params: CodeLensParams) -> Result>> { + fn code_lens(&mut self, params: CodeLensParams) -> Result>> { let _ = params; log("Got a textDocument/codeLens request, but it is not implemented"); Err(Error::method_not_found()) @@ -456,7 +456,7 @@ pub trait Handler { /// /// [`codeLens/resolve`]: https://microsoft.github.io/language-server-protocol/specification#codeLens_resolve - fn code_lens_resolve(&self, params: CodeLens) -> Result { + fn code_lens_resolve(&mut self, params: CodeLens) -> Result { let _ = params; log("Got a codeLens/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -471,7 +471,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.10.0. - fn folding_range(&self, params: FoldingRangeParams) -> Result>> { + fn folding_range(&mut self, params: FoldingRangeParams) -> Result>> { let _ = params; log("Got a textDocument/foldingRange request, but it is not implemented"); Err(Error::method_not_found()) @@ -490,7 +490,10 @@ pub trait Handler { /// /// This request was introduced in specification version 3.15.0. - fn selection_range(&self, params: SelectionRangeParams) -> Result>> { + fn selection_range( + &mut self, + params: SelectionRangeParams, + ) -> Result>> { let _ = params; log("Got a textDocument/selectionRange request, but it is not implemented"); Err(Error::method_not_found()) @@ -510,7 +513,7 @@ pub trait Handler { /// document. fn document_symbol( - &self, + &mut self, params: DocumentSymbolParams, ) -> Result> { let _ = params; @@ -535,7 +538,7 @@ pub trait Handler { /// This request was introduced in specification version 3.16.0. fn semantic_tokens_full( - &self, + &mut self, params: SemanticTokensParams, ) -> Result> { let _ = params; @@ -556,7 +559,7 @@ pub trait Handler { /// This request was introduced in specification version 3.16.0. fn semantic_tokens_full_delta( - &self, + &mut self, params: SemanticTokensDeltaParams, ) -> Result> { let _ = params; @@ -582,7 +585,7 @@ pub trait Handler { /// This request was introduced in specification version 3.16.0. fn semantic_tokens_range( - &self, + &mut self, params: SemanticTokensRangeParams, ) -> Result> { let _ = params; @@ -600,7 +603,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0. - fn inline_value(&self, params: InlineValueParams) -> Result>> { + fn inline_value(&mut self, params: InlineValueParams) -> Result>> { let _ = params; log("Got a textDocument/inlineValue request, but it is not implemented"); Err(Error::method_not_found()) @@ -616,7 +619,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0 - fn inlay_hint(&self, params: InlayHintParams) -> Result>> { + fn inlay_hint(&mut self, params: InlayHintParams) -> Result>> { let _ = params; log("Got a textDocument/inlayHint request, but it is not implemented"); Err(Error::method_not_found()) @@ -645,7 +648,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0 - fn inlay_hint_resolve(&self, params: InlayHint) -> Result { + fn inlay_hint_resolve(&mut self, params: InlayHint) -> Result { let _ = params; log("Got a inlayHint/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -675,7 +678,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. - fn moniker(&self, params: MonikerParams) -> Result>> { + fn moniker(&mut self, params: MonikerParams) -> Result>> { let _ = params; log("Got a textDocument/moniker request, but it is not implemented"); Err(Error::method_not_found()) @@ -700,7 +703,7 @@ pub trait Handler { /// must be provided in the `textDocument/completion` response and must not be changed during /// resolve. - fn completion(&self, params: CompletionParams) -> Result> { + fn completion(&mut self, params: CompletionParams) -> Result> { let _ = params; log("Got a textDocument/completion request, but it is not implemented"); Err(Error::method_not_found()) @@ -711,7 +714,7 @@ pub trait Handler { /// /// [`completionItem/resolve`]: https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve - fn completion_resolve(&self, params: CompletionItem) -> Result { + fn completion_resolve(&mut self, params: CompletionItem) -> Result { let _ = params; log("Got a completionItem/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -733,7 +736,7 @@ pub trait Handler { /// This request was introduced in specification version 3.17.0. fn diagnostic( - &self, + &mut self, params: DocumentDiagnosticParams, ) -> Result { let _ = params; @@ -771,7 +774,7 @@ pub trait Handler { /// This request was introduced in specification version 3.17.0. fn workspace_diagnostic( - &self, + &mut self, params: WorkspaceDiagnosticParams, ) -> Result { let _ = params; @@ -784,7 +787,7 @@ pub trait Handler { /// /// [`textDocument/signatureHelp`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp - fn signature_help(&self, params: SignatureHelpParams) -> Result> { + fn signature_help(&mut self, params: SignatureHelpParams) -> Result> { let _ = params; log("Got a textDocument/signatureHelp request, but it is not implemented"); Err(Error::method_not_found()) @@ -844,7 +847,7 @@ pub trait Handler { /// information. However it allows them to better group code action, for example, into /// corresponding menus (e.g. all refactor code actions into a refactor menu). - fn code_action(&self, params: CodeActionParams) -> Result> { + fn code_action(&mut self, params: CodeActionParams) -> Result> { let _ = params; log("Got a textDocument/codeAction request, but it is not implemented"); Err(Error::method_not_found()) @@ -862,7 +865,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. - fn code_action_resolve(&self, params: CodeAction) -> Result { + fn code_action_resolve(&mut self, params: CodeAction) -> Result { let _ = params; log("Got a codeAction/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -883,7 +886,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.6.0. - fn document_color(&self, params: DocumentColorParams) -> Result> { + fn document_color(&mut self, params: DocumentColorParams) -> Result> { let _ = params; log("Got a textDocument/documentColor request, but it is not implemented"); Err(Error::method_not_found()) @@ -907,7 +910,7 @@ pub trait Handler { /// resolve request for the [`textDocument/documentColor`](Self::document_color) request. fn color_presentation( - &self, + &mut self, params: ColorPresentationParams, ) -> Result> { let _ = params; @@ -920,7 +923,7 @@ pub trait Handler { /// /// [`textDocument/formatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting - fn formatting(&self, params: DocumentFormattingParams) -> Result>> { + fn formatting(&mut self, params: DocumentFormattingParams) -> Result>> { let _ = params; log("Got a textDocument/formatting request, but it is not implemented"); Err(Error::method_not_found()) @@ -932,7 +935,7 @@ pub trait Handler { /// [`textDocument/rangeFormatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting fn range_formatting( - &self, + &mut self, params: DocumentRangeFormattingParams, ) -> Result>> { let _ = params; @@ -946,7 +949,7 @@ pub trait Handler { /// [`textDocument/onTypeFormatting`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting fn on_type_formatting( - &self, + &mut self, params: DocumentOnTypeFormattingParams, ) -> Result>> { let _ = params; @@ -960,7 +963,7 @@ pub trait Handler { /// /// [`textDocument/rename`]: https://microsoft.github.io/language-server-protocol/specification#textDocument_rename - fn rename(&self, params: RenameParams) -> Result> { + fn rename(&mut self, params: RenameParams) -> Result> { let _ = params; log("Got a textDocument/rename request, but it is not implemented"); Err(Error::method_not_found()) @@ -976,7 +979,7 @@ pub trait Handler { /// This request was introduced in specification version 3.12.0. fn prepare_rename( - &self, + &mut self, params: TextDocumentPositionParams, ) -> Result> { let _ = params; @@ -1001,7 +1004,7 @@ pub trait Handler { /// This request was introduced in specification version 3.16.0. fn linked_editing_range( - &self, + &mut self, params: LinkedEditingRangeParams, ) -> Result> { let _ = params; @@ -1028,7 +1031,7 @@ pub trait Handler { /// Servers can only use this new model if clients advertise support for it via the /// `workspace.symbol.resolve_support` capability. - fn symbol(&self, params: WorkspaceSymbolParams) -> Result>> { + fn symbol(&mut self, params: WorkspaceSymbolParams) -> Result>> { let _ = params; log("Got a workspace/symbol request, but it is not implemented"); Err(Error::method_not_found()) @@ -1045,7 +1048,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.17.0. - fn symbol_resolve(&self, params: WorkspaceSymbol) -> Result { + fn symbol_resolve(&mut self, params: WorkspaceSymbol) -> Result { let _ = params; log("Got a workspaceSymbol/resolve request, but it is not implemented"); Err(Error::method_not_found()) @@ -1056,7 +1059,7 @@ pub trait Handler { /// /// [`workspace/didChangeConfiguration`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didChangeConfiguration - fn did_change_configuration(&self, params: DidChangeConfigurationParams) { + fn did_change_configuration(&mut self, params: DidChangeConfigurationParams) { let _ = params; log("Got a workspace/didChangeConfiguration notification, but it is not implemented"); } @@ -1075,7 +1078,7 @@ pub trait Handler { /// This notification is also sent if the server has registered itself to receive this /// notification. - fn did_change_workspace_folders(&self, params: DidChangeWorkspaceFoldersParams) { + fn did_change_workspace_folders(&mut self, params: DidChangeWorkspaceFoldersParams) { let _ = params; log("Got a workspace/didChangeWorkspaceFolders notification, but it is not implemented"); } @@ -1094,7 +1097,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. - fn will_create_files(&self, params: CreateFilesParams) -> Result> { + fn will_create_files(&mut self, params: CreateFilesParams) -> Result> { let _ = params; log("Got a workspace/willCreateFiles request, but it is not implemented"); Err(Error::method_not_found()) @@ -1105,7 +1108,7 @@ pub trait Handler { /// /// [`workspace/didCreateFiles`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didCreateFiles - fn did_create_files(&self, params: CreateFilesParams) { + fn did_create_files(&mut self, params: CreateFilesParams) { let _ = params; log("Got a workspace/didCreateFiles notification, but it is not implemented"); } @@ -1124,7 +1127,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. - fn will_rename_files(&self, params: RenameFilesParams) -> Result> { + fn will_rename_files(&mut self, params: RenameFilesParams) -> Result> { let _ = params; log("Got a workspace/willRenameFiles request, but it is not implemented"); Err(Error::method_not_found()) @@ -1135,7 +1138,7 @@ pub trait Handler { /// /// [`workspace/didRenameFiles`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didRenameFiles - fn did_rename_files(&self, params: RenameFilesParams) { + fn did_rename_files(&mut self, params: RenameFilesParams) { let _ = params; log("Got a workspace/didRenameFiles notification, but it is not implemented"); } @@ -1155,7 +1158,7 @@ pub trait Handler { /// /// This request was introduced in specification version 3.16.0. - fn will_delete_files(&self, params: DeleteFilesParams) -> Result> { + fn will_delete_files(&mut self, params: DeleteFilesParams) -> Result> { let _ = params; log("Got a workspace/willDeleteFiles request, but it is not implemented"); Err(Error::method_not_found()) @@ -1166,7 +1169,7 @@ pub trait Handler { /// /// [`workspace/didDeleteFiles`]: https://microsoft.github.io/language-server-protocol/specification#workspace_didDeleteFiles - fn did_delete_files(&self, params: DeleteFilesParams) { + fn did_delete_files(&mut self, params: DeleteFilesParams) { let _ = params; log("Got a workspace/didDeleteFiles notification, but it is not implemented"); } @@ -1180,7 +1183,7 @@ pub trait Handler { /// mechanism. This can be done here or in the [`initialized`](Self::initialized) method using /// [`Client::register_capability`](crate::Client::register_capability). - fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams) { + fn did_change_watched_files(&mut self, params: DidChangeWatchedFilesParams) { let _ = params; log("Got a workspace/didChangeWatchedFiles notification, but it is not implemented"); } @@ -1193,7 +1196,7 @@ pub trait Handler { /// In most cases, the server creates a [`WorkspaceEdit`] structure and applies the changes to /// the workspace using `Client::apply_edit()` before returning from this function. - fn execute_command(&self, params: ExecuteCommandParams) -> Result> { + fn execute_command(&mut self, params: ExecuteCommandParams) -> Result> { let _ = params; log("Got a workspace/executeCommand request, but it is not implemented"); Err(Error::method_not_found()) diff --git a/libs/lsp-server-wrapper/Cargo.lock b/libs/lsp-server-wrapper/Cargo.lock index 66c43c57..de4f7f57 100644 --- a/libs/lsp-server-wrapper/Cargo.lock +++ b/libs/lsp-server-wrapper/Cargo.lock @@ -76,17 +76,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "lsp-server-wrapper" -version = "0.1.0" -dependencies = [ - "lsp-server", - "lsp-types", - "serde", - "serde_json", - "tracing", -] - [[package]] name = "lsp-types" version = "0.94.1" @@ -106,6 +95,17 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "osmium-libs-lsp-server-wrapper" +version = "0.2.0" +dependencies = [ + "lsp-server", + "lsp-types", + "serde", + "serde_json", + "tracing", +] + [[package]] name = "percent-encoding" version = "2.3.0" diff --git a/libs/lsp-server-wrapper/Cargo.toml b/libs/lsp-server-wrapper/Cargo.toml index 1e31054a..3722f693 100644 --- a/libs/lsp-server-wrapper/Cargo.toml +++ b/libs/lsp-server-wrapper/Cargo.toml @@ -2,7 +2,7 @@ name = "osmium-libs-lsp-server-wrapper" description = "A wrapper around the LSP server crate with a tower-lsp like API" license = "GPL-3.0-or-later" -version = "0.1.0" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/libs/lsp-server-wrapper/src/client.rs b/libs/lsp-server-wrapper/src/client.rs index a593f9ef..97ad3fcd 100644 --- a/libs/lsp-server-wrapper/src/client.rs +++ b/libs/lsp-server-wrapper/src/client.rs @@ -60,7 +60,10 @@ impl Client { /// immediately return `Err` with JSON-RPC error code `-32002` ([read more]). /// /// [read more]: https://microsoft.github.io/language-server-protocol/specification#initialize - pub fn register_capability(&self, registrations: Vec) -> jsonrpc::Result<()> { + pub fn register_capability( + &self, + registrations: Vec, + ) -> jsonrpc::Result { self.send_request::(RegistrationParams { registrations }) } @@ -79,7 +82,7 @@ impl Client { pub fn unregister_capability( &self, unregisterations: Vec, - ) -> jsonrpc::Result<()> { + ) -> jsonrpc::Result { self.send_request::(UnregistrationParams { unregisterations }) } @@ -110,7 +113,7 @@ impl Client { typ: MessageType, message: M, actions: Option>, - ) -> jsonrpc::Result> { + ) -> jsonrpc::Result { self.send_request_unchecked::(ShowMessageRequestParams { typ, message: message.to_string(), @@ -148,9 +151,8 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.16.0. - pub fn show_document(&self, params: ShowDocumentParams) -> jsonrpc::Result { - let response = self.send_request::(params)?; - Ok(response.success) + pub fn show_document(&self, params: ShowDocumentParams) -> jsonrpc::Result { + self.send_request::(params) } // TODO: Add `work_done_progress_create()` here (since 3.15.0) when supported by `tower-lsp`. @@ -196,7 +198,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.16.0. - pub fn code_lens_refresh(&self) -> jsonrpc::Result<()> { + pub fn code_lens_refresh(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -222,7 +224,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.16.0. - pub fn semantic_tokens_refresh(&self) -> jsonrpc::Result<()> { + pub fn semantic_tokens_refresh(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -247,7 +249,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.17.0. - pub fn inline_value_refresh(&self) -> jsonrpc::Result<()> { + pub fn inline_value_refresh(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -272,7 +274,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.17.0. - pub fn inlay_hint_refresh(&self) -> jsonrpc::Result<()> { + pub fn inlay_hint_refresh(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -295,7 +297,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.17.0. - pub fn workspace_diagnostic_refresh(&self) -> jsonrpc::Result<()> { + pub fn workspace_diagnostic_refresh(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -337,7 +339,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.6.0. - pub fn configuration(&self, items: Vec) -> jsonrpc::Result> { + pub fn configuration(&self, items: Vec) -> jsonrpc::Result { self.send_request::(ConfigurationParams { items }) } @@ -360,7 +362,7 @@ impl Client { /// # Compatibility /// /// This request was introduced in specification version 3.6.0. - pub fn workspace_folders(&self) -> jsonrpc::Result>> { + pub fn workspace_folders(&self) -> jsonrpc::Result { self.send_request::(()) } @@ -377,7 +379,7 @@ impl Client { /// immediately return `Err` with JSON-RPC error code `-32002` ([read more]). /// /// [read more]: https://microsoft.github.io/language-server-protocol/specification#initialize - pub fn apply_edit(&self, edit: WorkspaceEdit) -> jsonrpc::Result { + pub fn apply_edit(&self, edit: WorkspaceEdit) -> jsonrpc::Result { self.send_request::(ApplyWorkspaceEditParams { edit, label: None }) } @@ -390,34 +392,24 @@ impl Client { where N: lsp_types::notification::Notification, { - let server_opt = self.inner.server.clone().unwrap().upgrade(); - if server_opt.is_none() { - eprintln!("Cannot send request, server is not initialized"); - return; - } - server_opt - .unwrap() - .send(Message::Notification(lsp_server::Notification::new( - N::METHOD.to_string(), - params, - ))); + self.send_notification_unchecked::(params) } fn send_notification_unchecked(&self, params: N::Params) where N: lsp_types::notification::Notification, { - let server_opt = self.inner.server.clone().unwrap().upgrade(); - if server_opt.is_none() { - eprintln!("Cannot send request, server is not initialized"); - return; + match self.inner.server.clone().unwrap().upgrade() { + Some(server) => { + server.send(Message::Notification(lsp_server::Notification::new( + N::METHOD.to_string(), + params, + ))); + } + None => { + eprintln!("Cannot send notification, server is not initialized"); + } } - server_opt - .unwrap() - .send(Message::Notification(lsp_server::Notification::new( - N::METHOD.to_string(), - params, - ))); } /// Sends a custom request to the client. @@ -428,43 +420,32 @@ impl Client { /// immediately return `Err` with JSON-RPC error code `-32002` ([read more]). /// /// [read more]: https://microsoft.github.io/language-server-protocol/specification#initialize - pub fn send_request(&self, params: R::Params) -> jsonrpc::Result + pub fn send_request(&self, params: R::Params) -> jsonrpc::Result where R: lsp_types::request::Request, { - let server_opt = self.inner.server.clone().unwrap().upgrade(); - if server_opt.is_none() { - eprintln!("Cannot send request, server is not initialized"); - return Err(jsonrpc::not_initialized_error()); - } - server_opt - .as_ref() - .unwrap() - .send(Message::Request(lsp_server::Request::new( - RequestId::from(self.next_request_id().to_string()), - R::METHOD.to_string(), - params, - ))); - Err(jsonrpc::not_initialized_error()) + self.send_request_unchecked::(params) } - fn send_request_unchecked(&self, params: R::Params) -> jsonrpc::Result + fn send_request_unchecked(&self, params: R::Params) -> jsonrpc::Result where R: lsp_types::request::Request, { - let server_opt = self.inner.server.clone().unwrap().upgrade(); - if server_opt.is_none() { - eprintln!("Cannot send request, server is not initialized"); - return Err(jsonrpc::not_initialized_error()); + match self.inner.server.clone().unwrap().upgrade() { + Some(server) => { + let id = RequestId::from(self.next_request_id().to_string()); + server.send(Message::Request(lsp_server::Request::new( + id.clone(), + R::METHOD.to_string(), + params, + ))); + Ok(id) + } + None => { + eprintln!("Cannot send request, server is not initialized"); + Err(jsonrpc::not_initialized_error()) + } } - server_opt - .unwrap() - .send(Message::Request(lsp_server::Request::new( - RequestId::from(self.next_request_id().to_string()), - R::METHOD.to_string(), - params, - ))); - Err(jsonrpc::not_initialized_error()) } } diff --git a/libs/lsp-server-wrapper/src/jsonrpc.rs b/libs/lsp-server-wrapper/src/jsonrpc.rs index 664d6868..a7ead68f 100644 --- a/libs/lsp-server-wrapper/src/jsonrpc.rs +++ b/libs/lsp-server-wrapper/src/jsonrpc.rs @@ -1,4 +1,4 @@ mod error; pub(crate) use self::error::not_initialized_error; -pub use self::error::{Error, ErrorCode, Result}; +pub use self::error::{Error, Result}; diff --git a/libs/lsp-server-wrapper/src/lib.rs b/libs/lsp-server-wrapper/src/lib.rs index 493d6b5d..165b337e 100644 --- a/libs/lsp-server-wrapper/src/lib.rs +++ b/libs/lsp-server-wrapper/src/lib.rs @@ -5,6 +5,7 @@ mod service; pub use crate::jsonrpc::{Error, Result}; pub use client::Client; +pub use lsp_server::RequestId; pub use lsp_types; use lsp_types::request::{ GotoDeclarationParams, GotoDeclarationResponse, GotoImplementationParams, @@ -1210,6 +1211,12 @@ pub trait LanguageServer { Err(Error::method_not_found()) } + fn on_response(&self, id: RequestId, response: Option) { + let _ = id; + let _ = response; + eprintln!("Got a response, but it is not implemented"); + } + // TODO: Add `work_done_progress_cancel()` here (since 3.15.0) when supported by `tower-lsp`. // https://github.com/ebkalderon/tower-lsp/issues/176 } diff --git a/libs/lsp-server-wrapper/src/server.rs b/libs/lsp-server-wrapper/src/server.rs index 1a7b118b..74cf0377 100644 --- a/libs/lsp-server-wrapper/src/server.rs +++ b/libs/lsp-server-wrapper/src/server.rs @@ -127,9 +127,7 @@ impl<'a> LspStdioServer { } continue; } - Message::Response(resp) => { - eprintln!("got response: {resp:?}"); - } + Message::Response(resp) => service.call_response(resp.id, resp.result), Message::Notification(not) => { let status = service.call_notification(¬.method, not.params); if status.is_err() { diff --git a/libs/lsp-server-wrapper/src/service.rs b/libs/lsp-server-wrapper/src/service.rs index 10bb8b62..3e08ad0e 100644 --- a/libs/lsp-server-wrapper/src/service.rs +++ b/libs/lsp-server-wrapper/src/service.rs @@ -3,6 +3,7 @@ mod state; pub(crate) use self::state::{ServerState, State}; pub use crate::client::Client; use crate::{jsonrpc, LanguageServer}; +use lsp_server::RequestId; use lsp_types::request::*; use lsp_types::*; use std::cell::RefCell; @@ -325,4 +326,8 @@ impl LspService { } Ok(()) } + + pub fn call_response(&self, id: RequestId, result: Option) { + self.inner.backend.on_response(id, result) + } } diff --git a/package.json b/package.json index 8e6b7703..22c4b412 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "manager", "packages/*", "toolchains/*", - "libs/*" + "libs/*", + "doc" ], "main": "index.js", "license": "MIT", diff --git a/toolchains/solidity/core/Cargo.lock b/toolchains/solidity/core/Cargo.lock index 481a071b..95fa11e5 100644 --- a/toolchains/solidity/core/Cargo.lock +++ b/toolchains/solidity/core/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.1.2" @@ -13,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -33,37 +48,81 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] [[package]] name = "bitflags" @@ -77,6 +136,21 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -85,9 +159,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.7" +version = "4.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642" dependencies = [ "clap_builder", "clap_derive", @@ -95,9 +169,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" dependencies = [ "anstream", "anstyle", @@ -114,7 +188,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] [[package]] @@ -131,20 +205,19 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" dependencies = [ "cfg-if", "crossbeam-utils", @@ -152,38 +225,155 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" dependencies = [ "cfg-if", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] +[[package]] +name = "foundry-compiler-server" +version = "0.3.0" +dependencies = [ + "osmium-libs-foundry-wrapper", + "tokio", + "tower-lsp", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.4.1" @@ -197,31 +387,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] -name = "idna" -version = "0.4.0" +name = "home" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "windows-sys 0.52.0", ] [[package]] -name = "is-terminal" -version = "0.4.9" +name = "httparse" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "hermit-abi", - "rustix", - "windows-sys", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "lazy_static" @@ -231,23 +425,36 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "linter-server" -version = "0.2.0" +version = "0.2.2" dependencies = [ + "glob", "osmium-libs-lsp-server-wrapper", + "serde", + "serde_json", "solidhunter-lib", ] [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "lock_api" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" @@ -257,9 +464,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lsp-server" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52dccdf3302eefab8c8a1273047f0a3c3dca4b527c8458d00c09484c8371928" +checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" dependencies = [ "crossbeam-channel", "log", @@ -282,19 +489,76 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "osmium-libs-lsp-server-wrapper" +name = "os" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffda62bb984a82b17675005290ffa19b76fb74c3774cb8bed86bccb628ca911" + +[[package]] +name = "osmium-libs-foundry-wrapper" version = "0.1.0" +dependencies = [ + "clap", + "glob", + "serde", + "serde_json", + "thiserror", + "which", +] + +[[package]] +name = "osmium-libs-lsp-server-wrapper" +version = "0.2.0" dependencies = [ "lsp-server", "lsp-types", @@ -309,11 +573,34 @@ version = "0.1.2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", "syn-solidity", "thiserror", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + [[package]] name = "paste" version = "1.0.14" @@ -322,9 +609,29 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] [[package]] name = "pin-project-lite" @@ -332,24 +639,63 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.10.2" @@ -379,50 +725,62 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -431,18 +789,66 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slither-server" +version = "0.3.0" +dependencies = [ + "colored", + "os", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "tokio", + "tower-lsp", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", ] [[package]] name = "solidhunter" -version = "0.2.1" +version = "0.2.4" dependencies = [ "clap", "colored", @@ -453,7 +859,7 @@ dependencies = [ [[package]] name = "solidhunter-lib" -version = "0.2.0" +version = "0.2.2" dependencies = [ "anyhow", "clap", @@ -474,9 +880,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.38" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -492,27 +909,40 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn", + "syn 2.0.48", +] + +[[package]] +name = "tests-positions-server" +version = "0.3.0" +dependencies = [ + "osmium-libs-lsp-server-wrapper", + "osmium-libs-solidity-ast-extractor", + "regex", + "serde", + "serde_json", + "tokio", + "tower-lsp", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] [[package]] @@ -530,6 +960,110 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-lsp" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tower-lsp-macros", + "tracing", +] + +[[package]] +name = "tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -549,7 +1083,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] [[package]] @@ -563,9 +1097,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" @@ -584,9 +1118,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -600,13 +1134,47 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -615,13 +1183,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -630,38 +1213,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/toolchains/solidity/core/Cargo.toml b/toolchains/solidity/core/Cargo.toml index 23f0a5f8..eaf3e245 100644 --- a/toolchains/solidity/core/Cargo.toml +++ b/toolchains/solidity/core/Cargo.toml @@ -18,4 +18,5 @@ rustdoc-args = ["--cfg", "docsrs"] extension = { version = "0.1.0", path = "crates/extension", default-features = false } solidhunter = { version = "0.2.1", path = "crates/solidhunter", default-features = false } linter-cli = { version = "0.2.0", path = "crates/linter-cli", default-features = false } -linter-server = { version = "0.1.0", path = "crates/linter-server", default-features = false } \ No newline at end of file +linter-server = { version = "0.1.0", path = "crates/linter-server", default-features = false } +foundry-compiler-server = { version = "0.1.0", path = "crates/foundry-compiler-server", default-features = false } \ No newline at end of file diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/Cargo.toml b/toolchains/solidity/core/crates/foundry-compiler-server/Cargo.toml new file mode 100644 index 00000000..da0beb7e --- /dev/null +++ b/toolchains/solidity/core/crates/foundry-compiler-server/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "foundry-compiler-server" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +osmium-libs-foundry-wrapper = { path = "../../../../../libs/foundry-wrapper" } +tower-lsp = "0.20.0" +tokio = { version = "1.34.0", features = ["full"] } \ No newline at end of file diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/Makefile b/toolchains/solidity/core/crates/foundry-compiler-server/Makefile new file mode 100644 index 00000000..1f0381e6 --- /dev/null +++ b/toolchains/solidity/core/crates/foundry-compiler-server/Makefile @@ -0,0 +1,3 @@ +build: + cargo build + cp ../../target/debug/foundry-server ../../../extension/dist \ No newline at end of file diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/src/affected_files_store.rs b/toolchains/solidity/core/crates/foundry-compiler-server/src/affected_files_store.rs new file mode 100644 index 00000000..daf0354f --- /dev/null +++ b/toolchains/solidity/core/crates/foundry-compiler-server/src/affected_files_store.rs @@ -0,0 +1,48 @@ +use std::collections::HashMap; + +#[derive(Debug)] +pub struct AffectedFilesStore { + projects_files: HashMap>, +} + +impl AffectedFilesStore { + pub fn new() -> Self { + Self { + projects_files: HashMap::new(), + } + } + + pub fn add_project_file(&mut self, project_path: String, file: String) { + if let Some(files) = self.projects_files.get_mut(&project_path) { + if !files.contains(&file) { + files.push(file); + } + } else { + self.projects_files.insert(project_path, vec![file]); + } + } + + /** + * This function returns the list of files that previously raised an error and are not raising it anymore. + * It also updates the list of files that are raising an error. + * @param {Vec} raised_files List of files that are raising an error + * @param {String} project_path Project path + * @returns {Vec} List of files that are not raising an error anymore + */ + pub fn fill_affected_files( + &mut self, + raised_files: Vec, + project_path: &str, + ) -> Vec { + let mut affected_files = Vec::new(); + if let Some(project_files) = self.projects_files.get_mut(project_path) { + project_files.retain(|file| !raised_files.contains(file)); + affected_files = project_files.clone(); + project_files.extend(raised_files); + } else { + self.projects_files + .insert(project_path.to_string(), raised_files); + } + affected_files + } +} diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs b/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs new file mode 100644 index 00000000..ab431df6 --- /dev/null +++ b/toolchains/solidity/core/crates/foundry-compiler-server/src/main.rs @@ -0,0 +1,408 @@ +use osmium_libs_foundry_wrapper::{CompilationError, Compiler, Error, ProjectCompileOutput}; +use std::collections::HashMap; +use std::fmt::Debug; +use std::path::{Path, PathBuf}; +use tokio::sync::Mutex; +use tower_lsp::jsonrpc::Result; +use tower_lsp::lsp_types::*; +use tower_lsp::{Client, LanguageServer, LspService, Server}; +mod utils; +use utils::{convert_severity, get_root_path, normalized_slash_path, slashify_path}; +mod affected_files_store; +use affected_files_store::AffectedFilesStore; + +#[derive(Debug)] +struct State { + compiler: Option, + initialized: bool, + affected_files: AffectedFilesStore, +} + +#[derive(Debug)] +struct Backend { + client: Client, + state: Mutex, +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, params: InitializeParams) -> Result { + self.client + .log_message(MessageType::INFO, "Foundry server initializing!") + .await; + if let Some(root_path) = get_root_path(params.clone()) { + self.client + .log_message( + MessageType::INFO, + &format!( + "Foundry server initializing with workspace path: {:?}", + root_path + ), + ) + .await; + let _ = self.load_workspace(root_path).await; + } else { + self.client + .log_message( + MessageType::INFO, + "Foundry server not initialized : no workspace path!", + ) + .await; + } + Ok(InitializeResult { + server_info: None, + capabilities: ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::FULL, + )), + ..ServerCapabilities::default() + }, + }) + } + + async fn initialized(&self, _: InitializedParams) { + self.client + .log_message(MessageType::INFO, "Foundry server initialized!") + .await; + } + + async fn did_open(&self, params: DidOpenTextDocumentParams) { + self.client + .log_message( + MessageType::INFO, + format!("file opened!: {:}", params.text_document.uri), + ) + .await; + let _ = self + .compile(normalized_slash_path(params.text_document.uri.path())) + .await; + } + + async fn did_save(&self, params: DidSaveTextDocumentParams) { + self.client + .log_message( + MessageType::INFO, + format!("file changed!: {:}", params.text_document.uri), + ) + .await; + let _ = self + .compile(normalized_slash_path(params.text_document.uri.path())) + .await; + } + + async fn shutdown(&self) -> Result<()> { + Ok(()) + } +} + +impl Backend { + pub async fn load_workspace(&self, path: String) -> std::result::Result<(), ()> { + let mut state = self.state.lock().await; + match Compiler::new_with_executable_check() { + Ok(compiler) => state.compiler = Some(compiler), + Err(Error::FoundryExecutableNotFound) => { + self.client + .show_message(MessageType::WARNING, "Foundry executable not found. Please install foundry and restart the extension.") + .await; + return Err(()); + } + Err(Error::InvalidFoundryVersion) => { + self.client + .show_message(MessageType::WARNING, "Foundry executable version is not compatible with this extension. Please update foundry and restart the extension.") + .await; + return Err(()); + } + Err(err) => { + self.client + .log_message( + MessageType::ERROR, + &format!("Foundry server failed to initialize: {:?}", err), + ) + .await; + return Err(()); + } + } + if let Err(err) = state.compiler.as_mut().unwrap().load_workspace(path) { + self.client + .log_message( + MessageType::ERROR, + &format!("Foundry server failed to initialize: {:?}", err), + ) + .await; + return Err(()); + } else { + state.initialized = true; + self.client + .log_message(MessageType::INFO, "Foundry server initialized!") + .await; + } + Ok(()) + } + + /** + * This function initializes the workspace if it is not already initialized. + * @param {&str} filepath Filepath to compile + * @returns {Result<(), ()>} Result of the initialization + */ + async fn initialize_if_not(&self, filepath: &str) -> std::result::Result<(), ()> { + let state = self.state.lock().await; + + if !state.initialized { + drop(state); // unlock the mutex before calling load_workspace + + self.client + .log_message(MessageType::INFO, "Foundry server initializing!") + .await; + let folder_path = Path::new(filepath) + .parent() + .unwrap() + .to_str() + .unwrap() + .to_string(); + self.load_workspace(folder_path).await? + } + Ok(()) + } + + pub async fn compile(&self, filepath: String) -> std::result::Result<(), ()> { + self.initialize_if_not(&filepath).await?; + let mut state = self.state.lock().await; + + self.client + .log_message(MessageType::INFO, "Foundry server compiling!") + .await; + + match state.compiler.as_mut().unwrap().compile(&filepath) { + Ok((project_path, output)) => { + /*self.client + .log_message(MessageType::INFO, format!("Compile errors: {:?}", output.get_errors())) + .await;*/ + drop(state); + self.publish_errors_diagnostics(slashify_path(&project_path), filepath, output) + .await; + } + Err(err) => { + self.client + .log_message( + MessageType::ERROR, + format!("error while compiling: {:?}", err), + ) + .await; + } + } + Ok(()) + } + + /** + * Generate and publish diagnostics from compilation errors + * @param {String} project_path Project path + * @param {String} filepath Filepath to compile + * @param {ProjectCompileOutput} output Compilation output + */ + pub async fn publish_errors_diagnostics( + &self, + project_path: String, + filepath: String, + output: ProjectCompileOutput, + ) { + let mut raised_diagnostics = HashMap::>::new(); + + for error in output.get_errors() { + // Generate diagnostic from compilation error + let (affected_file, diagnostic) = + match self.extract_diagnostic(error, &project_path).await { + Some(diagnostic) => diagnostic, + None => continue, + }; + + // Add diagnostic to the hashmap + let url = match affected_file.to_str() { + Some(source_path) => slashify_path(source_path), + None => continue, + }; + if !raised_diagnostics.contains_key(&url) { + raised_diagnostics.insert(url.clone(), vec![diagnostic]); + } else { + raised_diagnostics.get_mut(&url).unwrap().push(diagnostic); + } + } + + self.reset_not_affected_files(project_path, filepath, &raised_diagnostics) + .await; + for (uri, diags) in raised_diagnostics.iter() { + if let Ok(url) = Url::parse(&format!("file://{}", &uri)) { + self.client + .publish_diagnostics(url, diags.clone(), None) + .await; + } else { + self.client + .log_message( + MessageType::ERROR, + format!("error, cannot parse file uri : {}", uri), + ) + .await; + } + } + } + + /** + * Extract diagnostic from compilation error + * @param {CompilationError} compilation_error Compilation error + * @param {String} project_path Project path + * @returns {Option<(PathBuf, Diagnostic)>} Diagnostic + * @returns {None} If the diagnostic cannot be extracted + */ + async fn extract_diagnostic( + &self, + compilation_error: &CompilationError, + project_path: &str, + ) -> Option<(PathBuf, Diagnostic)> { + eprintln!("Compilation error: {:?}", compilation_error); + let (source_content_filepath, range) = match self + .extract_diagnostic_range(project_path, compilation_error) + .await + { + Some((source_content_filepath, range)) => (source_content_filepath, range), + None => return None, + }; + let diagnostic = Diagnostic { + range: Range { + start: Position { + line: range.start.line, + character: range.start.column, + }, + end: Position { + line: range.end.line, + character: range.end.column, + }, + }, + severity: Some(convert_severity(compilation_error.get_severity())), + code: None, + code_description: None, + source: Some("osmium-solidity-foundry-compiler".to_string()), + message: compilation_error.get_message(), + related_information: None, + tags: None, + data: None, + }; + Some((source_content_filepath, diagnostic)) + } + + /** + * Extract diagnostic range from compilation error's source location + * Open the file and get the range from the source location + * @param {String} project_path Project path + * @param {CompilationError} error Compilation error + * @returns {Option<(PathBuf, osmium_libs_foundry_wrapper::Range)>} Diagnostic range + * @returns {None} If the diagnostic range cannot be extracted + */ + async fn extract_diagnostic_range( + &self, + project_path: &str, + error: &CompilationError, + ) -> Option<(PathBuf, osmium_libs_foundry_wrapper::Range)> { + let source_content_filepath = match error.get_file_path() { + Some(source_path) => { + let mut complete_path = Path::new(project_path).to_path_buf(); + complete_path.push(source_path); + complete_path + } + None => { + self.client + .log_message( + MessageType::ERROR, + format!("error, cannot get filepath: {:?}", error), + ) + .await; + return None; + } + }; + let source_content = match std::fs::read_to_string(&source_content_filepath) { + Ok(content) => content, + Err(err) => { + self.client + .log_message( + MessageType::ERROR, + format!( + "error, cannot read file: {:?}, error: {:?}", + &source_content_filepath, err + ), + ) + .await; + return None; + } + }; + let range = match error.get_range(&source_content) { + Some(range) => range, + None => { + self.client + .log_message( + MessageType::ERROR, + format!("error, cannot get range: {:?}", error), + ) + .await; + return None; + } + }; + Some((source_content_filepath, range)) + } + + /** + * This function resets the diagnostics of the files that are not raising an error anymore. + * @param {String} project_path Project path + * @param {String} filepath Filepath to compile + * @param {HashMap>} raised_diagnostics Raised diagnostics + */ + async fn reset_not_affected_files( + &self, + project_path: String, + filepath: String, + raised_diagnostics: &HashMap>, + ) { + let mut state = self.state.lock().await; + + state + .affected_files + .add_project_file(project_path.clone(), filepath.clone()); + let raised_files = raised_diagnostics.keys().cloned().collect::>(); + let without_diagnostics = state + .affected_files + .fill_affected_files(raised_files, &project_path); + + self.client + .log_message( + MessageType::INFO, + format!("files without diagnostic: {:?}", without_diagnostics), + ) + .await; + + for file in without_diagnostics.iter() { + if let Ok(url) = Url::parse(&format!("file://{}", &file)) { + self.client.publish_diagnostics(url, vec![], None).await; + } else { + self.client + .log_message( + MessageType::ERROR, + format!("error, cannot parse file uri : {}", file), + ) + .await; + } + } + } +} + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::new(|client| Backend { + client, + state: Mutex::new(State { + compiler: None, + initialized: false, + affected_files: AffectedFilesStore::new(), + }), + }); + Server::new(stdin, stdout, socket).serve(service).await; +} diff --git a/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs b/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs new file mode 100644 index 00000000..15648f3f --- /dev/null +++ b/toolchains/solidity/core/crates/foundry-compiler-server/src/utils.rs @@ -0,0 +1,63 @@ +use osmium_libs_foundry_wrapper::Severity; +use tower_lsp::lsp_types::{DiagnosticSeverity, InitializeParams}; + +/** + * This function returns the first workspace path from the InitializeParams. + * If there is no workspace path, it returns the root path. + * @returns {Option} Normalized path + */ +pub fn get_root_path(params: InitializeParams) -> Option { + if let Some(folder) = params.workspace_folders?.first() { + return Some(normalize_path(folder.uri.path())); + } else if let Some(root_uri) = params.root_uri { + return Some(normalize_path(root_uri.path())); + } + None +} + +pub fn convert_severity(severity: Severity) -> DiagnosticSeverity { + match severity { + Severity::Error => DiagnosticSeverity::ERROR, + Severity::Warning => DiagnosticSeverity::WARNING, + Severity::Info => DiagnosticSeverity::INFORMATION, + } +} + +/** + * This function normalizes the path for Windows. + * VSCode send the path starting with /%3A/ instead of {letter}:/ + * @param {&str} path Path to normalize + * @returns {String} Normalized path + */ +#[cfg(target_family = "windows")] +pub fn normalize_path(path: &str) -> String { + let mut path = path.replace("%3A/", "://"); + path.remove(0); + path.to_string() +} + +/** + * This function normalizes the path for Linux and MacOS. Nothing to do. + * @param {&str} path Path to normalize + * @returns {String} Normalized path + */ +#[cfg(not(target_family = "windows"))] +pub fn normalize_path(path: &str) -> String { + path.to_string() +} + +/** + * This function replaces all backslashes and double-slahes with slashes. + * This is useful for Windows paths. + * @param {&str} path Path to slashify + * @returns {String} Slashified path + */ +pub fn slashify_path(path: &str) -> String { + path.replace('\\', "/") + .replace("\\\\", "/") + .replace("//", "/") +} + +pub fn normalized_slash_path(path: &str) -> String { + slashify_path(&normalize_path(path)) +} diff --git a/toolchains/solidity/core/crates/linter-cli/Cargo.toml b/toolchains/solidity/core/crates/linter-cli/Cargo.toml index 23d8805d..d825643f 100644 --- a/toolchains/solidity/core/crates/linter-cli/Cargo.toml +++ b/toolchains/solidity/core/crates/linter-cli/Cargo.toml @@ -2,14 +2,14 @@ name = "solidhunter" description = "Fast solidity linter cli" repository = "https://github.com/astrodevs-labs/osmium" -version = "0.2.1" +version = "0.2.4" edition = "2021" license = "GPL-3.0-or-later" authors = ["AstroDevs-Labs"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -solidhunter-lib = { path = "../linter-lib", version = "0.2.0" } +solidhunter-lib = { path = "../linter-lib", version = "0.2.2" } clap = { version = "4.0.29", features = ["derive"] } colored = "2" serde = { version = "1.0.149", features = ["derive"] } diff --git a/toolchains/solidity/core/crates/linter-cli/readme.md b/toolchains/solidity/core/crates/linter-cli/readme.md index c9b65a1d..84781203 100644 --- a/toolchains/solidity/core/crates/linter-cli/readme.md +++ b/toolchains/solidity/core/crates/linter-cli/readme.md @@ -32,6 +32,7 @@ Options: -h, --help Print help information -V, --version Print version information -g, --ignore Specify ignore file + -d, --documentation Exposes rules documentation ``` ## Configuration diff --git a/toolchains/solidity/core/crates/linter-cli/src/main.rs b/toolchains/solidity/core/crates/linter-cli/src/main.rs index dd3f4281..b3520575 100644 --- a/toolchains/solidity/core/crates/linter-cli/src/main.rs +++ b/toolchains/solidity/core/crates/linter-cli/src/main.rs @@ -44,6 +44,14 @@ struct Args { #[arg(short = 'e', long = "exclude", help = "Specify excluded files")] exclude: Option>, + + #[arg( + short = 'd', + long = "documentation", + default_value = "false", + help = "exposes rules documentation" + )] + documentation: bool, } fn print_result(results: Vec) { @@ -60,7 +68,22 @@ fn print_result(results: Vec) { } fn main() -> Result<(), SolidHunterError> { - let mut args = Args::parse(); + let args = Args::parse(); + + if args.documentation { + let linter: SolidLinter = SolidLinter::new_fileless(); + + let json = serde_json::to_string_pretty(&linter.get_documentation()); + match json { + Ok(j) => { + println!("{}", j); + } + Err(e) => { + println!("{}", e); + } + } + return Ok(()); + } if !args.to_json { println!(); @@ -79,21 +102,33 @@ fn main() -> Result<(), SolidHunterError> { println!("Using rules file: {}", args.rules_file); println!("Verbose output: {}", args.verbose); println!("Excluded files: {:?}", args.exclude); + println!("Documentation output: {}", args.documentation); } if args.init { println!("Initializing rules file..."); - create_rules_file(".solidhunter.json"); + if args.paths.is_empty() { + create_rules_file(&args.rules_file); + } + for path in &args.paths { + if let Ok(metadata) = std::fs::metadata(path.as_str()) { + if metadata.is_dir() { + create_rules_file(&(path.as_str().to_owned() + "/" + args.rules_file.as_str())); + } + } + } println!("Done!"); return Ok(()); } - if args.paths.is_empty() { - args.paths.push(String::from(".")); - } - let mut linter: SolidLinter = SolidLinter::new(); - linter.initialize_rules(&args.rules_file)?; + if !args.paths.is_empty() { + linter.initialize_rules( + &(args.paths[0].as_str().to_owned() + "/" + args.rules_file.as_str()), + )?; + } else { + linter.initialize_rules(&args.rules_file)?; + } linter.initialize_excluded_files(args.exclude.as_ref(), &args.paths)?; let mut results = vec![]; @@ -101,6 +136,11 @@ fn main() -> Result<(), SolidHunterError> { let result = linter.parse_path(path); results.push(result); } + // If no path is specified, we use the current directory + if args.paths.is_empty() { + let result = linter.parse_path("."); + results.push(result); + } for path_result in results { if !args.to_json { print_result(path_result); diff --git a/toolchains/solidity/core/crates/linter-lib/Cargo.toml b/toolchains/solidity/core/crates/linter-lib/Cargo.toml index e3468157..40ce5f3e 100644 --- a/toolchains/solidity/core/crates/linter-lib/Cargo.toml +++ b/toolchains/solidity/core/crates/linter-lib/Cargo.toml @@ -2,7 +2,7 @@ name = "solidhunter-lib" description = "Solidhunter/Osmium solidity linter library" repository = "https://github.com/astrodevs-labs/osmium" -version = "0.2.0" +version = "0.2.2" edition = "2021" authors = ["Astrodevs Labs"] license = "GPL-3.0-or-later" @@ -16,7 +16,7 @@ colored = "2" serde = { version = "1.0.149", features = ["derive"] } serde_json = "1.0.89" anyhow = "1.0" -glob = "0.3.0" +glob = "0.3.1" thiserror = "1.0" osmium-libs-solidity-ast-extractor = { path = "../../../../../libs/ast-extractor", version = "0.1.2" } regex = "1.9.6" diff --git a/toolchains/solidity/core/crates/linter-lib/src/linter.rs b/toolchains/solidity/core/crates/linter-lib/src/linter.rs index da50f1f9..20d2f9f4 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/linter.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/linter.rs @@ -2,6 +2,7 @@ use crate::errors::SolidHunterError; use crate::rules::create_default_rules; use crate::rules::factory::RuleFactory; use crate::rules::rule_impl::parse_rules; +use crate::rules::rule_impl::parse_rules_content; use crate::rules::types::*; use crate::types::*; use std::fs; @@ -64,6 +65,14 @@ impl SolidLinter { Ok(()) } + pub fn get_documentation(&self) -> Vec { + let mut res = Vec::new(); + for rule in &self.rules { + res.push(rule.get_documentation()) + } + res + } + pub fn initialize_excluded_files( &mut self, excluded_filepaths: Option<&Vec>, @@ -76,7 +85,14 @@ impl SolidLinter { } self.excluded_files .append(&mut get_excluded_files(filepaths)?); + Ok(()) + } + pub fn initialize_rules_content(&mut self, rules_config: &str) -> Result<(), SolidHunterError> { + let res = parse_rules_content(rules_config)?; + for rule in res.rules { + self.rules.push(self.rule_factory.create_rule(rule)); + } Ok(()) } @@ -120,15 +136,103 @@ impl SolidLinter { self.parse_content(&filepath, content.as_str()) } + fn _check_is_in_disable_range(&self, diag: &LintDiag, disable_ranges: &[DisableRange]) -> bool { + let mut rules_occurrences = vec![]; + + let filtered_range = disable_ranges + .iter() + // we only care about ranges that start before the diag + .filter(|range| range.start_line <= diag.range.start.line) + .map(|range| { + if range.rule_ids.is_empty() { + DisableRange { + rule_ids: vec!["".to_string()], // empty rule means all rules + ..range.clone() + } + } else { + range.clone() + } + }) + .collect::>(); + + for range in &filtered_range { + match range.ignore_type { + Ignore::SameLine | Ignore::NextLine => { + if range.start_line == diag.range.start.line + && (range.rule_ids.contains(&diag.id) + || range.rule_ids.contains(&"".to_string())) + { + return true; + } + } + Ignore::Disable => { + for rule in &range.rule_ids { + let mut found = false; + for (rule_id, occurences) in &mut rules_occurrences { + if *rule_id == rule { + *occurences += 1; + found = true; + break; + } + } + if !found { + rules_occurrences.push((rule, 1)); + } + } + } + Ignore::Enable => { + for rule in &range.rule_ids { + for (rule_id, occurences) in &mut rules_occurrences { + if *rule_id == rule { + *occurences -= 1; + break; + } + } + // TODO: global disable followed by a scoped enable might not work + } + } + } + } + + let disabled_rules = rules_occurrences + .iter() + .filter(|(_, occurences)| *occurences > 0) + .map(|(rule, _)| rule.to_string()) + .collect::>(); + + for rule in disabled_rules { + if rule.is_empty() || rule == diag.id { + return true; + } + } + false + } + + fn _check_is_diag_ignored(&self, diag: &LintDiag, file: &SolidFile) -> bool { + let ignore_comments: Vec = file + .content + .lines() + .enumerate() + .filter_map(|(line_number, line)| IgnoreComment::from_line(line_number + 1, line)) + .collect(); + let disable_ranges = build_disable_ranges(ignore_comments); + + self._check_is_in_disable_range(diag, &disable_ranges) + } + pub fn parse_content(&mut self, filepath: &str, content: &str) -> LintResult { let res = osmium_libs_solidity_ast_extractor::extract::extract_ast_from_content(content)?; self._add_file(filepath, res, content); - let mut res: Vec = Vec::new(); + let mut res: Vec<_> = vec![]; for rule in &self.rules { let mut diags = rule.diagnose(&self.files[self.files.len() - 1], &self.files); - res.append(&mut diags); + for diag in &mut diags { + if !self._check_is_diag_ignored(diag, &self.files[self.files.len() - 1]) { + res.push(diag.clone()); + } + } } Ok(FileDiags::new(content.to_string(), res)) } diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/custom_errors.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/custom_errors.rs index c6957c57..1ee562de 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/custom_errors.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/custom_errors.rs @@ -67,6 +67,48 @@ impl RuleType for CustomErrors { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Enforces the use of Custom Errors over Require and Revert statements" + .to_string(), + category: "best-practises".to_string(), + example_config: "{\"id\": \"custom-errors\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/custom_errors.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/CustomErrors".to_string(), + options: vec![], + examples: Examples { + good: vec![ + Example { + description: "Use Custom Errors".to_string(), + code: "revert CustomErrorFunction();".to_string(), + }, + Example { + description: "Use of Custom Errors with arguments".to_string(), + code: "revert CustomErrorFunction({ msg: \"Insufficient Balance\" });" + .to_string(), + }, + ], + bad: vec![ + Example { + description: "Use of require statement".to_string(), + code: "require(userBalance >= availableAmount, \"Insufficient Balance\");" + .to_string(), + }, + Example { + description: "Use of plain revert statement".to_string(), + code: "revert();".to_string(), + }, + Example { + description: "Use of revert statement with message".to_string(), + code: "revert(\"Insufficient Balance\");".to_string(), + }, + ], + }, + } + } } impl CustomErrors { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/explicit_types.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/explicit_types.rs index cf614918..73011b68 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/explicit_types.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/explicit_types.rs @@ -114,6 +114,54 @@ impl RuleType for ExplicitTypes { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: + "Forbid or enforce explicit types (like uint256) that have an alias (like uint)." + .to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"explicit-types\", \"severity\": \"WARNING\", \"data\": \"explicit\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/explicit_types.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ExplicitTypes".to_string(), + options: vec![Options { + description: "Options need to be one of \"explicit\", \"implicit\"".to_string(), + default: "explicit".to_string(), + }], + examples: Examples { + good: vec![ + Example { + description: "If explicit is selected".to_string(), + code: "uint256 public variableName;".to_string(), + }, + Example { + description: "If implicit is selected".to_string(), + code: "uint public variableName;".to_string(), + }, + Example { + description: "If explicit is selected".to_string(), + code: "uint256 public variableName = uint256(5);".to_string(), + }, + ], + bad: vec![ + Example { + description: "If explicit is selected".to_string(), + code: "uint public variableName;".to_string(), + }, + Example { + description: "If implicit is selected".to_string(), + code: "uint256 public variableName;".to_string(), + }, + Example { + description: "At any setting".to_string(), + code: "uint public variableName = uint256(5);".to_string(), + }, + ], + }, + } + } } impl ExplicitTypes { @@ -134,7 +182,6 @@ impl ExplicitTypes { let rule = ExplicitTypes { rule: value, data }; Box::new(rule) } - pub(crate) fn create_default() -> RuleEntry { RuleEntry { id: RULE_ID.to_string(), diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/function_max_lines.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/function_max_lines.rs index a704c0de..e76f8d5a 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/function_max_lines.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/function_max_lines.rs @@ -49,6 +49,28 @@ impl RuleType for FunctionMaxLines { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: + "Function body contains \"count\" lines but allowed no more than maxlines." + .to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"function-max-lines\", \"severity\": \"WARNING\", \"data\": 20}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/function_max_lines.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/FunctionMaxLines".to_string(), + options: vec![Options { + description: "Maximum allowed lines count per function ".to_string(), + default: "50".to_string(), + }], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } // returns a struct containing the line number of the start and end of the function if it is too long diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_line_length.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_line_length.rs index 751f19a5..c3fff2f4 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_line_length.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_line_length.rs @@ -54,6 +54,26 @@ impl RuleType for MaxLineLength { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Line length must be no more than maxlen.".to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"max-line-length\", \"severity\": \"WARNING\", \"data\": 80}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/max_line_length.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/MaxLineLength".to_string(), + options: vec![Options { + description: "Maximum allowed number of characters per line".to_string(), + default: "120".to_string(), + }], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl MaxLineLength { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_states_count.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_states_count.rs index 984798f5..c7af4dce 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_states_count.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/max_states_count.rs @@ -68,6 +68,24 @@ impl RuleType for MaxStatesCount { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Contract has \"some count\" states declarations but allowed no more than maxstates.".to_string(), + category: "best-practices".to_string(), + example_config: " {\"id\": \"max-states-count\", \"severity\": \"WARNING\", \"data\": [15]}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/max_states_count.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/MaxStatesCount".to_string(), + options: vec![Options{description: "Maximum allowed states declarations".to_string(), + default: "15".to_string(),}], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl MaxStatesCount { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_console.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_console.rs index c0ecbb32..f1962e4b 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_console.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_console.rs @@ -1,7 +1,7 @@ use osmium_libs_solidity_ast_extractor::*; use crate::linter::SolidFile; -use crate::rules::types::{RuleEntry, RuleType}; +use crate::rules::types::{Example, Examples, RuleDocumentation, RuleEntry, RuleType}; use crate::types::{LintDiag, Position, Range, Severity}; // global @@ -91,6 +91,29 @@ impl RuleType for NoConsole { res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "No console.log/logInt/logBytesX/logString/etc & No hardhat and forge-std console.sol import statements.".to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"no-console\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/no_console.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NoConsole".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![Example{description: "No console.logX statements".to_string(), + code: "console.log('test');".to_string()}, + Example{description: "No hardhat/console.sol import statements".to_string(), + code: "import 'hardhat/console.sol';".to_string()}, + Example{description: "No forge-std console.sol & console2.sol import statements".to_string(), + code: "import 'forge-std/consoleN.sol';".to_string()}, + ], + }, + } + } } impl NoConsole { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_empty_block.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_empty_block.rs index b667614c..c8a5295d 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_empty_block.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_empty_block.rs @@ -34,6 +34,47 @@ impl RuleType for NoEmptyBlock { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Code block has zero statements inside. Exceptions apply.".to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"no-empty-block\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/no_empty_block.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NoEmptyBlock".to_string(), + options: vec![], + examples: Examples { + good: vec![ + Example { + description: "Empty fallback function".to_string(), + code: "fallback() external {}".to_string(), + }, + Example { + description: "Empty constructor with member initialization list" + .to_string(), + code: "constructor(uint param) Foo(param) Bar(param*2) { }".to_string(), + }, + ], + bad: vec![ + Example { + description: "Empty block on if statement".to_string(), + code: "if (condition) { }".to_string(), + }, + Example { + description: "Empty contract".to_string(), + code: "contract Foo { }".to_string(), + }, + Example { + description: "Empty block in constructor without parent initialization" + .to_string(), + code: "constructor() { }".to_string(), + }, + ], + }, + } + } } fn check_empty_block(file: &SolidFile) -> Vec> { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_global_import.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_global_import.rs index 9ce99f5f..489b00e0 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_global_import.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/no_global_import.rs @@ -33,6 +33,46 @@ impl RuleType for NoGlobalImport { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Import statement includes an entire file instead of selected symbols." + .to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"no-global-import\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/no_global_import.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NoGlobalImport".to_string(), + options: vec![], + examples: Examples { + good: vec![ + Example { + description: "import names explicitly".to_string(), + code: "import {A} from \"./A.sol\"".to_string(), + }, + Example { + description: "import entire file into a name".to_string(), + code: "import \"./A.sol\" as A".to_string(), + }, + Example { + description: "import entire file into a name".to_string(), + code: "import * as A from \"./A.sol\"".to_string(), + }, + ], + bad: vec![ + Example { + description: "import all members from a file".to_string(), + code: "import * from \"foo.sol\";".to_string(), + }, + Example { + description: "import an entire file".to_string(), + code: "import \"foo.sol\"".to_string(), + }, + ], + }, + } + } } fn check_global_import(file: &SolidFile) -> Vec> { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/one_contract_per_file.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/one_contract_per_file.rs index 516f1db6..4930ff28 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/one_contract_per_file.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/one_contract_per_file.rs @@ -53,6 +53,32 @@ impl RuleType for OneContractPerFile { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Imported object name is not being used by the contract.".to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"one-contract-per-file\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/one_contract_per_file.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/OneContractPerFile".to_string(), + options: vec![], + examples: Examples { + good: vec![Example { + description: "Imported object is being used".to_string(), + code: + "import { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nContract MyToken is ERC20 {}" + .to_string(), + }], + bad: vec![Example { + description: "Imported object is not being used".to_string(), + code: "import { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nContract B {}" + .to_string(), + }], + }, + } + } } impl OneContractPerFile { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/payable_fallback.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/payable_fallback.rs index 8d798e06..78d2bfed 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/payable_fallback.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/payable_fallback.rs @@ -36,6 +36,30 @@ impl RuleType for PayableFallback { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "When fallback is not payable you will not be able to receive ethers." + .to_string(), + category: "best-practices".to_string(), + example_config: "{\"id\": \"payable-fallback\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/payable_fallback.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/PayableFallback".to_string(), + options: vec![], + examples: Examples { + good: vec![Example { + description: "Fallback is payable".to_string(), + code: "pragma solidity 0.4.4;\n\ncontract A {\n\tfunction () public payable {}\n}".to_string(), + }], + bad: vec![Example { + description: "Fallback is not payable".to_string(), + code: "pragma solidity 0.4.4;\n\ncontract A {\n\tfunction () public {}\n}".to_string(), + }], + }, + } + } } fn check_fallback_payable(file: &SolidFile) -> Vec> { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/reason_string.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/reason_string.rs index fb6ca252..c21791e0 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/reason_string.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/best_practises/reason_string.rs @@ -1,7 +1,7 @@ use osmium_libs_solidity_ast_extractor::*; use crate::linter::SolidFile; -use crate::rules::types::{RuleEntry, RuleType}; +use crate::rules::types::{Examples, Options, RuleDocumentation, RuleEntry, RuleType}; use crate::types::{LintDiag, Position, Range, Severity}; // global @@ -127,6 +127,24 @@ impl RuleType for ReasonString { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Require or revert statement must have a reason string and check that each reason string is at most N characters long.".to_string(), + category: "best-practices".to_string(), + example_config: " {\"id\": \"reason-string\", \"severity\": \"WARNING\", \"data\": 20}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/best_practices/reason_string.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ReasonString".to_string(), + options: vec![Options{description: "A JSON object with a single property \"maxLength\" specifying the max number of characters per reason string.".to_string(), + default: "{\"maxLength\":32}".to_string()}], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl ReasonString { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/const_name_snakecase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/const_name_snakecase.rs index 5f3c66ed..64ccad2b 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/const_name_snakecase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/const_name_snakecase.rs @@ -67,6 +67,23 @@ impl RuleType for ConstNameSnakeCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Constant name must be in capitalized SNAKE_CASE. (Does not check IMMUTABLES, use immutable-vars-naming)".to_string(), + category: "naming".to_string(), + example_config: " {\"id\": \"const-name-snakecase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/const_name_snakecase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ConstNameSnakecase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl ConstNameSnakeCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/contract_name_camelcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/contract_name_camelcase.rs index e5871e2f..0c76da7b 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/contract_name_camelcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/contract_name_camelcase.rs @@ -56,6 +56,23 @@ impl RuleType for ContractNameCamelCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Contract name must be in CamelCase.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"contract-name-camelcase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/contract_name_camelcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ContractNameCamelcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl ContractNameCamelCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/event_name_camelcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/event_name_camelcase.rs index 840226e2..859da766 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/event_name_camelcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/event_name_camelcase.rs @@ -77,6 +77,23 @@ impl RuleType for EventNameCamelCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Event name must be in CamelCase.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"event-name-camelcase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/event_name_camelcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/EventNameCamelcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl EventNameCamelCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/foundry_test_functions.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/foundry_test_functions.rs index 51128bda..c9f821e0 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/foundry_test_functions.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/foundry_test_functions.rs @@ -99,6 +99,47 @@ impl RuleType for FoundryTestFunctions { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Enforce naming convention on functions for Foundry test cases" + .to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"foundry-test-functions\", \"severity\": \"WARNING\", \"data\": [\"setUp\"]}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/foundry_test_functions.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/FoundryTestFunctions".to_string(), + options: vec![Options { + description: "Array of function to be skipped".to_string(), + default: "[]".to_string(), + }], + examples: Examples { + good: vec![ + Example { + description: "Foundry test case with correct Function declaration" + .to_string(), + code: "function test_NumberIs42() public {}".to_string(), + }, + Example { + description: "Foundry test case with correct Function declaration" + .to_string(), + code: "function testFail_Subtract43() public {}".to_string(), + }, + Example { + description: "Foundry test case with correct Function declaration" + .to_string(), + code: "function testFuzz_FuzzyTest() public {}".to_string(), + }, + ], + bad: vec![Example { + description: "Foundry test case with incorrect Function declaration" + .to_string(), + code: "function numberIs42() public {}".to_string(), + }], + }, + } + } } impl FoundryTestFunctions { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_name_mixedcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_name_mixedcase.rs index 0c24dc78..6acac49f 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_name_mixedcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_name_mixedcase.rs @@ -64,6 +64,23 @@ impl RuleType for FuncNameMixedCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Function name must be in mixedCase.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"func-name-mixedcase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_name_mixedcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/FuncNameMixedcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl FuncNameMixedCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_param_name_mixedcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_param_name_mixedcase.rs index 54d88752..7df4c845 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_param_name_mixedcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_param_name_mixedcase.rs @@ -63,6 +63,23 @@ impl RuleType for FuncParamNameMixedCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Function param name must be in mixedCase.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"func-param-name-mixedcase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/func_param_name_mixedcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/FuncParamNameMixedcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl FuncParamNameMixedCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/modifier_name_mixedcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/modifier_name_mixedcase.rs index 48fcd0aa..a9b58988 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/modifier_name_mixedcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/modifier_name_mixedcase.rs @@ -80,6 +80,23 @@ impl RuleType for ModifierNameMixedcase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Modifier name must be in mixedCase.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"modifier-name-mixedcase\", \"severity\": \"WARNING\", \"data\": []}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/modifier_name_mixedcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ModifierNameMixedcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl ModifierNameMixedcase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/named_parameters_mapping.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/named_parameters_mapping.rs index 78a59639..50eabfc6 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/named_parameters_mapping.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/named_parameters_mapping.rs @@ -92,6 +92,58 @@ impl RuleType for NamedParametersMapping { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Solidity v0.8.18 introduced named parameters on the mappings definition.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"named-parameters-mapping\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/named_parameters_mapping.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NamedParametersMapping".to_string(), + options: vec![], + examples: Examples { + good: vec![ + Example { + description: "To enter \"users\" mapping the key called \"name\" is needed to get the \"balance\"".to_string(), + code: "mapping(string name => uint256 balance) public users;".to_string(), + }, + Example { + description: "To enter owner token balance, the main key \"owner\" enters another mapping which its key is \"token\" to get its \"balance\"".to_string(), + code: "mapping(address owner => mapping(address token => uint256 balance)) public tokenBalances;".to_string(), + }, + Example { + description: "Main key of mapping is enforced. On nested mappings other naming are not neccesary".to_string(), + code: "mapping(address owner => mapping(address => uint256)) public tokenBalances;".to_string(), + }, Example { + description: "Main key of the parent mapping is enforced. No naming in nested mapping uint256".to_string(), + code: "mapping(address owner => mapping(address token => uint256)) public tokenBalances;".to_string(), + }, Example { + description: "Main key of the parent mapping is enforced. No naming in nested mapping address".to_string(), + code: "mapping(address owner => mapping(address => uint256 balance)) public tokenBalances;".to_string(), + }, + ], + bad: vec![ + Example { + description: "No naming at all in regular mapping".to_string(), + code: "mapping(address => uint256)) public tokenBalances;".to_string(), + }, + Example { + description: "Missing any variable name in regular mapping uint256".to_string(), + code: "mapping(address token => uint256)) public tokenBalances;".to_string(), + }, + Example { + description: "Missing any variable name in regular mapping address".to_string(), + code: "mapping(address => uint256 balance)) public tokenBalances;".to_string(), + }, Example { + description: "No MAIN KEY naming in nested mapping. Other naming are not enforced".to_string(), + code: "mapping(address => mapping(address token => uint256 balance)) public tokenBalances;".to_string(), + }, + ], + }, + } + } } impl NamedParametersMapping { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/private_vars_leading_underscore.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/private_vars_leading_underscore.rs index c2eb25bc..94486656 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/private_vars_leading_underscore.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/private_vars_leading_underscore.rs @@ -150,6 +150,50 @@ impl RuleType for PrivateVarsLeadingUnderscore { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Non-external functions and state variables should start with a single underscore. Others, shouldn't".to_string(), + category: "naming".to_string(), + example_config: " {\"id\": \"private-vars-leading-underscore\", \"severity\": \"WARNING\", \"data\": {\"strict\": true}}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/private_vars_leading_underscore.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/PrivateVarsLeadingUnderscore".to_string(), + options: vec![Options { + description: "A JSON object with a single property \"strict\" specifying if the rule should apply to ALL non state variables. Default: { strict: false }.".to_string(), + default: "{\"strict\":false}".to_string(), + }], + examples: Examples { + good: vec![Example { + description: "Internal function with correct naming".to_string(), + code: "function _thisIsInternal() internal {}".to_string(), + }, Example { + description: "Private function with correct naming".to_string(), + code: "function _thisIsPrivate() private {}".to_string(), + }, Example { + description: "Internal state variable with correct naming".to_string(), + code: "uint256 internal _thisIsInternalVariable;".to_string(), + }, Example { + description: "Internal state variable with correct naming (no visibility is considered internal)".to_string(), + code: "uint256 _thisIsInternalVariable;".to_string(), + }], + bad: vec![Example { + description: "Internal function with incorrect naming".to_string(), + code: "function thisIsInternal() internal {}".to_string(), + }, Example { + description: "Private function with incorrect naming".to_string(), + code: "function thisIsPrivate() private {}".to_string(), + }, Example { + description: "Internal state variable with incorrect naming".to_string(), + code: "uint256 internal thisIsInternalVariable;".to_string(), + }, Example { + description: "Internal state variable with incorrect naming (no visibility is considered internal)".to_string(), + code: "uint256 thisIsInternalVariable;".to_string(), + }], + }, + } + } } impl PrivateVarsLeadingUnderscore { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/use_forbidden_name.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/use_forbidden_name.rs index 94781d9b..97b9d03b 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/use_forbidden_name.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/use_forbidden_name.rs @@ -61,6 +61,23 @@ impl RuleType for UseForbiddenName { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Avoid to use letters 'I', 'l', 'O' as identifiers.".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"use-forbidden-name\", \"severity\": \"WARNING\", \"data\": []}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/use_forbidden_name.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/UseForbiddenName".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl UseForbiddenName { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/var_name_mixedcase.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/var_name_mixedcase.rs index 9fc95ed1..dd112ff4 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/naming/var_name_mixedcase.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/naming/var_name_mixedcase.rs @@ -68,6 +68,23 @@ impl RuleType for VarNameMixedCase { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Variable name must be in mixedCase. (Does not check IMMUTABLES, use immutable-vars-naming)".to_string(), + category: "naming".to_string(), + example_config: "{\"id\": \"var-name-mixedcase\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/naming/var_name_mixedcase.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/VarNameMixedcase".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl VarNameMixedCase { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/order/import_on_top.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/order/import_on_top.rs index 2518db39..c8ecbd29 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/order/import_on_top.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/order/import_on_top.rs @@ -69,6 +69,23 @@ impl RuleType for ImportOnTop { res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Import statements must be on top.".to_string(), + category: "order".to_string(), + example_config: "{\"id\": \"import-on-top\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/order/import_on_top.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/ImportOnTop".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl ImportOnTop { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/order/ordering.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/order/ordering.rs index 60afa75a..296105b5 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/order/ordering.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/order/ordering.rs @@ -515,6 +515,23 @@ impl RuleType for Ordering { visitor.visit_file(&file.data); visitor.reports } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Check order of elements in file and inside each contract, according to the style guide.".to_string(), + category: "order".to_string(), + example_config: "{\"id\": \"ordering\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/order/ordering.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/Ordering".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl Ordering { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/order/visibility_modifier_order.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/order/visibility_modifier_order.rs index feff35a4..427174dd 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/order/visibility_modifier_order.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/order/visibility_modifier_order.rs @@ -36,6 +36,23 @@ impl RuleType for VisibilityModiferOrder { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Visibility modifier must be first in list of modifiers.".to_string(), + category: "order".to_string(), + example_config: "{\"id\": \"visibility-modifier-order\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/order/visibility_modifier_order.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/VisibilityModifierOrder".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } fn check_visibility_modifier_order(file: &SolidFile) -> Vec { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/rule_impl.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/rule_impl.rs index 093433f7..e5639582 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/rule_impl.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/rule_impl.rs @@ -9,7 +9,7 @@ pub fn create_rules_file(path: &str) { }; let serialized = serde_json::to_string_pretty(&rules).unwrap(); - std::fs::write(path, serialized).unwrap(); + let _ = std::fs::write(path, serialized); } pub fn parse_rules(path: &str) -> Result { @@ -24,3 +24,9 @@ pub fn parse_rules(path: &str) -> Result { Ok(parsed) } + +pub fn parse_rules_content(content: &str) -> Result { + let parsed: Rules = serde_json::from_str(content)?; + + Ok(parsed) +} diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/security/avoid_tx_origin.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/security/avoid_tx_origin.rs index 8186ca48..43e5bea8 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/security/avoid_tx_origin.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/security/avoid_tx_origin.rs @@ -76,6 +76,23 @@ impl RuleType for AvoidTxOrigin { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Avoid to use tx.origin.".to_string(), + category: "security".to_string(), + example_config: " {\"id\": \"avoid-tx-origin\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/security/avoid_tx_origin.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/AvoidTxOrigin".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl AvoidTxOrigin { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/security/func_visibility.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/security/func_visibility.rs index b6348fc1..c53d25e5 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/security/func_visibility.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/security/func_visibility.rs @@ -7,6 +7,7 @@ use osmium_libs_solidity_ast_extractor::Spanned; pub const RULE_ID: &str = "func-visibility"; // specific +const DEFAULT_SEVERITY: Severity = Severity::WARNING; const DEFAULT_MESSAGE: &str = "Explicitly mark visibility in function (public, private, internal, external)"; pub const DEFAULT_IGNORE_CONSTRUCTORS: bool = true; @@ -76,6 +77,32 @@ impl RuleType for FuncVisibility { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Explicitly mark visibility in function.".to_string(), + category: "security".to_string(), + example_config: "{\"id\": \"func-visibility\", \"severity\": \"WARNING\", \"data\": {\"ignoreConstructors\": false}}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/security/func_visibility.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/FuncVisibility".to_string(), + options: vec![Options { + description: "A JSON object with a single property \"ignoreConstructors\" specifying if the rule should ignore constructors. (Note: This is required to be true for Solidity >=0.7.0 and false for <0.7.0)".to_string(), + default: "{\"ignoreConstructors\":false}".to_string(), + }], + examples: Examples { + good: vec![Example { + description: "Functions explicitly marked with visibility".to_string(), + code: "function b() internal { }\nfunction b() external { }\nfunction b() private { }\nfunction b() public { }\nconstructor() public { }".to_string(), + }], + bad: vec![Example { + description: "Functions without explicitly marked visibility".to_string(), + code: "function b() { }".to_string(), + }], + }, + } + } } impl FuncVisibility { @@ -103,7 +130,7 @@ impl FuncVisibility { pub(crate) fn create_default() -> RuleEntry { RuleEntry { id: RULE_ID.to_string(), - severity: Severity::WARNING, + severity: DEFAULT_SEVERITY, data: Some(serde_json::json!({ "ignoreConstructors": DEFAULT_IGNORE_CONSTRUCTORS, })), diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/security/no_inline_assembly.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/security/no_inline_assembly.rs index c6f717e9..0741ca26 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/security/no_inline_assembly.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/security/no_inline_assembly.rs @@ -51,6 +51,24 @@ impl RuleType for NoInlineAssembly { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Avoid to use inline assembly. It is acceptable only in rare cases." + .to_string(), + category: "security".to_string(), + example_config: "{\"id\": \"no-inline-assembly\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/security/no_inline_assembly.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NoInlineAssembly".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl NoInlineAssembly { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/security/not_rely_on_time.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/security/not_rely_on_time.rs index 413a57ee..2febac0c 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/security/not_rely_on_time.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/security/not_rely_on_time.rs @@ -1,7 +1,7 @@ use crate::linter::SolidFile; use crate::rules::types::*; use crate::types::*; -use osmium_libs_solidity_ast_extractor::*; +use osmium_libs_solidity_ast_extractor::LineColumn; // global pub const RULE_ID: &str = "not-rely-on-time"; @@ -77,6 +77,23 @@ impl RuleType for NotRelyOnTime { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Avoid making time-based decisions in your business logic.".to_string(), + category: "security".to_string(), + example_config: "{\"id\": \"not-rely-on-time\", \"severity\": \"WARNING\"}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/security/not_rely_on_time.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/NotRelyOnTime".to_string(), + options: vec![], + examples: Examples { + good: vec![], + bad: vec![], + }, + } + } } impl NotRelyOnTime { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/security/state_visibility.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/security/state_visibility.rs index 9efbf4a6..1ae0e57f 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/security/state_visibility.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/security/state_visibility.rs @@ -54,6 +54,29 @@ impl RuleType for StateVisibility { } res } + + fn get_documentation(&self) -> RuleDocumentation { + RuleDocumentation { + id: RULE_ID.to_string(), + severity: DEFAULT_SEVERITY, + description: "Explicitly mark visibility of state.".to_string(), + category: "security".to_string(), + example_config: "{\"id\": \"state-visibility\", \"severity\": \"WARNING\", \"data\": []}".to_string(), + source_link: "https://github.com/astrodevs-labs/osmium/blob/main/toolchains/solidity/core/crates/linter-lib/src/rules/security/state_visibility.rs".to_string(), + test_link: "https://github.com/astrodevs-labs/osmium/tree/main/toolchains/solidity/core/crates/linter-lib/testdata/".to_string(), + options: vec![], + examples: Examples { + good: vec![Example { + description: "State explicitly marked with visibility".to_string(), + code: "uint public data;".to_string(), + }], + bad: vec![Example { + description: "Functions without explicitly marked visibility".to_string(), + code: "uint data;".to_string(), + }], + }, + } + } } impl StateVisibility { diff --git a/toolchains/solidity/core/crates/linter-lib/src/rules/types.rs b/toolchains/solidity/core/crates/linter-lib/src/rules/types.rs index 09e6030e..32199a70 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/rules/types.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/rules/types.rs @@ -4,6 +4,37 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Options { + pub description: String, + pub default: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Example { + pub description: String, + pub code: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Examples { + pub good: Vec, + pub bad: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct RuleDocumentation { + pub id: String, + pub severity: Severity, + pub description: String, + pub category: String, + pub example_config: String, + pub source_link: String, + pub test_link: String, + pub options: Vec, + pub examples: Examples, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RuleEntry { pub id: String, @@ -20,6 +51,7 @@ pub struct Rules { pub trait RuleType: Send + Sync + 'static { fn diagnose(&self, file: &SolidFile, files: &[SolidFile]) -> Vec; + fn get_documentation(&self) -> RuleDocumentation; } pub type RulesMap = HashMap Box>; diff --git a/toolchains/solidity/core/crates/linter-lib/src/types.rs b/toolchains/solidity/core/crates/linter-lib/src/types.rs index c1a6a7af..682660dc 100644 --- a/toolchains/solidity/core/crates/linter-lib/src/types.rs +++ b/toolchains/solidity/core/crates/linter-lib/src/types.rs @@ -10,6 +10,8 @@ mod lint_diag; pub use lint_diag::LintDiag; mod file_diags; pub use file_diags::FileDiags; +mod ignore; +pub use ignore::*; pub type LintResult = Result; diff --git a/toolchains/solidity/core/crates/linter-lib/src/types/ignore.rs b/toolchains/solidity/core/crates/linter-lib/src/types/ignore.rs new file mode 100644 index 00000000..fc163b6c --- /dev/null +++ b/toolchains/solidity/core/crates/linter-lib/src/types/ignore.rs @@ -0,0 +1,127 @@ +use serde::{Deserialize, Serialize}; + +macro_rules! define_ignore_enum { + ($name:ident, $($variant:ident => $str:expr),* $(,)?) => { + #[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Debug)] + pub enum $name { + $($variant),* + } + + impl ToString for $name { + fn to_string(&self) -> String { + match self { + $(Self::$variant => $str),* + } + .to_string() + } + } + + impl $name { + pub fn iter() -> impl Iterator { + [$(Self::$variant),*].iter().copied() + } + } + }; +} + +define_ignore_enum! { + Ignore, + NextLine => "solidhunter-disable-next-line", + SameLine => "solidhunter-disable-line", + Disable => "solidhunter-disable", + Enable => "solidhunter-enable", +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct IgnoreComment { + pub line_number: usize, + pub ignore_type: Ignore, + pub rule_ids: Option>, +} + +impl IgnoreComment { + pub fn from_line(line_number: usize, line: &str) -> Option { + for ignore in Ignore::iter() { + let ignore_str = ignore.to_string(); + if line.contains(&ignore_str) { + let rule_ids_str = line.split(&ignore_str).nth(1); + let rule_ids = rule_ids_str + .map(|s| { + s.split(' ') + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect::>() + }) + .filter(|s| !s.is_empty()); + return Some(Self { + line_number, + ignore_type: ignore, + rule_ids, + }); + } + } + None + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DisableRange { + pub start_line: usize, + pub end_line: usize, + pub ignore_type: Ignore, + pub rule_ids: Vec, +} + +pub fn build_disable_ranges(comments: Vec) -> Vec { + let mut disable_ranges = vec![]; + let mut current_range: Option = None; + + for comment in comments { + let line_number = comment.line_number; + let ignore_type = comment.ignore_type; + let rule_ids = comment.rule_ids.unwrap_or(vec![]); + + match ignore_type { + Ignore::Enable | Ignore::Disable => { + if let Some(range) = current_range { + disable_ranges.push(range); + } + current_range = Some(DisableRange { + start_line: line_number, + end_line: line_number, + ignore_type, + rule_ids, + }); + } + Ignore::SameLine => { + if let Some(range) = &mut current_range { + range.end_line = line_number; + } + disable_ranges.push(DisableRange { + start_line: line_number, + end_line: line_number, + ignore_type, + rule_ids, + }); + } + Ignore::NextLine => { + if let Some(range) = &mut current_range { + range.end_line = line_number; + } + disable_ranges.push(DisableRange { + start_line: line_number + 1, + end_line: line_number + 1, + ignore_type, + rule_ids, + }); + } + } + } + + if let Some(range) = current_range { + disable_ranges.push(range); + } + + disable_ranges +} diff --git a/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/.solidhunter.json b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/.solidhunter.json new file mode 100644 index 00000000..96de8e57 --- /dev/null +++ b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/.solidhunter.json @@ -0,0 +1,8 @@ +{ + "name": "solidhunter", "rules": [ + { + "id": "avoid-tx-origin", + "severity": "WARNING" + } + ] +} \ No newline at end of file diff --git a/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/file.sol b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/file.sol new file mode 100644 index 00000000..613d53ab --- /dev/null +++ b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/file.sol @@ -0,0 +1,66 @@ +pragma solidity 0.8.0; + +contract Test { + function awesome() public returns (address) { + // solidhunter-disable-next-line exist-with-error + return tx.origin; // solidhunter-disable-line exist-with-error + } + + function awesomeLineUp() public returns (address) { + // solidhunter-disable-next-line avoid-tx-origin + return tx.origin; + } + function awesomeSameLine() public returns (address) { + return tx.origin; // solidhunter-disable-line avoid-tx-origin + } + + function notAwesome() public returns (address) { + // solidhunter-disable-next-line not-exist-no-error + return msg.sender; // solidhunter-disable-line not-exist-no-error + } + + function awesomeLineUpAny() public returns (address) { + // solidhunter-disable-next-line + return tx.origin; + } + function awesomeSameLineAny() public returns (address) { + return tx.origin; // solidhunter-disable-line + } + + function awesomeLineUpAny() public returns (address) { + // solidhunter-disable-next-line dummy-rule avoid-tx-origin dummy-rule2 + return tx.origin; + } + function awesomeSameLineAny() public returns (address) { + return tx.origin; // solidhunter-disable-line dummy-rule avoid-tx-origin dummy-rule2 + } + + // solidhunter-disable + function awesome() public returns (address) { + return tx.origin; + } + // solidhunter-enable + + + // solidhunter-disable + // solidhunter-disable + // solidhunter-enable + function awesome() public returns (address) { + return tx.origin; + } + // solidhunter-enable + + // solidhunter-disable avoid-tx-origin + function awesome() public returns (address) { + return tx.origin; + } + // solidhunter-enable avoid-tx-origin + + // solidhunter-disable avoid-tx-origin + // solidhunter-disable + // solidhunter-enable avoid-tx-origin + function awesome() public returns (address) { + return tx.origin; + } + // solidhunter-enable +} \ No newline at end of file diff --git a/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/findings.csv b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/findings.csv new file mode 100644 index 00000000..a0a4913b --- /dev/null +++ b/toolchains/solidity/core/crates/linter-lib/testdata/SolidHunterIgnoreRule/findings.csv @@ -0,0 +1 @@ +avoid-tx-origin:6:15:6:24 \ No newline at end of file diff --git a/toolchains/solidity/core/crates/linter-lib/tests/linter.rs b/toolchains/solidity/core/crates/linter-lib/tests/linter.rs index 05bf0d4e..94663ee1 100644 --- a/toolchains/solidity/core/crates/linter-lib/tests/linter.rs +++ b/toolchains/solidity/core/crates/linter-lib/tests/linter.rs @@ -171,7 +171,8 @@ test_directories! { Ordering, PrivateVarsLeadingUnderscore, FoundryTestFunctions, - AvoidTxOrigin + AvoidTxOrigin, + SolidHunterIgnoreRule, } #[allow(non_snake_case)] diff --git a/toolchains/solidity/core/crates/linter-server/Cargo.toml b/toolchains/solidity/core/crates/linter-server/Cargo.toml index ce4305b0..9d200a1e 100644 --- a/toolchains/solidity/core/crates/linter-server/Cargo.toml +++ b/toolchains/solidity/core/crates/linter-server/Cargo.toml @@ -1,11 +1,14 @@ [package] name = "linter-server" license = "GPL-3.0-or-later" -version = "0.2.0" +version = "0.2.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -osmium-libs-lsp-server-wrapper = { path = "../../../../../libs/lsp-server-wrapper", version = "0.1.0" } -solidhunter-lib = { path = "../linter-lib", version = "0.2.0" } \ No newline at end of file +osmium-libs-lsp-server-wrapper = { path = "../../../../../libs/lsp-server-wrapper", version = "0.2.0" } +solidhunter-lib = { path = "../linter-lib", version = "0.2.2" } +glob = "0.3.0" +serde = { version = "1.0.149", features = ["derive"] } +serde_json = "1.0.89" diff --git a/toolchains/solidity/core/crates/linter-server/src/get_content.rs b/toolchains/solidity/core/crates/linter-server/src/get_content.rs new file mode 100644 index 00000000..16bc1458 --- /dev/null +++ b/toolchains/solidity/core/crates/linter-server/src/get_content.rs @@ -0,0 +1,20 @@ +use osmium_libs_lsp_server_wrapper::lsp_types::request::Request; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ContentRequestParams { + pub uri: String, +} + +pub struct ContentRequest {} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ContentResponse { + pub content: String, +} + +impl Request for ContentRequest { + type Params = ContentRequestParams; + type Result = ContentResponse; + const METHOD: &'static str = "osmium/getContent"; +} diff --git a/toolchains/solidity/core/crates/linter-server/src/main.rs b/toolchains/solidity/core/crates/linter-server/src/main.rs index 28f0932b..993cbaa0 100644 --- a/toolchains/solidity/core/crates/linter-server/src/main.rs +++ b/toolchains/solidity/core/crates/linter-server/src/main.rs @@ -1,8 +1,12 @@ use osmium_libs_lsp_server_wrapper::{ - lsp_types::*, Client, LanguageServer, LspStdioServer, Result, + lsp_types::*, Client, LanguageServer, LspStdioServer, RequestId, Result, }; use solidhunter_lib::{linter::SolidLinter, types::LintDiag}; use std::{cell::RefCell, rc::Rc}; +mod utils; +use utils::get_closest_config_filepath; +mod get_content; +use get_content::{ContentRequest, ContentRequestParams, ContentResponse}; struct Backend { connection: Rc>, @@ -10,8 +14,35 @@ struct Backend { } impl LanguageServer for Backend { - fn initialize(&self, _: InitializeParams) -> Result { - eprintln!("starting example main loop"); + fn initialize(&self, params: InitializeParams) -> Result { + let connection = self.connection.borrow_mut(); + connection.log_message(MessageType::INFO, "Server initializing!"); + if let Ok(Some(path)) = get_closest_config_filepath(&connection, params.clone()) { + connection.log_message( + MessageType::INFO, + format!("Initializing linter with workspace path: {:?}", path), + ); + let mut linter = SolidLinter::new(); + + let res = linter.initialize_rules(&path); + if res.is_ok() { + self.linter.replace(Some(linter)); + } else { + connection.log_message( + MessageType::ERROR, + "Failed to initialize linter with workspace path, using fileless linter", + ); + let linter = SolidLinter::new_fileless(); + self.linter.replace(Some(linter)); + } + } else { + connection.log_message( + MessageType::INFO, + "Initializing linter without workspace path", + ); + let linter = SolidLinter::new_fileless(); + self.linter.replace(Some(linter)); + } Ok(InitializeResult { server_info: None, capabilities: ServerCapabilities { @@ -24,14 +55,6 @@ impl LanguageServer for Backend { } fn initialized(&self, _: InitializedParams) { - self.connection - .borrow_mut() - .log_message(MessageType::INFO, "Server initialized!"); - - self.linter - .borrow_mut() - .replace(SolidLinter::new_fileless()); - self.connection .borrow_mut() .log_message(MessageType::INFO, "Linter initialized!"); @@ -64,6 +87,76 @@ impl LanguageServer for Backend { params.content_changes[0].text.clone(), ); } + + fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams) { + self.connection + .borrow_mut() + .log_message(MessageType::INFO, "configuration file changed!"); + + if params.changes[0].typ == FileChangeType::DELETED { + return; + } + + let params = ContentRequestParams { + uri: params.changes[0].uri.path().to_string().clone(), + }; + + let res = self + .connection + .borrow_mut() + .send_request::(params.clone()); + + if res.is_err() { + self.connection.borrow_mut().log_message( + MessageType::ERROR, + "Failed to send request to get configuration file content!", + ); + return; + } + + self.connection.borrow_mut().log_message( + MessageType::INFO, + format!( + "Sent request to get file content for config file : {:}", + params.uri + ), + ); + } + + fn on_response(&self, _: RequestId, result: Option) { + self.connection + .borrow_mut() + .log_message(MessageType::INFO, "Got response!"); + + if result.is_none() { + self.connection + .borrow_mut() + .log_message(MessageType::ERROR, "Get content response is empty!"); + return; + } + let res: serde_json::Result = + serde_json::from_value::(result.unwrap()); + if res.is_err() { + self.connection + .borrow_mut() + .log_message(MessageType::ERROR, "Failed to parse response!"); + return; + } + let response: ContentResponse = res.unwrap(); + + let mut linter = SolidLinter::new(); + let res = linter.initialize_rules_content(&response.content); + if res.is_ok() { + self.connection + .borrow_mut() + .log_message(MessageType::INFO, "configuration file loaded!"); + self.linter.replace(Some(linter)); + } else { + self.connection + .borrow_mut() + .log_message(MessageType::ERROR, "configuration file failed to load!"); + } + } } impl Backend { diff --git a/toolchains/solidity/core/crates/linter-server/src/utils.rs b/toolchains/solidity/core/crates/linter-server/src/utils.rs new file mode 100644 index 00000000..478e498d --- /dev/null +++ b/toolchains/solidity/core/crates/linter-server/src/utils.rs @@ -0,0 +1,96 @@ +use glob::{glob, PatternError}; +use osmium_libs_lsp_server_wrapper::{ + lsp_types::{InitializeParams, MessageType, WorkspaceFolder}, + Client, +}; + +pub fn get_closest_config_filepath( + connection: &Client, + params: InitializeParams, +) -> Result, PatternError> { + let root_path_url = params.root_uri.unwrap(); + let root_path = root_path_url.path(); + connection.log_message(MessageType::INFO, format!("root_path: {:?}", root_path)); + + if let Some(folders) = params.workspace_folders { + connection.log_message(MessageType::INFO, format!("folders: {:?}", folders)); + return get_closest_workspace_config_filepath(connection, folders); + } + + // Return the path to the closest .solidhunter.json file + let paths = glob(&format!("{}/**/.solidhunter.json", root_path))?; + let mut all_configs = vec![]; + for path in paths.flatten() { + all_configs.push(path.to_str().unwrap().to_string()); + } + all_configs.sort_by_key(|a| a.len()); + if all_configs.is_empty() { + return Ok(None); + } + Ok(Some(all_configs[0].clone())) +} + +fn get_closest_workspace_config_filepath( + connection: &Client, + folders: Vec, +) -> Result, PatternError> { + let mut paths: Vec = Vec::new(); + for folder in folders { + let workspace_path = folder.uri.path(); + + let file_content = + match std::fs::read_to_string(format!("{}/.solidhunter.json", workspace_path)) { + Ok(content) => content, + Err(err) => { + connection.log_message( + MessageType::ERROR, + format!( + "error, cannot read file: {:?}, error: {:?}", + format!("{}/.solidhunter.json", workspace_path), + err + ), + ); + continue; + } + }; + connection.log_message( + MessageType::INFO, + format!("file_content: {:?}", file_content), + ); + + let pattern = format!("{}/**/.solidhunter.json", workspace_path); + connection.log_message(MessageType::INFO, format!("pattern: {:?}", pattern)); + let workspaces_paths = glob(&pattern).map_err(|err| { + connection.log_message(MessageType::ERROR, format!("error: {:?}", err)); + err + })?; + let mut all_configs = vec![]; + for path in workspaces_paths { + match path { + Ok(path) => { + connection.log_message(MessageType::INFO, format!("pushing path: {:?}", path)); + all_configs.push(path.to_str().unwrap().to_string()); + } + Err(err) => { + connection.log_message(MessageType::ERROR, format!("error: {:?}", err)); + } + } + } + connection.log_message(MessageType::INFO, format!("all_configs: {:?}", all_configs)); + all_configs.sort_by_key(|a| a.len()); + // Push the shortest path , if any exist + if !all_configs.is_empty() { + connection.log_message( + MessageType::INFO, + format!("pushing workspace_path: {:?}", workspace_path), + ); + paths.push(all_configs[0].clone()); + } + } + paths.sort_by_key(|a| a.len()); + connection.log_message(MessageType::INFO, format!("paths: {:?}", paths)); + if paths.is_empty() { + return Ok(None); + } + Ok(Some(paths[0].clone())) +} diff --git a/toolchains/solidity/core/crates/slither-server/Cargo.toml b/toolchains/solidity/core/crates/slither-server/Cargo.toml new file mode 100644 index 00000000..bdf4d969 --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "slither-server" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +os = "0.1.0" +serde = "1.0.193" +serde_derive = "1.0.193" +serde_json = "1.0.108" +tokio = { version="1.34.0", features = ["full"] } +tower-lsp = "0.20.0" +colored = "2.0.4" +thiserror = "1.0.50" diff --git a/toolchains/solidity/core/crates/slither-server/src/error.rs b/toolchains/solidity/core/crates/slither-server/src/error.rs new file mode 100644 index 00000000..c8526990 --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/src/error.rs @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum SlitherError { + #[error("Error while runing slither")] + Unknown, + #[error("Error while runing the slither command: {0}")] + IoCommandError(#[from] std::io::Error), + #[error("Error while parsing slither output: {0}")] + ParsingFailed(#[from] serde_json::Error), +} diff --git a/toolchains/solidity/core/crates/slither-server/src/main.rs b/toolchains/solidity/core/crates/slither-server/src/main.rs new file mode 100644 index 00000000..bf78bd26 --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/src/main.rs @@ -0,0 +1,171 @@ +mod error; +mod slither; +mod types; + +use crate::error::SlitherError; +use crate::slither::*; +use tower_lsp::jsonrpc::Result; +use tower_lsp::lsp_types::*; +use tower_lsp::{Client, LanguageServer, LspService, Server}; + +#[derive(Debug)] +struct Backend { + client: Client, +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, _: InitializeParams) -> Result { + if !is_slither_installed() { + self.client + .show_message( + MessageType::ERROR, + "Slither is not installed! Please install it and restart the extension", + ) + .await; + self.client + .log_message(MessageType::ERROR, "Slither is not installed!") + .await; + return Err(tower_lsp::jsonrpc::Error::internal_error()); + } + if !is_solc_installed() { + self.client + .show_message( + MessageType::ERROR, + "Solc is not installed! Please install it and restart the extension", + ) + .await; + self.client + .log_message(MessageType::ERROR, "Solc is not installed!") + .await; + return Err(tower_lsp::jsonrpc::Error::internal_error()); + } + Ok(InitializeResult { + server_info: None, + capabilities: ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::INCREMENTAL, + )), + workspace: Some(WorkspaceServerCapabilities { + workspace_folders: Some(WorkspaceFoldersServerCapabilities { + supported: Some(true), + change_notifications: Some(OneOf::Left(true)), + }), + file_operations: None, + }), + ..ServerCapabilities::default() + }, + }) + } + + async fn initialized(&self, _: InitializedParams) { + self.client + .log_message(MessageType::INFO, "osmium-slither initialized!") + .await; + } + + async fn shutdown(&self) -> Result<()> { + Ok(()) + } + + async fn did_open(&self, file: DidOpenTextDocumentParams) { + self.client + .log_message( + MessageType::INFO, + format!( + "Opened file '{}' for analyzing.", + file.text_document.uri.path() + ), + ) + .await; + if file.text_document.uri.path().ends_with(".t.sol") { + self.client + .log_message( + MessageType::INFO, + format!( + "File '{}' is a test solidity file, skipping analysis.", + file.text_document.uri.path() + ), + ) + .await; + return; + } + self.check_slither_result(file.text_document.uri).await + } + + async fn did_save(&self, file: DidSaveTextDocumentParams) { + self.client + .log_message( + MessageType::INFO, + format!( + "Saved file '{}' for analyzing.", + file.text_document.uri.path() + ), + ) + .await; + if file.text_document.uri.path().ends_with(".t.sol") { + self.client + .log_message( + MessageType::INFO, + format!( + "File '{}' is a test solidity file, skipping analysis.", + file.text_document.uri.path() + ), + ) + .await; + return; + } + self.check_slither_result(file.text_document.uri).await + } +} + +impl Backend { + async fn check_slither_result(&self, uri: Url) { + let res = exec_slither(uri.path()); + match res { + Ok(res) => { + self.client + .log_message( + MessageType::INFO, + format!( + "File '{}' did generate {} security diagnostics.", + uri.path(), + res.len() + ), + ) + .await; + self.client.publish_diagnostics(uri, res, None).await; + } + Err(SlitherError::ParsingFailed(e)) => { + self.client + .log_message( + MessageType::ERROR, + format!( + "File '{}' did generate an error while parsing the output: {:?}", + uri.path(), + e + ), + ) + .await; + self.client.publish_diagnostics(uri, vec![], None).await; + } + Err(e) => { + self.client + .log_message( + MessageType::ERROR, + format!("File '{}' did generate an error: {:?}", uri.path(), e), + ) + .await; + } + } + } +} + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::new(|client| Backend { client }); + Server::new(stdin, stdout, socket).serve(service).await; +} diff --git a/toolchains/solidity/core/crates/slither-server/src/slither.rs b/toolchains/solidity/core/crates/slither-server/src/slither.rs new file mode 100644 index 00000000..f23586eb --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/src/slither.rs @@ -0,0 +1,50 @@ +use crate::error::SlitherError; +use crate::types::SlitherResult; +use std::process::Command; +use tower_lsp::lsp_types::Diagnostic; + +pub fn is_slither_installed() -> bool { + let output = Command::new("slither").arg("--version").output(); + output.is_ok() +} + +pub fn is_solc_installed() -> bool { + let output = Command::new("solc").arg("--version").output(); + output.is_ok() +} + +#[cfg(target_family = "windows")] +fn normalize_slither_path(path: &str) -> String { + let mut path = path.replace("%3A/", "://"); + path.remove(0); + path.to_string() +} + +#[cfg(not(target_family = "windows"))] +fn normalize_slither_path(path: &str) -> String { + path.to_string() +} + +pub fn exec_slither(filepath: &str) -> Result, SlitherError> { + let mut results: Vec = Vec::new(); + let out = Command::new("slither") + .arg(normalize_slither_path(filepath)) + .arg("--exclude") + .arg("naming-convention") + .arg("--json") + .arg("-") + .output()?; + if out.status.code() == Some(1) { + eprintln!("Unknown error occured: {:?}", out); + return Err(SlitherError::Unknown); + } + if out.stdout.is_empty() { + return Ok(results); + } + let json: SlitherResult = + serde_json::from_str(&String::from_utf8_lossy(&out.stdout).replace("\\\"", "\""))?; + for detector in json.results.detectors { + results.append(&mut crate::types::diag_from_json(detector.clone())); + } + Ok(results) +} diff --git a/toolchains/solidity/core/crates/slither-server/src/types.rs b/toolchains/solidity/core/crates/slither-server/src/types.rs new file mode 100644 index 00000000..0486f555 --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/src/types.rs @@ -0,0 +1,125 @@ +use serde::{Deserialize, Serialize}; +use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity as Severity, Position, Range}; + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherResult { + pub results: SlitherResults, + pub success: bool, + pub error: Option, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherResults { + pub detectors: Vec, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherDetector { + pub elements: Vec, + pub description: String, + pub check: String, + pub impact: String, + pub id: String, + pub confidence: String, + pub markdown: String, + pub first_markdown_element: String, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherElement { + pub source_mapping: SlitherSourceMapping, + + #[serde(rename = "type")] + pub type_: String, + pub name: String, + pub type_specific_fields: Option, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherSourceMapping { + pub filename_absolute: String, + pub filename_relative: String, + pub filename_short: String, + pub is_dependency: bool, + pub lines: Vec, + pub starting_column: usize, + pub ending_column: usize, + pub length: usize, + pub start: usize, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherTypeSpecificFields { + pub directive: Option>, + pub signature: Option, + pub additional_fields: Option, + pub parent: Option, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherParent { + pub name: String, + #[serde(rename = "type")] + pub type_: String, + pub type_specific_fields: Option>, + pub source_mapping: Option, + pub signature: Option, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct SlitherAdditionalFields { + pub underlying_type: Option, + pub visibility: Option, + pub variable_name: Option, +} + +pub fn diag_from_json(json: SlitherDetector) -> Vec { + let mut results: Vec = Vec::new(); + + for idx in 0..json.elements.len() { + if json.elements[idx].source_mapping.lines.is_empty() + || json.elements[idx].type_ == "contract" + { + continue; + } + let lines = &json.elements[idx].source_mapping.lines; + let start_col = json.elements[idx].source_mapping.starting_column; + let end_col = json.elements[idx].source_mapping.ending_column; + let range = Range { + start: Position { + line: lines[0] as u32 - 1, + character: start_col as u32 - 1, + }, + end: Position { + line: lines[lines.len() - 1] as u32 - 1, + character: end_col as u32, + }, + }; + + let severity = match json.impact.as_str() { + "High" => Severity::ERROR, + "Medium" => Severity::WARNING, + "Low" => Severity::HINT, + "Informational" => Severity::INFORMATION, + _ => Severity::ERROR, + }; + + results.push(Diagnostic { + range, + severity: Some(severity), + code: None, + code_description: None, + source: Some("osmium-slither".to_string()), + message: json.description.to_string() + "\nCheck: " + &json.check, + related_information: None, + tags: None, + data: None, + }); + } + + results +} + +//////////////////////////////////////////////////////////// +/////////////////// RELATED TYPES: ///////////////////////// +//////////////////////////////////////////////////////////// diff --git a/toolchains/solidity/core/crates/slither-server/test.json b/toolchains/solidity/core/crates/slither-server/test.json new file mode 100644 index 00000000..e6a2a763 --- /dev/null +++ b/toolchains/solidity/core/crates/slither-server/test.json @@ -0,0 +1,860 @@ +{ + "success": true, + "error": null, + "results": { + "detectors": [ + { + "elements": [ + { + "type": "variable", + "name": "test", + "source_mapping": { + "start": 293, + "length": 16, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 10 + ], + "starting_column": 9, + "ending_column": 25 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "test", + "source_mapping": { + "start": 230, + "length": 254, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "test()" + } + } + } + }, + { + "type": "function", + "name": "test", + "source_mapping": { + "start": 230, + "length": 254, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "test()" + } + } + ], + "description": "Test.test().test (VarNameMixedCase/file.sol#10) shadows:\n\t- Test.test() (VarNameMixedCase/file.sol#9-15) (function)\n", + "markdown": "[Test.test().test](VarNameMixedCase/file.sol#L10) shadows:\n\t- [Test.test()](VarNameMixedCase/file.sol#L9-L15) (function)\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L10", + "id": "cd02f0d58377d623f3c8889edc1f9cef4c816f5f91b6dc77ec5ab0a30f0da89a", + "check": "shadowing-local", + "impact": "Low", + "confidence": "High" + }, + { + "elements": [ + { + "type": "pragma", + "name": "^0.8.0", + "source_mapping": { + "start": 0, + "length": 23, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 1 + ], + "starting_column": 1, + "ending_column": 24 + }, + "type_specific_fields": { + "directive": [ + "solidity", + "^", + "0.8", + ".0" + ] + } + } + ], + "description": "Pragma version^0.8.0 (VarNameMixedCase/file.sol#1) allows old versions\n", + "markdown": "Pragma version[^0.8.0](VarNameMixedCase/file.sol#L1) allows old versions\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L1", + "id": "2dda11de37b3076df14acf93394be6277599b82b9eee970c37fab5b9b1b8005a", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.8.0 is not recommended for deployment\n", + "markdown": "solc-0.8.0 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "c298e4718eba1e635e63e4c3206d561ac1974eaef1a3bba154ff9c56bcf6282a", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "test_contract_for_linter", + "source_mapping": { + "start": 172, + "length": 36, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 5, + "ending_column": 41 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + }, + "additional_fields": { + "target": "variable", + "convention": "mixedCase" + } + } + ], + "description": "Variable Test.test_contract_for_linter (VarNameMixedCase/file.sol#7) is not in mixedCase\n", + "markdown": "Variable [Test.test_contract_for_linter](VarNameMixedCase/file.sol#L7) is not in mixedCase\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L7", + "id": "4e48c72cfd518c91e9520f8e00950ca6857a81e2e829c5d2cf15090f07337b4e", + "check": "naming-convention", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "test_contract_for_linter", + "source_mapping": { + "start": 172, + "length": 36, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 5, + "ending_column": 41 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + }, + { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + ], + "description": "Test.test_contract_for_linter (VarNameMixedCase/file.sol#7) is never used in Test (VarNameMixedCase/file.sol#3-16)\n", + "markdown": "[Test.test_contract_for_linter](VarNameMixedCase/file.sol#L7) is never used in [Test](VarNameMixedCase/file.sol#L3-L16)\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L7", + "id": "249b0e713ea45bf6437843661e45195736cb77b9f51e8567b2efab053a8b5a79", + "check": "unused-state", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "contracts", + "source_mapping": { + "start": 48, + "length": 21, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 4 + ], + "starting_column": 5, + "ending_column": 26 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + }, + { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + ], + "description": "Test.contracts (VarNameMixedCase/file.sol#4) is never used in Test (VarNameMixedCase/file.sol#3-16)\n", + "markdown": "[Test.contracts](VarNameMixedCase/file.sol#L4) is never used in [Test](VarNameMixedCase/file.sol#L3-L16)\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L4", + "id": "4a65411183e0d7542dfef6c8fbf65127f35f02df5c617af7f34b249d00b6170b", + "check": "unused-state", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "testContractForLinter", + "source_mapping": { + "start": 123, + "length": 33, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 6 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + }, + { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + ], + "description": "Test.testContractForLinter (VarNameMixedCase/file.sol#6) is never used in Test (VarNameMixedCase/file.sol#3-16)\n", + "markdown": "[Test.testContractForLinter](VarNameMixedCase/file.sol#L6) is never used in [Test](VarNameMixedCase/file.sol#L3-L16)\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L6", + "id": "a838f6c866f803a79379bef45de3562aea0b2bd25b45a236b1f20a1241e3f2bb", + "check": "unused-state", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "_contract2", + "source_mapping": { + "start": 85, + "length": 22, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 5 + ], + "starting_column": 5, + "ending_column": 27 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + }, + { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + ], + "description": "Test._contract2 (VarNameMixedCase/file.sol#5) is never used in Test (VarNameMixedCase/file.sol#3-16)\n", + "markdown": "[Test._contract2](VarNameMixedCase/file.sol#L5) is never used in [Test](VarNameMixedCase/file.sol#L3-L16)\n", + "first_markdown_element": "VarNameMixedCase/file.sol#L5", + "id": "ecf8c5b3c78ca9c1e8015e0726d5ccb9d6a3e6584d0e7c8a779fba5abea92640", + "check": "unused-state", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "contracts", + "source_mapping": { + "start": 48, + "length": 21, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 4 + ], + "starting_column": 5, + "ending_column": 26 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Test.contracts (VarNameMixedCase/file.sol#4) should be constant \n", + "markdown": "[Test.contracts](VarNameMixedCase/file.sol#L4) should be constant \n", + "first_markdown_element": "VarNameMixedCase/file.sol#L4", + "id": "6db1de55012a570ba924671b4431a1fb4aa17a1312a12c385b19cab0ac0cdbac", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "_contract2", + "source_mapping": { + "start": 85, + "length": 22, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 5 + ], + "starting_column": 5, + "ending_column": 27 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Test._contract2 (VarNameMixedCase/file.sol#5) should be constant \n", + "markdown": "[Test._contract2](VarNameMixedCase/file.sol#L5) should be constant \n", + "first_markdown_element": "VarNameMixedCase/file.sol#L5", + "id": "81ce76bdea73dfd45eb250dc7e2437ec8b3ed809bbe65651577a7e8a06bd8940", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "test_contract_for_linter", + "source_mapping": { + "start": 172, + "length": 36, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 5, + "ending_column": 41 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Test.test_contract_for_linter (VarNameMixedCase/file.sol#7) should be constant \n", + "markdown": "[Test.test_contract_for_linter](VarNameMixedCase/file.sol#L7) should be constant \n", + "first_markdown_element": "VarNameMixedCase/file.sol#L7", + "id": "9420b4e072bd069f87d9bd6212424e443a593b4d6c6fc9a43c86f346d98f916f", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "testContractForLinter", + "source_mapping": { + "start": 123, + "length": 33, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 6 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Test", + "source_mapping": { + "start": 27, + "length": 460, + "filename_relative": "VarNameMixedCase/file.sol", + "filename_absolute": "C:\\Users\\trigr\\Work\\astrodevs-labs\\osmium\\toolchains\\solidity\\core\\crates\\linter-lib\\testdata\\VarNameMixedCase\\file.sol", + "filename_short": "VarNameMixedCase/file.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Test.testContractForLinter (VarNameMixedCase/file.sol#6) should be constant \n", + "markdown": "[Test.testContractForLinter](VarNameMixedCase/file.sol#L6) should be constant \n", + "first_markdown_element": "VarNameMixedCase/file.sol#L6", + "id": "ff4df4c88e398e8a146a65bedf8261150643c59f4f37e678398b043cd7426732", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + } + ] + } +} \ No newline at end of file diff --git a/toolchains/solidity/core/crates/tests-positions-server/Cargo.toml b/toolchains/solidity/core/crates/tests-positions-server/Cargo.toml new file mode 100644 index 00000000..84aa3876 --- /dev/null +++ b/toolchains/solidity/core/crates/tests-positions-server/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "tests-positions-server" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +exclude.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +osmium-libs-lsp-server-wrapper = { path = "../../../../../libs/lsp-server-wrapper", version = "0.2.0" } +serde = { version = "1.0.149", features = ["derive"] } +serde_json = "1.0.89" +tokio = {version = "1.34.0", features = ["full"] } +tower-lsp = "0.20.0" +osmium-libs-solidity-ast-extractor = { path = "../../../../../libs/ast-extractor", version = "0.1.2" } +regex = "1.10.2" diff --git a/toolchains/solidity/core/crates/tests-positions-server/src/get_tests_positions.rs b/toolchains/solidity/core/crates/tests-positions-server/src/get_tests_positions.rs new file mode 100644 index 00000000..652934e5 --- /dev/null +++ b/toolchains/solidity/core/crates/tests-positions-server/src/get_tests_positions.rs @@ -0,0 +1,33 @@ +use osmium_libs_lsp_server_wrapper::lsp_types::{request::Request, Range}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GetTestsPositionsParams { + pub file_content: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TestContract { + pub name: String, + pub range: Range, + pub tests: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Test { + pub name: String, + pub range: Range, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GetTestsPositionsResponse { + pub contracts: Vec, +} + +pub struct GetTestsPositionsRequest {} + +impl Request for GetTestsPositionsRequest { + type Params = GetTestsPositionsParams; + type Result = GetTestsPositionsResponse; + const METHOD: &'static str = "osmium/getTestsPositions"; +} diff --git a/toolchains/solidity/core/crates/tests-positions-server/src/main.rs b/toolchains/solidity/core/crates/tests-positions-server/src/main.rs new file mode 100644 index 00000000..63152c3f --- /dev/null +++ b/toolchains/solidity/core/crates/tests-positions-server/src/main.rs @@ -0,0 +1,99 @@ +use get_tests_positions::{GetTestsPositionsParams, GetTestsPositionsResponse, Test, TestContract}; +use osmium_libs_solidity_ast_extractor::retriever::retrieve_functions_nodes; +use osmium_libs_solidity_ast_extractor::File; +use osmium_libs_solidity_ast_extractor::{ + extract::extract_ast_from_content, retriever::retrieve_contract_nodes, +}; +use tower_lsp::jsonrpc::{self, Result}; +use tower_lsp::lsp_types::*; +use tower_lsp::{Client, LanguageServer, LspService, Server}; + +mod get_tests_positions; +mod utils; +use utils::range_from_spanned; + +#[derive(Debug)] +struct Backend { + client: Client, +} + +#[tower_lsp::async_trait] +impl LanguageServer for Backend { + async fn initialize(&self, _: InitializeParams) -> Result { + Ok(InitializeResult::default()) + } + + async fn initialized(&self, _: InitializedParams) { + self.client + .log_message(MessageType::INFO, "server initialized!") + .await; + } + + async fn shutdown(&self) -> Result<()> { + Ok(()) + } +} + +impl Backend { + fn new(client: Client) -> Self { + Self { client } + } + + async fn get_tests_positions( + &self, + params: GetTestsPositionsParams, + ) -> Result { + self.client + .log_message(MessageType::INFO, "Getting tests positions for file") + .await; + let res = extract_ast_from_content(¶ms.file_content); + + if let Ok(ast) = res { + self.extract_tests_positions(ast) + } else { + let err = res.unwrap_err(); + eprintln!("Error: {:?}", err); + Err(jsonrpc::Error::invalid_params(format!("Error: {:?}", err))) + } + } + + pub fn extract_tests_positions(&self, ast: File) -> Result { + let mut res = vec![]; + let re = regex::Regex::new(r"^test.*_.+").unwrap(); + let contracts = retrieve_contract_nodes(&ast); + for contract in contracts { + let mut tests: Vec = vec![]; + let mut functions = retrieve_functions_nodes(&contract); + let contract_tests = functions.iter_mut().filter(|f| { + f.name.is_some() && re.is_match(f.name.as_ref().unwrap().as_string().as_str()) + }); + for test in contract_tests { + let name = match &test.name { + Some(name) => name, + None => continue, + }; + tests.push(Test { + name: name.as_string(), + range: range_from_spanned(name), + }); + } + res.push(TestContract { + name: contract.name.as_string(), + range: range_from_spanned(&contract.name), + tests, + }); + } + Ok(GetTestsPositionsResponse { contracts: res }) + } +} + +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::build(Backend::new) + .custom_method("osmium/getTestsPositions", Backend::get_tests_positions) + .finish(); + Server::new(stdin, stdout, socket).serve(service).await; +} diff --git a/toolchains/solidity/core/crates/tests-positions-server/src/utils.rs b/toolchains/solidity/core/crates/tests-positions-server/src/utils.rs new file mode 100644 index 00000000..c8160328 --- /dev/null +++ b/toolchains/solidity/core/crates/tests-positions-server/src/utils.rs @@ -0,0 +1,19 @@ +use osmium_libs_solidity_ast_extractor::{LineColumn, Spanned}; +use tower_lsp::lsp_types::{Position, Range}; + +pub fn range_from_span(start: LineColumn, end: LineColumn) -> Range { + Range { + start: Position { + line: start.line as u32, + character: start.column as u32, + }, + end: Position { + line: end.line as u32, + character: end.column as u32, + }, + } +} + +pub fn range_from_spanned(spanned: &T) -> Range { + range_from_span(spanned.span().start(), spanned.span().end()) +} diff --git a/toolchains/solidity/core/scripts/copy-core.js b/toolchains/solidity/core/scripts/copy-core.js index 386df391..58948cb8 100644 --- a/toolchains/solidity/core/scripts/copy-core.js +++ b/toolchains/solidity/core/scripts/copy-core.js @@ -18,7 +18,7 @@ fs.readdir('target', { withFileTypes: true }, (err, dirs) => { return; } const files = entries.filter(file => file.isFile()).map(file => file.name); - const serverBinaries = files.filter(file => file.endsWith('-server')); + const serverBinaries = files.filter(file => file.endsWith('-server') || file.endsWith('-server.exe')); serverBinaries.forEach(binary => { fs.copyFile(`target/${dir}/${binary}`, `${outputFolder}/${binary}`, (err) => { if (err) { diff --git a/toolchains/solidity/extension/.gitignore b/toolchains/solidity/extension/.gitignore new file mode 100644 index 00000000..c195d8dc --- /dev/null +++ b/toolchains/solidity/extension/.gitignore @@ -0,0 +1,2 @@ +!.vscode/launch.json +!.vscode/tasks.json diff --git a/toolchains/solidity/extension/package.json b/toolchains/solidity/extension/package.json index c4875980..90305130 100644 --- a/toolchains/solidity/extension/package.json +++ b/toolchains/solidity/extension/package.json @@ -2,7 +2,7 @@ "name": "osmium-solidity-extension", "displayName": "Osmium Solidity", "description": "", - "version": "0.2.0", + "version": "0.1.3", "publisher": "OsmiumToolchains", "repository": { "type": "git", @@ -16,14 +16,18 @@ "Other" ], "activationEvents": [ - "onLanguage:solidity" + "workspaceContains:solidity" ], "main": "./dist/extension.js", "contributes": { "commands": [ { - "command": "extension.helloWorld", - "title": "Hello World" + "command": "osmium.lint-sol-file", + "title": "Osmium: Lint Solidity File" + }, + { + "command": "osmium.lint-sol-workspace", + "title": "Osmium: Lint Solidity Workspace" } ], "languages": [ diff --git a/toolchains/solidity/extension/src/extension.ts b/toolchains/solidity/extension/src/extension.ts index 2d021566..f6e1193d 100644 --- a/toolchains/solidity/extension/src/extension.ts +++ b/toolchains/solidity/extension/src/extension.ts @@ -1,72 +1,41 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import { glob } from 'glob'; -import * as path from 'path'; import { workspace, ExtensionContext } from 'vscode'; - import { LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind } from 'vscode-languageclient/node'; - -let client: LanguageClient; +import { createLinterClient } from './linter'; +import { createFoundryCompilerClient } from './foundry-compiler'; +import { createSlitherClient } from './slither'; +import { createTestsPositionsClient } from './tests-positions'; +import registerForgeFmtLinter from "./fmt-wrapper"; +import { TestManager } from './tests/test-manager'; + +let slitherClient: LanguageClient; +let linterClient: LanguageClient; +let foundryCompilerClient: LanguageClient; +let testsPositionsClient: LanguageClient; +let testManager: TestManager; export async function activate(context: ExtensionContext) { - // The server is implemented in node - const serverBinary = context.asAbsolutePath( - path.join('dist', 'linter-server') - ); - - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { command: serverBinary, transport: TransportKind.stdio }, - debug: { - command: serverBinary, - transport: TransportKind.stdio, - } - }; + linterClient = await createLinterClient(context); + foundryCompilerClient = createFoundryCompilerClient(context); + slitherClient = createSlitherClient(context); + testsPositionsClient = await createTestsPositionsClient(context); + if (workspace.workspaceFolders?.length) + testManager = new TestManager(testsPositionsClient, workspace.workspaceFolders[0].uri.fsPath); - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for plain text documents - documentSelector: [{ scheme: 'file', language: 'solidity' }], - synchronize: { - // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: workspace.createFileSystemWatcher('**/.solidhunter.json') - } - }; + context.subscriptions.push(linterClient, foundryCompilerClient, slitherClient, testsPositionsClient, testManager.testController); - // Create the language client and start the client. - client = new LanguageClient( - 'osmium-solidity', - 'Osmium Solidity Language Server', - serverOptions, - clientOptions - ); - - // Start the client. This will also launch the server - client.start(); + registerForgeFmtLinter(context); + const folders = workspace.workspaceFolders; if (folders) { - const folder = folders[0]; - const files = await workspace.findFiles('**/*.sol', `${folder.uri.fsPath}/**`); + const files = await workspace.findFiles('**/*.sol', `${folders[0].uri.fsPath}/**`); files.forEach(file => { - workspace.openTextDocument(file); + if (!file.path.includes('forge-std')) { + workspace.openTextDocument(file); + } }); } } - -export function deactivate(): Thenable | undefined { - if (!client) { - return undefined; - } - return client.stop(); -} diff --git a/toolchains/solidity/extension/src/fmt-wrapper.ts b/toolchains/solidity/extension/src/fmt-wrapper.ts new file mode 100644 index 00000000..08549f6c --- /dev/null +++ b/toolchains/solidity/extension/src/fmt-wrapper.ts @@ -0,0 +1,245 @@ +import { exec } from "child_process"; +import * as vscode from "vscode"; + +type ForgeFmtOptions = { + root?: string; // Root is used to get fmt config from forge.toml +} & ( + | { + check: true; + raw?: boolean; + } + | { + check?: false; + raw: false; + } +); + +type ForgeFmtArgs = { + options: ForgeFmtOptions; + files: string[]; +}; + +type ForgeFmtResult = { + exitCode: number; + output: string; +}; + +function isFmtInstalled(): boolean { + try { + exec("forge fmt --version", (error, _stdout, _stderr) => { + if (error) { + throw error; + } + }); + return true; + } catch (error) { + return false; + } +} + +function forgeFmt( + args: ForgeFmtArgs, + debug?: boolean +): Promise { + const { options, files } = args; + const { root, check, raw } = options; + + const commandArgs = ["fmt"]; + + if (root) { + commandArgs.push("--root", `"${root}"`); + } + + if (check) { + commandArgs.push("--check"); + } + + if (raw) { + commandArgs.push("--raw"); + } + + commandArgs.push( + ...files.map((file) => (file.includes(" ") ? `"${file}"` : file)) + ); + + const command = `forge ${commandArgs.join(" ")}`; + + if (debug) { + console.debug("command =>", command); + } + + return new Promise((resolve, reject) => { + exec(command, (error, stdout, _stderr) => { + if (error && !check) { + reject(error); + } else { + resolve({ + exitCode: 0, + output: stdout, + }); + } + }); + }); +} + +function registerForgeFmtLinter(context: vscode.ExtensionContext) { + const lintSolFile = vscode.commands.registerCommand( + "osmium.lint-sol-file", + function () { + if (!isFmtInstalled()) { + vscode.window.showErrorMessage( + "Forge fmt is not installed. Please install it and try again." + ); + return; + } + + // Get the active text editor + const editor = vscode.window.activeTextEditor; + + if (editor) { + const document = editor.document; + + if ( + document.languageId !== "solidity" && + editor.document.fileName.split(".").pop() !== "sol" + ) { + vscode.window.showErrorMessage( + "Forge fmt is only available for solidity files." + ); + return; + } + + const options: ForgeFmtOptions = { + root: vscode.workspace.workspaceFolders?.[0].uri.fsPath, + check: false, + raw: false, + }; + + const args: ForgeFmtArgs = { + options, + files: [document.fileName], + }; + + forgeFmt(args) + .then((result) => { + if (result.exitCode === 0) { + vscode.window.showInformationMessage( + "Forge fmt ran successfully." + ); + } else { + vscode.window.showErrorMessage( + "Forge fmt failed. Please check the output for details." + ); + + console.log(result.output); + } + }) + .catch((error) => { + vscode.window.showErrorMessage( + "Forge fmt failed. Please check the output for details." + ); + console.error(error); + }); + } else { + vscode.window.showErrorMessage( + "Forge fmt is only available for solidity files." + ); + } + } + ); + + const lintSolWorkspace = vscode.commands.registerCommand( + "osmium.lint-sol-workspace", + function () { + if (!isFmtInstalled()) { + vscode.window.showErrorMessage( + "Forge fmt is not installed. Please install it and try again." + ); + return; + } + + if (!vscode.workspace.workspaceFolders?.[0]) { + vscode.window.showErrorMessage( + "Unable to find workspace root. Please open a folder and try again." + ); + return; + } + + const options: ForgeFmtOptions = { + root: vscode.workspace.workspaceFolders?.[0].uri.fsPath, + check: false, + raw: false, + }; + + const args: ForgeFmtArgs = { + options, + files: [vscode.workspace.workspaceFolders?.[0].uri.fsPath], + }; + + forgeFmt(args) + .then((result) => { + if (result.exitCode === 0) { + vscode.window.showInformationMessage("Forge fmt ran successfully."); + } else { + vscode.window.showErrorMessage( + "Forge fmt failed. Please check the output for details." + ); + + console.log(result.output); + } + }) + .catch((error) => { + vscode.window.showErrorMessage( + "Forge fmt failed. Please check the output for details." + ); + console.error(error); + }); + } + ); + + const formatter = vscode.languages.registerDocumentFormattingEditProvider( + "solidity", + { + provideDocumentFormattingEdits: (document) => { + if (!isFmtInstalled()) { + vscode.window.showErrorMessage( + "Forge fmt is not installed. Please install it and try again." + ); + return; + } + + const options: ForgeFmtOptions = { + root: vscode.workspace.workspaceFolders?.[0].uri.fsPath, + check: false, + raw: false, + }; + + const args: ForgeFmtArgs = { + options, + files: [document.fileName], + }; + + return forgeFmt(args).then((result) => { + if (result.exitCode === 0) { + vscode.window.showInformationMessage("Forge fmt ran successfully."); + } else { + vscode.window.showErrorMessage( + "Forge fmt failed. Please check the output for details." + ); + + console.log(result.output); + } + + return []; + }); + }, + } + ); + + context.subscriptions.push(lintSolFile); + context.subscriptions.push(lintSolWorkspace); + + context.subscriptions.push(formatter); +} + +export default registerForgeFmtLinter; diff --git a/toolchains/solidity/extension/src/foundry-compiler.ts b/toolchains/solidity/extension/src/foundry-compiler.ts new file mode 100644 index 00000000..b43a9c27 --- /dev/null +++ b/toolchains/solidity/extension/src/foundry-compiler.ts @@ -0,0 +1,50 @@ +import * as path from 'path'; +import { workspace, ExtensionContext } from "vscode"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient/node'; +import * as os from 'os'; + +export function createFoundryCompilerClient(context: ExtensionContext): LanguageClient { + // The server is implemented in node + const serverBinary = context.asAbsolutePath( + path.join('dist', + os.platform().startsWith("win") ? 'foundry-compiler-server.exe' : 'foundry-compiler-server') + ); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used[] + const serverOptions: ServerOptions = { + run: { command: serverBinary, transport: TransportKind.stdio }, + debug: { + command: serverBinary, + transport: TransportKind.stdio, + } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: 'file', language: 'solidity' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: workspace.createFileSystemWatcher('**/.solidhunter.json') + } + }; + + // Create the language client and start the client. + const client = new LanguageClient( + 'osmium-solidity-foundry-compiler', + 'Osmium Solidity Foundry Compiler Language Server', + serverOptions, + clientOptions + ); + + // Start the client. This will also launch the server + client.start(); + + return client; +} \ No newline at end of file diff --git a/toolchains/solidity/extension/src/linter.ts b/toolchains/solidity/extension/src/linter.ts new file mode 100644 index 00000000..c8b0aed9 --- /dev/null +++ b/toolchains/solidity/extension/src/linter.ts @@ -0,0 +1,61 @@ +import * as path from 'path'; +import * as os from 'os'; +import { workspace, ExtensionContext, Uri } from "vscode"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient/node'; +import { TextDecoder } from 'util'; + +export async function createLinterClient(context: ExtensionContext): Promise { + // The server is implemented in node + const serverBinary = context.asAbsolutePath( + path.join( + 'dist', + os.platform().startsWith("win") ? 'linter-server.exe' : 'linter-server' + ) + ); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { command: serverBinary, transport: TransportKind.stdio }, + debug: { + command: serverBinary, + transport: TransportKind.stdio, + } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: 'file', language: 'solidity' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: workspace.createFileSystemWatcher('**/.solidhunter.json') + } + }; + + // Create the language client and start the client. + const client = new LanguageClient( + 'osmium-solidity-linter', + 'Osmium Solidity Linter Language Server', + serverOptions, + clientOptions + ); + + client.onRequest('osmium/getContent', async (params: { uri: string}) => { + const contentUint8 = await workspace.fs.readFile(Uri.parse(params.uri)); + const content = new TextDecoder().decode(contentUint8); + return { + content, + }; + }); + + // Start the client. This will also launch the server + await client.start(); + + return client; +} \ No newline at end of file diff --git a/toolchains/solidity/extension/src/slither.ts b/toolchains/solidity/extension/src/slither.ts new file mode 100644 index 00000000..ac1128e8 --- /dev/null +++ b/toolchains/solidity/extension/src/slither.ts @@ -0,0 +1,61 @@ +import * as path from 'path'; +import * as os from 'os'; +import { workspace, ExtensionContext, Uri } from "vscode"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient/node'; +import { TextDecoder } from 'util'; + +export function createSlitherClient(context: ExtensionContext): LanguageClient { + // The server is implemented in node + const serverBinary = context.asAbsolutePath( + path.join( + 'dist', + os.platform().startsWith("win") ? 'slither-server.exe' : 'slither-server' + ) + ); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { command: serverBinary, transport: TransportKind.stdio }, + debug: { + command: serverBinary, + transport: TransportKind.stdio, + } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: 'file', language: 'solidity' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: workspace.createFileSystemWatcher('**/.solidhunter.json') + } + }; + + // Create the language client and start the client. + const client = new LanguageClient( + 'osmium-slither', + 'Osmium Slither Language Server', + serverOptions, + clientOptions + ); + + client.onRequest('osmium/getContent', async (params: { uri: string}) => { + const contentUint8 = await workspace.fs.readFile(Uri.parse(params.uri)); + const content = new TextDecoder().decode(contentUint8); + return { + content, + }; + }); + + // Start the client. This will also launch the server + client.start(); + + return client; +} \ No newline at end of file diff --git a/toolchains/solidity/extension/src/tests-positions.ts b/toolchains/solidity/extension/src/tests-positions.ts new file mode 100644 index 00000000..ca8ae7c8 --- /dev/null +++ b/toolchains/solidity/extension/src/tests-positions.ts @@ -0,0 +1,53 @@ +import * as path from 'path'; +import * as os from 'os'; +import { workspace, ExtensionContext, Uri } from "vscode"; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient/node'; +import { TextDecoder } from 'util'; + +export async function createTestsPositionsClient(context: ExtensionContext): Promise { + // The server is implemented in node + const serverBinary = context.asAbsolutePath( + path.join( + 'dist', + os.platform().startsWith("win") ? 'tests-positions-server.exe' : 'tests-positions-server' + ) + ); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { command: serverBinary, transport: TransportKind.stdio }, + debug: { + command: serverBinary, + transport: TransportKind.stdio, + } + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + //documentSelector: [{ scheme: 'file', language: 'solidity' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + //fileEvents: workspace.createFileSystemWatcher('**/.solidhunter.json') + } + }; + + // Create the language client and start the client. + const client = new LanguageClient( + 'osmium-tests-positions', + 'Osmium Solidity Tests Positions Language Server', + serverOptions, + clientOptions + ); + + // Start the client. This will also launch the server + await client.start(); + + return client; +} \ No newline at end of file diff --git a/toolchains/solidity/extension/src/tests/foundry-test.ts b/toolchains/solidity/extension/src/tests/foundry-test.ts new file mode 100644 index 00000000..65877a7e --- /dev/null +++ b/toolchains/solidity/extension/src/tests/foundry-test.ts @@ -0,0 +1,125 @@ +import {exec} from 'child_process'; +import * as vscode from "vscode"; + +type TestResult = { + status: string, + reason: string | null, + counterexample: any | null, + logs: any[], + // eslint-disable-next-line @typescript-eslint/naming-convention + decoded_logs: string[] + kind: any, + traces: any + coverage: any + // eslint-disable-next-line @typescript-eslint/naming-convention + labeled_addresses: { + [key: string]: string + } + debug: any | null + breakpoints: any +}; + +type SuiteResult = { + duration: { + nanos: number + secs: number + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + test_results: { + [key: string]: TestResult + }, + warnings: string[] +}; + +type FileResult = { + [key: string]: SuiteResult +}; + +const hasForge = async (workspace: string) => { + return new Promise((resolve, reject) => { + exec('forge --version', { + cwd: workspace + }, (err, stdout, stderr) => { + if (err) { + console.log(err); + vscode.window.showErrorMessage('Forge not found. Please install it and try again.'); + resolve(false); + } else { + resolve(true); + } + }); + }); +}; + +const testAll = async (workspace: string): Promise => { + return new Promise(async (resolve, reject) => { + if (!(await hasForge(workspace))) { + reject("No forge found"); + } + + exec('forge test --json', { + cwd: workspace + }, (error, stdout, stderr) => { + if (error) { // An error is returned by node if the forge test command fails, which is the case if a test fails + if (!stderr.length) { + return resolve(JSON.parse(stdout)); + } + console.log(stderr); + vscode.window.showErrorMessage( + "Error while running forge tests." + ); + reject(stderr); + } else { + resolve(JSON.parse(stdout)); + } + }); + }); +}; + +const testContract = (workspace: string, contractName: string): Promise => { + return new Promise(async (resolve, reject) => { + if (!(await hasForge(workspace))) { + reject("No forge found"); + } + + exec(`forge test --json --match-contract '${contractName}'`, { + cwd: workspace + }, (error, stdout, stderr) => { + if (error) { // An error is returned by node if the forge test command fails, which is the case if a test fails + if (!stderr.length) { + return resolve(JSON.parse(stdout)); + } + console.log(stderr); + vscode.window.showErrorMessage('Error while running forge tests.'); + reject(stderr); + } else { + resolve(JSON.parse(stdout)); + } + }); + }); +}; + +const testFunction = (workspace: string, contractName: string, functionName: string): Promise => { + return new Promise(async (resolve, reject) => { + if (!(await hasForge(workspace))) { + reject("No forge found"); + } + exec(`forge test --json --match-contract '${contractName}' --match-test '${functionName}'`, { + cwd: workspace + }, (error, stdout, stderr) => { + if (error) { // An error is returned by node if the forge test command fails, which is the case if a test fails + if (!stderr.length) { + return resolve(JSON.parse(stdout)); + } + console.log(stderr); + vscode.window.showErrorMessage('Error while running forge tests.'); + reject(stderr); + } else { + resolve(JSON.parse(stdout)); + } + }); + }); +}; + + +export {hasForge, testAll, testContract, testFunction, FileResult, SuiteResult, TestResult}; \ No newline at end of file diff --git a/toolchains/solidity/extension/src/tests/test-manager.ts b/toolchains/solidity/extension/src/tests/test-manager.ts new file mode 100644 index 00000000..073cec43 --- /dev/null +++ b/toolchains/solidity/extension/src/tests/test-manager.ts @@ -0,0 +1,340 @@ +import { LanguageClient } from "vscode-languageclient/node"; +import * as vscode from "vscode"; +import { testContract, testFunction, FileResult } from "./foundry-test"; + +enum ItemType { + file, + contractCase, + testCase, +} + +export class TestManager { + public testController: vscode.TestController; + private testData = new WeakMap(); + + constructor(private client: LanguageClient, private workspace: string) { + this.testController = vscode.tests.createTestController( + "solidityTestController", + "Solidity test controller" + ); + + this.testController.resolveHandler = (test) => { + console.log("controller resolve"); + return this.resolve(test); + }; + this.testController.createRunProfile( + "Run tests", + vscode.TestRunProfileKind.Run, + (request, token) => this.runHandler(false, request, token) + ); + // Uncomment this when debugging is supported + //this.testController.createRunProfile("Debug tests", vscode.TestRunProfileKind.Run, (request, token) => this.runHandler(true, request, token)) + + vscode.workspace.onDidOpenTextDocument((e) => { + this.parseTestsInDocument(e); + }); + + console.log("Test manager created"); + } + + /** + * + * @param _shouldDebug Whether the tests should be run in debug mode + * @param request The TestRunRequest containing the tests to run + * @param token A cancellation token + */ + private async runHandler( + _shouldDebug: boolean, + request: vscode.TestRunRequest, + token: vscode.CancellationToken + ) { + console.log("Run handler called"); + const run = this.testController.createTestRun(request); + const queue: vscode.TestItem[] = []; + + // Loop through all included tests, or all known tests, and add them to our queue + if (request.include) { + console.log("request include", request.include); + request.include.forEach((test) => queue.push(test)); + } else { + console.log("testAll"); + this.testController.items.forEach((test) => queue.push(test)); + } + + // For every test that was queued, try to run it. Call run.passed() or run.failed(). + // The `TestMessage` can contain extra information, like a failing location or + // a diff output. But here we'll just give it a textual message. + while (queue.length > 0 && !token.isCancellationRequested) { + const test = queue.pop()!; + + // Skip tests the user asked to exclude + if (request.exclude?.includes(test)) { + continue; + } + + const date = Date.now(); + try { + switch (this.testData.get(test)!) { + case ItemType.file: + // If we're running a file and don't know what it contains yet, parse it now + if (test.children.size === 0) { + await this.parseTestsInFileContents(test); + } + break; + case ItemType.contractCase: + //get result form foundry wrapper for contract test + const contractResult = await testContract( + this.workspace, + test.label + ); + const contractTime = Date.now() - date; + if (this.analyzeTestResults(contractResult)) { + run.appendOutput( + this.extractResultLogs(contractResult).join("\r\n") + ); + run.passed(test, contractTime); + } else { + run.failed( + test, + new vscode.TestMessage( + `Contract test failed\n\n${this.extractResultLogs(contractResult).join( + "\n" + )}` + ), + contractTime + ); + } + break; + case ItemType.testCase: + //get result form foundry wrapper for test case + const functionResult = await testFunction( + this.workspace, + test.parent!.label, + test.label + ); + const functionTime = Date.now() - date; + + if (this.analyzeTestResults(functionResult)) { + run.appendOutput(this.extractResultLogs(functionResult).join("\r\n")); + run.passed(test, functionTime); + } else { + run.failed( + test, + new vscode.TestMessage(`Test failed\n\${this.extractResultLogs(functionResult).join("\n")}`), + functionTime + ); + } + break; + } + } catch (e: any) { + run.appendOutput(JSON.stringify(e)); + run.failed(test, new vscode.TestMessage("Test failed")); + if (e === "No forge found") { + vscode.window.showErrorMessage( + "No forge found. Please install forge and make sure it's in your PATH" + ); + } + } + + // If the test type is a file, we'll queue up all of its children (contracts) to run next. + // Otherwise, we do nothing as the highest level (contracts) already include their children (test cases). + if (this.testData.get(test) === ItemType.file) { + test.children.forEach((test) => queue.push(test)); + } + } + + // Make sure to end the run after all tests have been executed: + run.end(); + } + + private analyzeTestResults(result: FileResult) { + let ret = true; + + for (const suiteResult of Object.values(result)) { + for (const testResult of Object.values(suiteResult.test_results)) { + if (testResult.status !== "Success") { + return false; + } + } + } + return true; + } + + private extractResultLogs(result: FileResult) { + let logs: string[] = []; + + for (const suiteResult of Object.values(result)) { + for (const testResult of Object.values(suiteResult.test_results)) { + logs = logs.concat(testResult.decoded_logs); + } + } + + return logs; + } + + /** + * Sends a request to the language server to get the positions of all tests in a file + * @param content The content of the file to parse + * @returns A structure containing the positions of all tests in the file (see /toolchains/solidity/core/tests-positions-server/src/get-tests-positions.rs) + */ + private async getTestsPositions(content: string): Promise { + console.log("getTestsPositions"); + return this.client.sendRequest("osmium/getTestsPositions", { + file_content: content, // eslint-disable-line @typescript-eslint/naming-convention + }); + } + + /** + * Check if a TestItem for a file already exists in the testController, and if not, create it + * @param uri URI of the file to get or create a TestItem for + * @returns The TestItem for the file + */ + private getOrCreateTestFileItem(uri: vscode.Uri) { + console.log("getOrCreateTestFileItem"); + const existing = this.testController.items.get(uri.toString()); + if (existing) { + return existing; + } + + const file = this.testController.createTestItem( + uri.toString(), + uri.path.split("/").pop()!, + uri + ); + this.testData.set(file, ItemType.file); + file.canResolveChildren = true; + this.testController.items.add(file); + return file; + } + + /** + * Resolve a TestItem. If it's a file, parse it for tests. If it's a contract, parse it for tests and add them as children + * @param test The TestItem to resolve + */ + private async resolve(test?: vscode.TestItem) { + if (!test) { + await this.discoverAllFilesInWorkspace(); + } else { + await this.parseTestsInFileContents(test); + } + } + + /** + * Discover all files in the workspace and add them to the testController + * Also create a FileSystemWatcher for each file to watch for changes + */ + private async discoverAllFilesInWorkspace() { + if (!vscode.workspace.workspaceFolders) { + return []; // handle the case of no open folders + } + + return Promise.all( + vscode.workspace.workspaceFolders.map(async (workspaceFolder) => { + const pattern = new vscode.RelativePattern( + workspaceFolder, + "**/*.t.sol" + ); + const watcher = vscode.workspace.createFileSystemWatcher(pattern); + + // When files are created, make sure there's a corresponding "file" node in the tree + watcher.onDidCreate((uri) => this.getOrCreateTestFileItem(uri)); + // When files change, re-parse them. Note that you could optimize this so + // that you only re-parse children that have been resolved in the past. + watcher.onDidChange((uri) => + this.parseTestsInFileContents(this.getOrCreateTestFileItem(uri)) + ); + // And, finally, delete TestItems for removed files. This is simple, since + // we use the URI as the TestItem's ID. + watcher.onDidDelete((uri) => + this.testController.items.delete(uri.toString()) + ); + + for (const file of await vscode.workspace.findFiles(pattern)) { + this.getOrCreateTestFileItem(file); + } + + return watcher; + }) + ); + } + + /** + * Check if the document is a test file and parse it if it is + * @param e TextDocument that was opened + */ + private parseTestsInDocument(e: vscode.TextDocument) { + if (e.uri.scheme === "file" && e.uri.path.endsWith(".t.sol")) { + this.parseTestsInFileContents( + this.getOrCreateTestFileItem(e.uri), + e.getText() + ); + } + } + + /** + * Read the contents of a file and parse it for tests by calling the tests-positions language server method. It will then fill the children of the TestItem with the tests found. + * @param file A TestItem representing the file to parse + * @param contents The contents of the file. If not provided, the file will be read from disk + */ + private async parseTestsInFileContents( + file: vscode.TestItem, + contents?: string + ) { + // If a document is open, VS Code already knows its contents. If this is being + // called from the resolveHandler when a document isn't open, we'll need to + // read them from disk ourselves. + if (contents === undefined) { + const rawContent = await vscode.workspace.fs.readFile(file.uri!); + contents = new TextDecoder().decode(rawContent); + } + + if (contents !== undefined) { + // CALL getTestPositions and fill children + await this.getTestsPositions(contents) + .then((testPositions) => { + testPositions.contracts.forEach((contract: any) => { + const contractName = contract.name.replace(" ", ""); + const contractItem = this.testController.createTestItem( + contractName, + contract.name, + file.uri + ); + contractItem.range = convertRange(contract.range); + console.log("Contract range", JSON.stringify(contractItem.range)); + this.testData.set(contractItem, ItemType.contractCase); + file.children.add(contractItem); + + contract.tests.forEach((test: any) => { + const functionItem = this.testController.createTestItem( + `${contractName}_${test.name}`, + test.name, + file.uri + ); + functionItem.range = convertRange(test.range); + console.log("Test range", JSON.stringify(functionItem.range)); + this.testData.set(functionItem, ItemType.testCase); + contractItem.children.add(functionItem); + }); + }); + }) + .catch((error) => { + console.log("Error getting tests positions", error); + vscode.window.showErrorMessage("Error while getting tests positions"); + }); + } + } +} + +/** + * Convert a LSP range to a VSCode range (offsets are 0-based in VScode and 1-based in LSP) + * @param lspRange LSP range + * @returns A VSCode range with the same start and end positions + */ +function convertRange(lspRange: any): vscode.Range { + const range = new vscode.Range( + new vscode.Position(lspRange.start.line - 1, lspRange.start.character), + new vscode.Position(lspRange.end.line - 1, lspRange.end.character) + ); + console.log(range); + return range; +} diff --git a/toolchains/solidity/extension/webpack.config.js b/toolchains/solidity/extension/webpack.config.js index ac2e9abb..0bb3bb71 100644 --- a/toolchains/solidity/extension/webpack.config.js +++ b/toolchains/solidity/extension/webpack.config.js @@ -1,7 +1,6 @@ //@ts-check 'use strict'; - const path = require('path'); //@ts-check @@ -22,7 +21,7 @@ const extensionConfig = { libraryTarget: 'commonjs2' }, externals: { - vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ + vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ // modules added here also need to be added in the .vscodeignore file }, resolve: { diff --git a/toolchains/solidity/package.json b/toolchains/solidity/package.json index f7edb201..9719dc7d 100644 --- a/toolchains/solidity/package.json +++ b/toolchains/solidity/package.json @@ -12,5 +12,8 @@ "test": "cd core && yarn core:test && cd ../extension && yarn extension:test", "format": "cd core && yarn core:format && cd ../extension && yarn extension:format", "publish": "cd core && yarn core:publish && cd ../extension && yarn extension:publish && cd .." + }, + "dependencies": { + "@types/node": "^20.10.1" } } diff --git a/yarn.lock b/yarn.lock index 6d844cbb..8ec74293 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,15 +31,15 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": - version: 4.9.1 - resolution: "@eslint-community/regexpp@npm:4.9.1" - checksum: 8f1ba51fa5dedd93f01623382d006c838a436aaea85561c7e540b15600988350843bf746a60e2aaefa79ee4904c9dc0a2f3f00e025b162112c76520ffb34805d + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 8c36169c815fc5d726078e8c71a5b592957ee60d08c6470f9ce0187c8046af1a00afbda0a065cc40ff18d5d83f82aed9793c6818f7304a74a7488dc9f3ecbd42 languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.2": - version: 2.1.2 - resolution: "@eslint/eslintrc@npm:2.1.2" +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -50,14 +50,14 @@ __metadata: js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: fa25638f2666cac6810f98ee7d0f4b912f191806467c1b40d72bac759fffef0b3357f12a1869817286837b258e4de3517e0c7408520e156ca860fc53a1fbaed9 + checksum: 7a3b14f4b40fc1a22624c3f84d9f467a3d9ea1ca6e9a372116cb92507e485260359465b58e25bcb6c9981b155416b98c9973ad9b796053fd7b3f776a6946bce8 languageName: node linkType: hard -"@eslint/js@npm:8.52.0": - version: 8.52.0 - resolution: "@eslint/js@npm:8.52.0" - checksum: 86beff213d0ae4ced203a922b74e2cc4d767d109e7815f985bf648946ba072198977102e32afc9fa04f7825a6de83a831874f6b6675ba0c1d0743ade2dc2d53d +"@eslint/js@npm:8.55.0": + version: 8.55.0 + resolution: "@eslint/js@npm:8.55.0" + checksum: 34b001a95b16501fd64f525b1de3ab0e4c252e5820b74069004934cb13977fc04ba4522a3e8f8074bd6af49da10d3444cd49fa711819f425ad73d6bf46eea82d languageName: node linkType: hard @@ -179,6 +179,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.1" + checksum: 822ea077553cd9cfc5cbd6d92380b0950fcb054a7027cd1b63a33bd0cbb16b0c6626ea75d95ec0e804643c8904472d3361d2da8c2444b1fb02a9b525d9c07c41 + languageName: node + linkType: hard + "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -194,6 +207,12 @@ __metadata: languageName: unknown linkType: soft +"@osmium-libs/foundry-wrapper@workspace:libs/foundry-wrapper": + version: 0.0.0-use.local + resolution: "@osmium-libs/foundry-wrapper@workspace:libs/foundry-wrapper" + languageName: unknown + linkType: soft + "@osmium-libs/lsp-handler@workspace:libs/lsp-handler": version: 0.0.0-use.local resolution: "@osmium-libs/lsp-handler@workspace:libs/lsp-handler" @@ -242,37 +261,30 @@ __metadata: languageName: node linkType: hard -"@tootallnate/once@npm:2": - version: 2.0.0 - resolution: "@tootallnate/once@npm:2.0.0" - checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 - languageName: node - linkType: hard - "@types/eslint-scope@npm:^3.7.3": - version: 3.7.6 - resolution: "@types/eslint-scope@npm:3.7.6" + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" dependencies: "@types/eslint": "npm:*" "@types/estree": "npm:*" - checksum: a2339e312949ae7f96bca52cde89a3d2218d4505746a78a0ba1aa56573e43b3d52ce9662b86ab785663a62fa8f2bd2fb61b990398785b40f2efc91be3fd246f8 + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e languageName: node linkType: hard "@types/eslint@npm:*": - version: 8.44.6 - resolution: "@types/eslint@npm:8.44.6" + version: 8.44.8 + resolution: "@types/eslint@npm:8.44.8" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 07ee27c1803fce2d732800d4972462e4c08f2ac84c70a6addb0ae2566de392eb92e39ccc8f6ab487348f751b4b253c4724d3490ea8856abcd8917acae676a2d6 + checksum: d6e0788eb7bff90e5f5435b0babe057e76a7d3eed1e36080bacd7b749098eddae499ddb3c0ce6438addce98cc6020d9653b5012dec54e47ca96faa7b8e25d068 languageName: node linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.0": - version: 1.0.3 - resolution: "@types/estree@npm:1.0.3" - checksum: c51984ec3003a93b619f25995ceba74428f390747d246833928d0121bb2df3b8bca67deb27fc634da47c5b341837d2ae17d0c5b8d16be5110477a73531ac3528 + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 languageName: node linkType: hard @@ -287,9 +299,9 @@ __metadata: linkType: hard "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": - version: 7.0.14 - resolution: "@types/json-schema@npm:7.0.14" - checksum: 84b5efed51984c077f9cb7c5a3dcb8d8288ce1ae8825952b173c3506a0cfc90bc961d7f2a8847c440310d02bbd570cf918ac463d8310b0c9dce2252baa1ba4e0 + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 languageName: node linkType: hard @@ -301,18 +313,18 @@ __metadata: linkType: hard "@types/mocha@npm:^10.0.1": - version: 10.0.3 - resolution: "@types/mocha@npm:10.0.3" - checksum: 31d44b6a45e20dba3f349a62b0f6fc23b054155e7b7e558e1be76b1bc5e91a6902062fdd7b9167beeed7b0083d351bd2b94352a677bf1a03b4d42c767497213f + version: 10.0.6 + resolution: "@types/mocha@npm:10.0.6" + checksum: fc73626e81e89c32d06b7ff9b72c4177b46d579cdd932f796614adc026852d84cb849d743473ba572cb4d9ea6d8c04e3749552d326c26495ec1c4b46e6e0a0c0 languageName: node linkType: hard "@types/node@npm:*": - version: 20.8.7 - resolution: "@types/node@npm:20.8.7" + version: 20.9.3 + resolution: "@types/node@npm:20.9.3" dependencies: - undici-types: "npm:~5.25.1" - checksum: a347ac7e6a9748ffff018ca01142ba625e774cb0b53785abb58b16a5a8468cc9b7656686dbe4c39c2f3fc477439994ee8aeae9b80ced86f320598bafaf83f802 + undici-types: "npm:~5.26.4" + checksum: 5d2a3a6b2b900814eab8c5093dabb7aa10895928719ec0074b9ac5584bcc83f5b680e2d2cb6c8b9751511b7b1b7fdd8586d2fc827b156f0263fdb65c4741bdef languageName: node linkType: hard @@ -323,17 +335,26 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.10.1": + version: 20.10.1 + resolution: "@types/node@npm:20.10.1" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 703c3cc5bdb2818a16f87019fe4072bfd66489bb300338970260c5b84dd2129595995c41b28773c3b7d9d1a64f36fec59a741629ec466f2aeddad7a9d0c027ac + languageName: node + linkType: hard + "@types/semver@npm:^7.3.12": - version: 7.5.4 - resolution: "@types/semver@npm:7.5.4" - checksum: e99c3edc8d64f56abcd891b9e44a45c4ae3cab551c8af5aa67b5df2b49e5fd03f74aac9da71fd5357a50a08d5deb95014516956b15b407052e07f25c7a4a606e + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: e77282b17f74354e17e771c0035cccb54b94cc53d0433fa7e9ba9d23fd5d7edcd14b6c8b7327d58bbd89e83b1c5eda71dfe408e06b929007e2b89586e9b63459 languageName: node linkType: hard "@types/vscode@npm:^1.75.0": - version: 1.83.1 - resolution: "@types/vscode@npm:1.83.1" - checksum: 4acffc65861ec672b32d513f9859507a60db80f093b2edaa1f197c587f2456242e8865cc8a497ccdcad083522866b5a3d43b0d2aa854d63d7be955a0032c9623 + version: 1.84.2 + resolution: "@types/vscode@npm:1.84.2" + checksum: 45687e6e26e1d25d995093099672fdb6c0592480279c1446432a6ee5d412518f1d794cf2df1c548e7fc884a9df8b2de2c663e9d7f92096e57c85b9923dac99f8 languageName: node linkType: hard @@ -466,14 +487,14 @@ __metadata: linkType: hard "@vscode/test-electron@npm:^2.3.2": - version: 2.3.5 - resolution: "@vscode/test-electron@npm:2.3.5" + version: 2.3.8 + resolution: "@vscode/test-electron@npm:2.3.8" dependencies: http-proxy-agent: "npm:^4.0.1" https-proxy-agent: "npm:^5.0.0" jszip: "npm:^3.10.1" semver: "npm:^7.5.2" - checksum: b0de89154fc513616c27954805ca309c3d853bc8e42c96e06bc83e9794316a482f6172b588f1fdf21d39e5fe8c407a3666fa39d2ad4ab1d7bb201d3c2afb487b + checksum: 044ce44866cd6ee8444f1b07478e942004e60559265124cb6a8e8d2815b8b31fa4ed7eb0ef8ad500dae5ca805f92d62fa779dd6e7208a1ace93ec1b328f5d8c6 languageName: node linkType: hard @@ -709,10 +730,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^1.0.0": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: 2d882941183c66aa665118bafdab82b7a177e9add5eb2776c33e960a4f3c89cff88a1b38aba13a456de01d0dd9d66a8bea7c903268b21ea91dd1097e1e2e8243 +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: ca0a54e35bea4ece0ecb68a47b312e1a9a6f772408d5bcb9051230aaa94b0460671c5b5c9cb3240eb5b7bc94c52476550eb221f65a0bbd0145bdc9f3113a6707 languageName: node linkType: hard @@ -735,15 +756,15 @@ __metadata: linkType: hard "acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" + version: 8.11.2 + resolution: "acorn@npm:8.11.2" bin: acorn: bin/acorn - checksum: 522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd + checksum: ff559b891382ad4cd34cc3c493511d0a7075a51f5f9f02a03440e92be3705679367238338566c5fbd3521ecadd565d29301bc8e16cb48379206bffbff3d72500 languageName: node linkType: hard -"agent-base@npm:6, agent-base@npm:^6.0.2": +"agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" dependencies: @@ -752,12 +773,12 @@ __metadata: languageName: node linkType: hard -"agentkeepalive@npm:^4.2.1": - version: 4.5.0 - resolution: "agentkeepalive@npm:4.5.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" dependencies: - humanize-ms: "npm:^1.2.1" - checksum: dd210ba2a2e2482028f027b1156789744aadbfd773a6c9dd8e4e8001930d5af82382abe19a69240307b1d8003222ce6b0542935038313434b900e351914fc15f + debug: "npm:^4.3.4" + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f languageName: node linkType: hard @@ -848,23 +869,6 @@ __metadata: languageName: node linkType: hard -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: c2b9a631298e8d6f3797547e866db642f68493808f5b37cd61da778d5f6ada890d16f668285f7d60bd4fc3b03889bd590ffe62cf81b700e9bb353431238a0a7b - languageName: node - linkType: hard - -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: "npm:^1.0.0" - readable-stream: "npm:^3.6.0" - checksum: 390731720e1bf9ed5d0efc635ea7df8cbc4c90308b0645a932f06e8495a0bf1ecc7987d3b97e805f62a17d6c4b634074b25200aa4d149be2a7b17250b9744bc4 - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -964,16 +968,16 @@ __metadata: linkType: hard "browserslist@npm:^4.14.5": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" dependencies: - caniuse-lite: "npm:^1.0.30001541" - electron-to-chromium: "npm:^1.4.535" - node-releases: "npm:^2.0.13" + caniuse-lite: "npm:^1.0.30001565" + electron-to-chromium: "npm:^1.4.601" + node-releases: "npm:^2.0.14" update-browserslist-db: "npm:^1.0.13" bin: browserslist: cli.js - checksum: 4a515168e0589c7b1ccbf13a93116ce0418cc5e65d228ec036022cf0e08773fdfb732e2abbf1e1188b96d19ecd4dd707504e75b6d393cba2782fc7d6a7fdefe8 + checksum: e3590793db7f66ad3a50817e7b7f195ce61e029bd7187200244db664bfbe0ac832f784e4f6b9c958aef8ea4abe001ae7880b7522682df521f4bc0a5b67660b5e languageName: node linkType: hard @@ -1001,23 +1005,23 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^17.0.0": - version: 17.1.4 - resolution: "cacache@npm:17.1.4" +"cacache@npm:^18.0.0": + version: 18.0.1 + resolution: "cacache@npm:18.0.1" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" glob: "npm:^10.2.2" - lru-cache: "npm:^7.7.1" + lru-cache: "npm:^10.0.1" minipass: "npm:^7.0.3" - minipass-collect: "npm:^1.0.2" + minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" p-map: "npm:^4.0.0" ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 6e26c788bc6a18ff42f4d4f97db30d5c60a5dfac8e7c10a03b0307a92cf1b647570547cf3cd96463976c051eb9c7258629863f156e224c82018862c1a8ad0e70 + checksum: aecafd368fbfb2fc0cda1f2f831fe5a1d8161d2121317c92ac089bcd985085e8a588e810b4471e69946f91c6d2661849400e963231563c519aa1e3dac2cf6187 languageName: node linkType: hard @@ -1046,10 +1050,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001553 - resolution: "caniuse-lite@npm:1.0.30001553" - checksum: b14b512307aeaeccd4798439ae8665c9c215778132d4a87194552edbbd11965c1a8b3bee593e43a511332e5c4282962e12006ffb75bd3d938c080af7cfc89096 +"caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001565 + resolution: "caniuse-lite@npm:1.0.30001565" + checksum: abc58bf3504508c4cb62f0e4a3267a222140935cb63ff252f1e960bf8680cc17368da1d29fb1f68343dfa8b046de7b9e7c2003b822732adc4c68e8ab6ae82c0e languageName: node linkType: hard @@ -1204,15 +1208,6 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 4bcfe30eea1498fe1cabc852bbda6c9770f230ea0e4faf4611c5858b1b9e4dde3730ac485e65f54ca182f4c50b626c1bea7c8441ceda47367a54a818c248aa7a - languageName: node - linkType: hard - "colorette@npm:^2.0.14": version: 2.0.20 resolution: "colorette@npm:2.0.20" @@ -1248,13 +1243,6 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 27b5fa302bc8e9ae9e98c03c66d76ca289ad0c61ce2fe20ab288d288bee875d217512d2edb2363fc83165e88f1c405180cf3f5413a46e51b4fe1a004840c6cdb - languageName: node - linkType: hard - "core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" @@ -1293,7 +1281,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -1346,13 +1334,6 @@ __metadata: languageName: node linkType: hard -"delegates@npm:^1.0.0": - version: 1.0.0 - resolution: "delegates@npm:1.0.0" - checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd - languageName: node - linkType: hard - "detect-libc@npm:^2.0.0": version: 2.0.2 resolution: "detect-libc@npm:2.0.2" @@ -1376,6 +1357,14 @@ __metadata: languageName: node linkType: hard +"doc@workspace:doc": + version: 0.0.0-use.local + resolution: "doc@workspace:doc" + dependencies: + retypeapp: "npm:^3.5.0" + languageName: unknown + linkType: soft + "doctrine@npm:^3.0.0": version: 3.0.0 resolution: "doctrine@npm:3.0.0" @@ -1430,10 +1419,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.535": - version: 1.4.565 - resolution: "electron-to-chromium@npm:1.4.565" - checksum: caee9af984e0387ab8bb852c544b0f606c3f20ce26636fb863d121b98be00ad70d86e9f5d8281bc895e0bce8d8243784d276ca1c22041b010ae3df0c9bddf6a7 +"electron-to-chromium@npm:^1.4.601": + version: 1.4.601 + resolution: "electron-to-chromium@npm:1.4.601" + checksum: 6a7e510156a1ecfb58a9569592d1ccc8d6089f2e764b5267d9e627e4a81ef4e15f4cdcce8cee4c0355af8df50069ca980c76913aa9a2026bfdffd7c31ef82ad7 languageName: node linkType: hard @@ -1501,11 +1490,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3": - version: 7.10.0 - resolution: "envinfo@npm:7.10.0" + version: 7.11.0 + resolution: "envinfo@npm:7.11.0" bin: envinfo: dist/cli.js - checksum: d4db29c5a405081759c57c0e74ffa6adab09b7477ca105587252643394f13ab128ad4c8f755b15334b5f1901cef091acc76c71b695ce0f27853ebf147c882075 + checksum: 8cba09db181329b243fe02b3384ec275ebf93d5d3663c31e2064697aa96576c7de9b7e1c878a250f8eaec0db8026bace747709dcdc8d8a4ecd9a653cdbc08926 languageName: node linkType: hard @@ -1517,9 +1506,9 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.3.1 - resolution: "es-module-lexer@npm:1.3.1" - checksum: c6aa137c5f5865fe1d12b4edbe027ff618d3836684cda9e52ae4dec48bfc2599b25db4f1265a12228d4663e21fd0126addfb79f761d513f1a6708c37989137e3 + version: 1.4.1 + resolution: "es-module-lexer@npm:1.4.1" + checksum: cf453613468c417af6e189b03d9521804033fdd5a229a36fedec28d37ea929fccf6822d42abff1126eb01ba1d2aa2845a48d5d1772c0724f8204464d9d3855f6 languageName: node linkType: hard @@ -1572,13 +1561,13 @@ __metadata: linkType: hard "eslint@npm:^8.41.0, eslint@npm:^8.46.0": - version: 8.52.0 - resolution: "eslint@npm:8.52.0" + version: 8.55.0 + resolution: "eslint@npm:8.55.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.2" - "@eslint/js": "npm:8.52.0" + "@eslint/eslintrc": "npm:^2.1.4" + "@eslint/js": "npm:8.55.0" "@humanwhocodes/config-array": "npm:^0.11.13" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" @@ -1615,7 +1604,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 01784ab15351d749bc95446039ed7acd5124f7cc84acdbf98c7199272eae06212a8f3ea4a9b47e7cc54ab17ca094c3a664bbfc3002c7de27936220e278b5028a + checksum: afd016cfbe9e9d667b3f98c14c681a7e518808f6c30856e56cbb02248900eac5bf6dc5e577a7eaec259539486db48ef7d16ef58fb14b1585ba7c84b35490c53c languageName: node linkType: hard @@ -1698,15 +1687,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.2.9": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" micromatch: "npm:^4.0.4" - checksum: 51bcd15472879dfe51d4b01c5b70bbc7652724d39cdd082ba11276dbd7d84db0f6b33757e1938af8b2768a4bf485d9be0c89153beae24ee8331d6dcc7550379f + checksum: 222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -1788,13 +1777,13 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.1.1 - resolution: "flat-cache@npm:3.1.1" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: flatted: "npm:^3.2.9" keyv: "npm:^4.5.3" rimraf: "npm:^3.0.2" - checksum: 04b57c7cb4bd54f1e80a335f037bff467cc7b2479ecc015ff7e78fd41aa12777757d55836e99c7e5faca2271eb204a96bf109b4d98c36c20c3b98cf1372b5592 + checksum: 02381c6ece5e9fa5b826c9bbea481d7fd77645d96e4b0b1395238124d581d10e56f17f723d897b6d133970f7a57f0fab9148cbbb67237a0a0ffe794ba60c0c70 languageName: node linkType: hard @@ -1882,22 +1871,6 @@ __metadata: languageName: node linkType: hard -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: "npm:^1.0.3 || ^2.0.0" - color-support: "npm:^1.1.3" - console-control-strings: "npm:^1.1.0" - has-unicode: "npm:^2.0.1" - signal-exit: "npm:^3.0.7" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - wide-align: "npm:^1.1.5" - checksum: 09535dd53b5ced6a34482b1fa9f3929efdeac02f9858569cde73cef3ed95050e0f3d095706c1689614059898924b7a74aa14042f51381a1ccc4ee5c29d2389c4 - languageName: node - linkType: hard - "get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -1963,7 +1936,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2": +"glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -1978,7 +1951,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.6, glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:^7.0.6, glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -2088,13 +2061,6 @@ __metadata: languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 041b4293ad6bf391e21c5d85ed03f412506d6623786b801c4ab39e4e6ca54993f13201bceb544d92963f9e0024e6e7fbf0cb1d84c9d6b31cb9c79c8c990d13d8 - languageName: node - linkType: hard - "hasown@npm:^2.0.0": version: 2.0.0 resolution: "hasown@npm:2.0.0" @@ -2152,14 +2118,13 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^5.0.0": - version: 5.0.0 - resolution: "http-proxy-agent@npm:5.0.0" +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" dependencies: - "@tootallnate/once": "npm:2" - agent-base: "npm:6" - debug: "npm:4" - checksum: 5ee19423bc3e0fd5f23ce991b0755699ad2a46a440ce9cec99e8126bb98448ad3479d2c0ea54be5519db5b19a4ffaa69616bac01540db18506dd4dac3dc418f0 + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: dbaaf3d9f3fc4df4a5d7ec45d456ec50f575240b557160fa63427b447d1f812dd7fe4a4f17d2e1ba003d231f07edf5a856ea6d91cb32d533062ff20a7803ccac languageName: node linkType: hard @@ -2173,12 +2138,13 @@ __metadata: languageName: node linkType: hard -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" +"https-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" dependencies: - ms: "npm:^2.0.0" - checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 9ec844f78fd643608239c9c3f6819918631df5cd3e17d104cc507226a39b5d4adda9d790fc9fd63ac0d2bb8a761b2f9f60faa80584a9bf9d7f2e8c5ed0acd330 languageName: node linkType: hard @@ -2208,9 +2174,9 @@ __metadata: linkType: hard "ignore@npm:^5.2.0": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 4f7caf5d2005da21a382d4bd1d2aa741a3bed51de185c8562dd7f899a81a620ac4fd0619b06f7029a38ae79e4e4c134399db3bd0192c703c3ef54bb82df3086c + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 51594355cea4c6ad6b28b3b85eb81afa7b988a1871feefd7062baf136c95aa06760ee934fa9590e43d967bd377ce84a4cf6135fbeb6063e063f1182a0e9a3bcd languageName: node linkType: hard @@ -2394,6 +2360,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^3.0.1": version: 3.0.1 resolution: "isobject@npm:3.0.1" @@ -2587,6 +2560,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 207278d6fa711fb1f94a0835d4d4737441d2475302482a14785b10515e4c906a57ebf9f35bf060740c9560e91c7c1ad5a04fd7ed030972a9ba18bce2a228e95b + languageName: node + linkType: hard + "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -2596,40 +2576,22 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.7.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: 6029ca5aba3aacb554e919d7ef804fffd4adfc4c83db00fac8248c7c78811fb6d4b6f70f7fd9d55032b3823446546a007edaa66ad1f2377ae833bd983fac5d98 - languageName: node - linkType: hard - -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.1 - resolution: "lru-cache@npm:10.0.1" - checksum: 5bb91a97a342a41fd049c3494b44d9e21a7d4843f9284d0a0b26f00bb0e436f1f627d0641c78f88be16b86b4231546c5ee4f284733fb530c7960f0bcd7579026 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^11.0.3": - version: 11.1.1 - resolution: "make-fetch-happen@npm:11.1.1" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" dependencies: - agentkeepalive: "npm:^4.2.1" - cacache: "npm:^17.0.0" + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" http-cache-semantics: "npm:^4.1.1" - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.0" is-lambda: "npm:^1.0.1" - lru-cache: "npm:^7.7.1" - minipass: "npm:^5.0.0" + minipass: "npm:^7.0.2" minipass-fetch: "npm:^3.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" negotiator: "npm:^0.6.3" promise-retry: "npm:^2.0.1" - socks-proxy-agent: "npm:^7.0.0" ssri: "npm:^10.0.0" - checksum: b4b442cfaaec81db159f752a5f2e3ee3d7aa682782868fa399200824ec6298502e01bdc456e443dc219bcd5546c8e4471644d54109c8599841dc961d17a805fa + checksum: ded5a91a02b76381b06a4ec4d5c1d23ebbde15d402b3c3e4533b371dac7e2f7ca071ae71ae6dae72aa261182557b7b1b3fd3a705b39252dc17f74fa509d3e76f languageName: node linkType: hard @@ -2754,12 +2716,12 @@ __metadata: languageName: node linkType: hard -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" dependencies: - minipass: "npm:^3.0.0" - checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 + minipass: "npm:^7.0.3" + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 languageName: node linkType: hard @@ -2821,7 +2783,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.3": +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": version: 7.0.4 resolution: "minipass@npm:7.0.4" checksum: e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18 @@ -2893,7 +2855,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0": +"ms@npm:2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -2970,41 +2932,40 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 9.4.0 - resolution: "node-gyp@npm:9.4.0" + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" - glob: "npm:^7.1.4" + glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^11.0.3" - nopt: "npm:^6.0.0" - npmlog: "npm:^6.0.0" - rimraf: "npm:^3.0.2" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^3.0.0" semver: "npm:^7.3.5" tar: "npm:^6.1.2" - which: "npm:^2.0.2" + which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 458317127c63877365f227b18ef2362b013b7f8440b35ae722935e61b31e6b84ec0e3625ab07f90679e2f41a1d5a7df6c4049fdf8e7b3c81fcf22775147b47ac + checksum: 578cf0c821f258ce4b6ebce4461eca4c991a4df2dee163c0624f2fe09c7d6d37240be4942285a0048d307230248ee0b18382d6623b9a0136ce9533486deddfa8 languageName: node linkType: hard -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: c9bb813aab2717ff8b3015ecd4c7c5670a5546e9577699a7c84e8d69230cd3b1ce8f863f8e9b50f18b19a5ffa4b9c1a706bbbfe4c378de955fedbab04488a338 +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 0f7607ec7db5ef1dc616899a5f24ae90c869b6a54c2d4f36ff6d84a282ab9343c7ff3ca3670fe4669171bb1e8a9b3e286e1ef1c131f09a83d70554f855d54f24 languageName: node linkType: hard -"nopt@npm:^6.0.0": - version: 6.0.0 - resolution: "nopt@npm:6.0.0" +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" dependencies: - abbrev: "npm:^1.0.0" + abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 3c1128e07cd0241ae66d6e6a472170baa9f3e84dd4203950ba8df5bafac4efa2166ce917a57ef02b01ba7c40d18b2cc64b29b225fd3640791fe07b24f0b33a32 + checksum: 1e7489f17cbda452c8acaf596a8defb4ae477d2a9953b76eb96f4ec3f62c6b421cd5174eaa742f88279871fde9586d8a1d38fb3f53fa0c405585453be31dff4c languageName: node linkType: hard @@ -3015,18 +2976,6 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: "npm:^3.0.0" - console-control-strings: "npm:^1.1.0" - gauge: "npm:^4.0.3" - set-blocking: "npm:^2.0.0" - checksum: 82b123677e62deb9e7472e27b92386c09e6e254ee6c8bcd720b3011013e4168bc7088e984f4fbd53cb6e12f8b4690e23e4fa6132689313e0d0dc4feea45489bb - languageName: node - linkType: hard - "nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" @@ -3106,6 +3055,8 @@ __metadata: "osmium-solidity@workspace:toolchains/solidity": version: 0.0.0-use.local resolution: "osmium-solidity@workspace:toolchains/solidity" + dependencies: + "@types/node": "npm:^20.10.1" languageName: unknown linkType: soft @@ -3318,11 +3269,18 @@ __metadata: linkType: hard "prettier@npm:^3.0.0": - version: 3.0.3 - resolution: "prettier@npm:3.0.3" + version: 3.1.0 + resolution: "prettier@npm:3.1.0" bin: prettier: bin/prettier.cjs - checksum: ccf1ead9794b017be6b42d0873f459070beef2069eb393c8b4c0d11aa3430acefc54f6d5f44a5b7ce9af05ad8daf694b912f0aa2808d1c22dfa86e61e9d563f8 + checksum: e95e8f93c6b9aea2ac1e86bebe329bee90c8c50d9a23d1f593eba8d7f39b33b3641eb28785001505b6723c47895a5322ad12a2fb855b289cb7bae450ffc34425 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 languageName: node linkType: hard @@ -3354,9 +3312,9 @@ __metadata: linkType: hard "punycode@npm:^2.1.0": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: d4e7fbb96f570c57d64b09a35a1182c879ac32833de7c6926a2c10619632c1377865af3dab5479f59d51da18bcd5035a20a5ef6ceb74020082a3e78025d9a9ca + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 languageName: node linkType: hard @@ -3408,7 +3366,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": +"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -3515,6 +3473,15 @@ __metadata: languageName: node linkType: hard +"retypeapp@npm:^3.5.0": + version: 3.5.0 + resolution: "retypeapp@npm:3.5.0" + bin: + retype: retype.js + checksum: 1af2e98319ed55439aa4b49ebd59ad145124f71085a07c8a754235d60579e2226f642930ec06ca559abe779f94cdeed3d4fd1bd50674ba07fed8c80b4bf4a041 + languageName: node + linkType: hard + "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -3619,13 +3586,6 @@ __metadata: languageName: node linkType: hard -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 8980ebf7ae9eb945bb036b6e283c547ee783a1ad557a82babf758a065e2fb6ea337fd82cac30dd565c1e606e423f30024a19fff7afbf4977d784720c4026a8ef - languageName: node - linkType: hard - "set-function-length@npm:^1.1.1": version: 1.1.1 resolution: "set-function-length@npm:1.1.1" @@ -3681,13 +3641,6 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.7": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - "signal-exit@npm:^4.0.1": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" @@ -3727,18 +3680,18 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "socks-proxy-agent@npm:7.0.0" +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" dependencies: - agent-base: "npm:^6.0.2" - debug: "npm:^4.3.3" - socks: "npm:^2.6.2" - checksum: 26c75d9c62a9ed3fd494df60e65e88da442f78e0d4bc19bfd85ac37bd2c67470d6d4bba5202e804561cda6674db52864c9e2a2266775f879bc8d89c1445a5f4c + agent-base: "npm:^7.0.2" + debug: "npm:^4.3.4" + socks: "npm:^2.7.1" + checksum: ea727734bd5b2567597aa0eda14149b3b9674bb44df5937bbb9815280c1586994de734d965e61f1dd45661183d7b41f115fb9e432d631287c9063864cfcc2ecc languageName: node linkType: hard -"socks@npm:^2.6.2": +"socks@npm:^2.7.1": version: 2.7.1 resolution: "socks@npm:2.7.1" dependencies: @@ -3781,7 +3734,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -3956,8 +3909,8 @@ __metadata: linkType: hard "terser@npm:^5.16.8": - version: 5.22.0 - resolution: "terser@npm:5.22.0" + version: 5.24.0 + resolution: "terser@npm:5.24.0" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -3965,7 +3918,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: e5407f9a143e7f9306f1b585b16dbb03df19b93318b55a26b542e12b74cc792dcf6961d9a2cab6778b20d7b591f498c200376d282a300cf9999ca40bccbc047c + checksum: bd7ba6bfef58f8c179592894923c8c933d980e17287d3f2a9927550be853d1601beebb724cf015929599b32945641c44f9c3db8dd242c7933af3830bcb853510 languageName: node linkType: hard @@ -3995,8 +3948,8 @@ __metadata: linkType: hard "ts-loader@npm:^9.4.3": - version: 9.5.0 - resolution: "ts-loader@npm:9.5.0" + version: 9.5.1 + resolution: "ts-loader@npm:9.5.1" dependencies: chalk: "npm:^4.1.0" enhanced-resolve: "npm:^5.0.0" @@ -4006,7 +3959,7 @@ __metadata: peerDependencies: typescript: "*" webpack: ^5.0.0 - checksum: 8ffc6411ec366eb11bb1420ce444bf60a38072461f75e30731fd3af21dafea0e00fbb3a3588d9cb7a3191237d7ff80a8e3cf5675a36c30d61620fd6f5625b93a + checksum: a85d43bb6f72858d613290ac02d1d24e81c38ba2dcb98b90465dc97eb6c2036bf9a389542c1a7865548643e7ed39f063fdff2dbb3e5aafbc511de6a3eb275adf languageName: node linkType: hard @@ -4072,22 +4025,22 @@ __metadata: linkType: hard "typescript@npm:^5.1.3": - version: 5.2.2 - resolution: "typescript@npm:5.2.2" + version: 5.3.2 + resolution: "typescript@npm:5.3.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: d65e50eb849bd21ff8677e5b9447f9c6e74777e346afd67754934264dcbf4bd59e7d2473f6062d9a015d66bd573311166357e3eb07fea0b52859cf9bb2b58555 + checksum: 415e5fb6611f5713e460bad48039f00bcfdbde53a2f911727862d5aa9c5d5edd250059a419df382d8f031709e15a169c41eb62b6a401da5eec7ac0f4e359d6ac languageName: node linkType: hard "typescript@patch:typescript@npm%3A^5.1.3#optional!builtin": - version: 5.2.2 - resolution: "typescript@patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441" + version: 5.3.2 + resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: f79cc2ba802c94c2b78dbb00d767a10adb67368ae764709737dc277273ec148aa4558033a03ce901406b35fddf4eac46dabc94a1e1d12d2587e2b9cfe5707b4a + checksum: 1b45cdfb577a78ae7a9a9d0b77a7b772142cb98ba05e4e5aefba7044a028ded885bcecef63166407a5986645cea816fe4986894336aacd5e791796ea79a6a7ed languageName: node linkType: hard @@ -4105,10 +4058,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.25.1": - version: 5.25.3 - resolution: "undici-types@npm:5.25.3" - checksum: 9a57f2dd6fecb2d0f7d9b86aa6f417609a0ffc73247a95aa25c078cf36cbbfe6c164b63b8dace7ad01126e6510f284c185b69c78356bb1d6b279f195acffcaf4 +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd languageName: node linkType: hard @@ -4317,7 +4270,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1, which@npm:^2.0.2": +"which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -4328,12 +4281,14 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" dependencies: - string-width: "npm:^1.0.2 || 2 || 3 || 4" - checksum: d5f8027b9a8255a493a94e4ec1b74a27bff6679d5ffe29316a3215e4712945c84ef73ca4045c7e20ae7d0c72f5f57f296e04a4928e773d4276a2f1222e4c2e99 + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 languageName: node linkType: hard