Compare commits
5 Commits
master
...
ft/revert_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6c26d30bed | ||
![]() |
9fef286c33 | ||
![]() |
66dfb14591 | ||
![]() |
3e7a5a4108 | ||
![]() |
e2375b3b06 |
@ -1,4 +1,4 @@
|
||||
load("github.com/SonarSource/cirrus-modules@v3", "load_features")
|
||||
load("github.com/SonarSource/cirrus-modules@v2", "load_features")
|
||||
|
||||
def main(ctx):
|
||||
return load_features(ctx)
|
||||
|
41
.cirrus.yml
41
.cirrus.yml
@ -25,7 +25,7 @@ container_definition: &CONTAINER_DEFINITION
|
||||
|
||||
setup_sonar_scanner: &SETUP_SONAR_SCANNER
|
||||
setup_sonar_scanner_script:
|
||||
- apt update -y && apt upgrade -y && apt update -y && apt install -y unzip
|
||||
- apt update -y && apt upgrade -y && apt update -y && apt install -y unzip
|
||||
- curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
|
||||
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
|
||||
|
||||
@ -38,7 +38,9 @@ tooling_tests_task:
|
||||
env:
|
||||
PYTHONPATH: .
|
||||
install_dependencies_script:
|
||||
- ci/install_rspec_tools_dependencies.sh
|
||||
- cd rspec-tools
|
||||
- pipenv install --dev
|
||||
- pipenv run pip install pytest pytest-cov
|
||||
tests_script:
|
||||
- bash ci/fetch_branches.sh
|
||||
- cd rspec-tools
|
||||
@ -75,6 +77,15 @@ frontend_tests_task:
|
||||
- cd frontend
|
||||
- sonar-scanner
|
||||
|
||||
validate_metadata_task:
|
||||
eks_container:
|
||||
<<: *CONTAINER_DEFINITION
|
||||
dockerfile: ci/Dockerfile
|
||||
cpu: 1
|
||||
memory: 2G
|
||||
metadata_tests_script:
|
||||
- ./ci/validate_metadata.sh
|
||||
|
||||
validate_ci_tests_task:
|
||||
skip: "!changesInclude('ci_tests/**', 'ci/**')"
|
||||
eks_container:
|
||||
@ -85,22 +96,17 @@ validate_ci_tests_task:
|
||||
ci_tests_script:
|
||||
- ./ci_tests/asciidoc_validation/run_tests.sh
|
||||
|
||||
validate_rules_task:
|
||||
validate_asciidoc_task:
|
||||
eks_container:
|
||||
<<: *CONTAINER_DEFINITION
|
||||
dockerfile: ci/Dockerfile
|
||||
cpu: 1
|
||||
memory: 2G
|
||||
metadata_validation_script:
|
||||
- ./ci/validate_metadata.sh
|
||||
file_extensions_validation_script:
|
||||
- ./ci/validate_file_extensions.sh
|
||||
asciidoc_validation_script:
|
||||
asciidoc_tests_script:
|
||||
- ./ci/validate_asciidoc.sh
|
||||
|
||||
validate_links_task:
|
||||
timeout_in: 120m
|
||||
execution_lock: RSPEC_validate_links
|
||||
eks_container:
|
||||
<<: *CONTAINER_DEFINITION
|
||||
dockerfile: ci/Dockerfile
|
||||
@ -111,20 +117,31 @@ validate_links_task:
|
||||
LINK_CACHE_PATH: /root/link-probing-history.cache
|
||||
cache_download_script:
|
||||
- bash ci/cirrus-cache.sh download ${LINK_CACHE_NAME} ${LINK_CACHE_PATH}
|
||||
- md5sum /root/link-probing-history.cache/link_probes.history || true
|
||||
tests_script:
|
||||
- md5sum /root/link-probing-history.cache/link_probes.history || true
|
||||
- ./ci/validate_links.sh ${LINK_CACHE_PATH}
|
||||
- md5sum /root/link-probing-history.cache/link_probes.history
|
||||
always:
|
||||
cache_upload_script:
|
||||
- md5sum /root/link-probing-history.cache/link_probes.history || true
|
||||
- bash ci/cirrus-cache.sh upload ${LINK_CACHE_NAME} ${LINK_CACHE_PATH}
|
||||
|
||||
validate_file_extensions_task:
|
||||
eks_container:
|
||||
<<: *CONTAINER_DEFINITION
|
||||
dockerfile: ci/Dockerfile
|
||||
cpu: 1
|
||||
memory: 2G
|
||||
file_extension_tests_script:
|
||||
- bash ./ci/validate_file_extensions.sh
|
||||
|
||||
all_required_checks_task:
|
||||
depends_on:
|
||||
- tooling_tests
|
||||
- frontend_tests
|
||||
- validate_rules
|
||||
- validate_metadata
|
||||
- validate_asciidoc
|
||||
- validate_ci_tests
|
||||
- validate_file_extensions
|
||||
eks_container:
|
||||
<<: *CONTAINER_DEFINITION
|
||||
dockerfile: ci/Dockerfile
|
||||
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"dockerfile": "../ci/Dockerfile"
|
||||
},
|
||||
// https://code.visualstudio.com/docs/devcontainers/create-dev-container#_rebuild
|
||||
"postCreateCommand": ".devcontainer/finalize-container.sh",
|
||||
"waitFor": "postCreateCommand",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"asciidoctor.asciidoctor-vscode"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
TOP_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)/..
|
||||
|
||||
$TOP_DIR/ci/install_rspec_tools_dependencies.sh
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
||||
.github/CODEOWNERS @sonarsource/quality-cfamily-squad
|
||||
.github/CODEOWNERS @sonarsource/analysis-cfamily-squad
|
||||
|
9
.github/pull_request_template.md
vendored
9
.github/pull_request_template.md
vendored
@ -1,12 +1,3 @@
|
||||
<!--
|
||||
Jira Automation:
|
||||
|
||||
* Mention existing issue in the PR title to move it around automatically.
|
||||
* Mention existing issue in the PR description and a sub-task will be created for you to track this rspec PR separately.
|
||||
|
||||
No issue is created by default.
|
||||
-->
|
||||
|
||||
## Review
|
||||
|
||||
A dedicated reviewer checked the rule description successfully for:
|
||||
|
28
.github/workflows/PullRequestClosed.yml
vendored
28
.github/workflows/PullRequestClosed.yml
vendored
@ -1,28 +0,0 @@
|
||||
name: Pull Request Closed
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
PullRequestMerged_job:
|
||||
name: Pull Request Merged
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
pull-requests: read
|
||||
# For external PR, ticket should be moved manually
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- id: secrets
|
||||
uses: SonarSource/vault-action-wrapper@v3
|
||||
with:
|
||||
secrets: |
|
||||
development/kv/data/jira user | JIRA_USER;
|
||||
development/kv/data/jira token | JIRA_TOKEN;
|
||||
- uses: sonarsource/gh-action-lt-backlog/PullRequestClosed@v2
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }}
|
||||
jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }}
|
28
.github/workflows/PullRequestCreated.yml
vendored
28
.github/workflows/PullRequestCreated.yml
vendored
@ -1,28 +0,0 @@
|
||||
name: Pull Request Created
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: ["opened"]
|
||||
|
||||
jobs:
|
||||
PullRequestCreated_job:
|
||||
name: Pull Request Created
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
# For external PR, ticket should be created manually
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- id: secrets
|
||||
uses: SonarSource/vault-action-wrapper@v3
|
||||
with:
|
||||
secrets: |
|
||||
development/github/token/{REPO_OWNER_NAME_DASH}-jira token | GITHUB_TOKEN;
|
||||
development/kv/data/jira user | JIRA_USER;
|
||||
development/kv/data/jira token | JIRA_TOKEN;
|
||||
- uses: sonarsource/gh-action-lt-backlog/PullRequestCreated@v2
|
||||
with:
|
||||
github-token: ${{ fromJSON(steps.secrets.outputs.vault).GITHUB_TOKEN }}
|
||||
jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }}
|
||||
jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }}
|
28
.github/workflows/RequestReview.yml
vendored
28
.github/workflows/RequestReview.yml
vendored
@ -1,28 +0,0 @@
|
||||
name: Request review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: ["review_requested"]
|
||||
|
||||
jobs:
|
||||
RequestReview_job:
|
||||
name: Request review
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
# For external PR, ticket should be moved manually
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- id: secrets
|
||||
uses: SonarSource/vault-action-wrapper@v3
|
||||
with:
|
||||
secrets: |
|
||||
development/github/token/{REPO_OWNER_NAME_DASH}-jira token | GITHUB_TOKEN;
|
||||
development/kv/data/jira user | JIRA_USER;
|
||||
development/kv/data/jira token | JIRA_TOKEN;
|
||||
- uses: sonarsource/gh-action-lt-backlog/RequestReview@v2
|
||||
with:
|
||||
github-token: ${{ fromJSON(steps.secrets.outputs.vault).GITHUB_TOKEN }}
|
||||
jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }}
|
||||
jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }}
|
30
.github/workflows/SubmitReview.yml
vendored
30
.github/workflows/SubmitReview.yml
vendored
@ -1,30 +0,0 @@
|
||||
name: Submit Review
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
SubmitReview_job:
|
||||
name: Submit Review
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
pull-requests: read
|
||||
# For external PR, ticket should be moved manually
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
&& (github.event.review.state == 'changes_requested'
|
||||
|| github.event.review.state == 'approved')
|
||||
steps:
|
||||
- id: secrets
|
||||
uses: SonarSource/vault-action-wrapper@v3
|
||||
with:
|
||||
secrets: |
|
||||
development/kv/data/jira user | JIRA_USER;
|
||||
development/kv/data/jira token | JIRA_TOKEN;
|
||||
- uses: sonarsource/gh-action-lt-backlog/SubmitReview@v2
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
jira-user: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }}
|
||||
jira-token: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }}
|
3
.github/workflows/add_language.yml
vendored
3
.github/workflows/add_language.yml
vendored
@ -15,9 +15,6 @@ on:
|
||||
jobs:
|
||||
add_language_to_rule:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
3
.github/workflows/create_new_rspec.yml
vendored
3
.github/workflows/create_new_rspec.yml
vendored
@ -12,9 +12,6 @@ on:
|
||||
jobs:
|
||||
create_new_rule:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@ -7,10 +7,11 @@ on:
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
pull-requests: read # Get the list and metadata of open new-rule PRs
|
||||
contents: write # Get the contents of open new-rule PRs, the 'master'; write to 'gh-pages' branch
|
||||
pages: write # for github-pages-deploy-action
|
||||
steps:
|
||||
- name: Checkout 🛎️
|
||||
uses: actions/checkout@v4 # If you're using actions/checkout you must set persist-credentials to false in most cases for the deployment to work correctly.
|
||||
|
103
.github/workflows/update_coverage.yml
vendored
103
.github/workflows/update_coverage.yml
vendored
@ -2,34 +2,20 @@ name: Update rule coverage
|
||||
on:
|
||||
schedule:
|
||||
- cron: '17 2 * * *'
|
||||
workflow_dispatch: # When manually triggered from a non-default branch, the results will not be pushed
|
||||
|
||||
workflow_dispatch
|
||||
jobs:
|
||||
update_coverage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # required by SonarSource/vault-action-wrapper
|
||||
contents: write
|
||||
actions: write # required by andymckay/cancel-action
|
||||
env:
|
||||
TMP_BRANCH: temporary/coverage_update
|
||||
|
||||
steps:
|
||||
- name: 'get secrets'
|
||||
id: secrets
|
||||
uses: SonarSource/vault-action-wrapper@v3
|
||||
with:
|
||||
secrets: |
|
||||
development/github/token/SonarSource-rspec-coverage token | coverage_github_token;
|
||||
development/kv/data/slack token | slack_token;
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: true
|
||||
fetch-depth: 0
|
||||
ref: master
|
||||
path: 'rspec'
|
||||
token: ${{ fromJSON(steps.secrets.outputs.vault).coverage_github_token }}
|
||||
ref: 'master'
|
||||
token: ${{ secrets.COVERAGE_GITHUB_TOKEN }}
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
@ -45,7 +31,7 @@ jobs:
|
||||
|
||||
- name: 'Regenerate coverage information'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).coverage_github_token }}
|
||||
GITHUB_TOKEN: ${{ secrets.COVERAGE_GITHUB_TOKEN }}
|
||||
id: gen-coverage
|
||||
working-directory: 'rspec/rspec-tools'
|
||||
run: |
|
||||
@ -73,67 +59,44 @@ jobs:
|
||||
git commit -m "update coverage information"
|
||||
git push --force-with-lease origin $TMP_BRANCH
|
||||
|
||||
- name: 'Create a PR'
|
||||
id: create-github-pr
|
||||
working-directory: 'rspec'
|
||||
env:
|
||||
GH_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).coverage_github_token }}
|
||||
run: |
|
||||
PR_URL=$(gh pr create --head ${{ env.TMP_BRANCH }} --title "Update coverage information" --body "" --label "rspec system")
|
||||
gh pr merge $PR_URL
|
||||
- name: 'Wait for CI to succeed'
|
||||
if: steps.gen-coverage.outputs.new_coverage == 'true'
|
||||
uses: fountainhead/action-wait-for-check@v1.0.0
|
||||
id: wait-for-build
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
checkName: all_required_checks
|
||||
ref: ${{ env.TMP_BRANCH }}
|
||||
timeoutSeconds: 2400
|
||||
intervalSeconds: 30
|
||||
|
||||
- name: 'Wait until the PR is merged'
|
||||
id: wait-for-pr-to-merge
|
||||
env:
|
||||
GH_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).coverage_github_token }}
|
||||
- name: 'Push the updated coverage to master'
|
||||
if: |
|
||||
steps.gen-coverage.outputs.new_coverage == 'true' &&
|
||||
steps.wait-for-build.outputs.conclusion == 'success'
|
||||
working-directory: 'rspec'
|
||||
run: |
|
||||
set -ueo pipefail
|
||||
git checkout master
|
||||
git merge $TMP_BRANCH
|
||||
git push origin master
|
||||
|
||||
# Implicitly referring to the PR corresponding to current branch
|
||||
- name: 'Delete the temporary branch'
|
||||
if: always() && steps.create-temp-branch.conclusion == 'success'
|
||||
uses: dawidd6/action-delete-branch@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN}}
|
||||
branches: ${{ env.TMP_BRANCH}}
|
||||
|
||||
# Set timeout (20 minutes in seconds)
|
||||
TIMEOUT=1200 # seconds
|
||||
START_TIME=$(date +%s)
|
||||
INTERVAL=20 # seconds
|
||||
|
||||
while true; do
|
||||
# Check if the PR is merged
|
||||
PR_STATE=$(gh pr view --json state,mergedAt -q '.state')
|
||||
MERGED_AT=$(gh pr view --json state,mergedAt -q '.mergedAt')
|
||||
|
||||
if [[ "${PR_STATE}" == "MERGED" ]]; then
|
||||
echo "PR merged at: $MERGED_AT"
|
||||
exit 0
|
||||
fi
|
||||
echo "PR state is ${PR_STATE}"
|
||||
|
||||
# Check for timeout
|
||||
CURRENT_TIME=$(date +%s)
|
||||
ELAPSED_TIME=$((CURRENT_TIME - START_TIME))
|
||||
|
||||
if [[ "${ELAPSED_TIME}" -gt "${TIMEOUT}" ]]; then
|
||||
echo "Timeout waiting for PR to merge."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for $INTERVAL seconds before checking again
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
|
||||
- name: 'Close PR and delete branch upon failure to merge'
|
||||
if: ${{ failure() }}
|
||||
env:
|
||||
GH_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).coverage_github_token }}
|
||||
working-directory: 'rspec'
|
||||
run: |
|
||||
PR_URL=$(gh pr view --json url --jq '.url')
|
||||
gh pr close "$PR_URL" --delete-branch
|
||||
- name: 'Fail if the change breaks CI'
|
||||
if: |
|
||||
steps.gen-coverage.outputs.new_coverage == 'true' &&
|
||||
steps.wait-for-build.outputs.conclusion != 'success'
|
||||
run: exit 1
|
||||
|
||||
- name: 'Notify on slack about the failure'
|
||||
if: ${{ failure() }}
|
||||
env:
|
||||
SLACK_API_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).slack_token }}
|
||||
SLACK_API_TOKEN: ${{ secrets.SLACK_API_TOKEN }}
|
||||
working-directory: 'rspec/rspec-tools'
|
||||
run: |
|
||||
pipenv run rspec-tools notify-failure-on-slack \
|
||||
|
5
.github/workflows/update_quickfix_status.yml
vendored
5
.github/workflows/update_quickfix_status.yml
vendored
@ -25,10 +25,7 @@ on:
|
||||
jobs:
|
||||
update_quickfix_status:
|
||||
name: Update quick fix status
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,7 +10,6 @@
|
||||
# generated files
|
||||
/rules/**/*.html
|
||||
/frontend/public/rules
|
||||
rspec-tools/link_probes.history
|
||||
|
||||
# compiled files
|
||||
*.out
|
||||
|
275
LICENSE
275
LICENSE
@ -1,184 +1,165 @@
|
||||
SONAR Source-Available License v1.0
|
||||
Last Updated November 13, 2024
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
1. DEFINITIONS
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
"Agreement" means this Sonar Source-Available License v1.0
|
||||
|
||||
"Competing" means marketing a product or service as a substitute for the
|
||||
functionality or value of SonarQube. A product or service may compete regardless
|
||||
of how it is designed or deployed. For example, a product or service may compete
|
||||
even if it provides its functionality via any kind of interface (including
|
||||
services, libraries, or plug-ins), even if it is ported to a different platform
|
||||
or programming language, and even if it is provided free of charge.
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
"Contribution" means:
|
||||
0. Additional Definitions.
|
||||
|
||||
a) in the case of the initial Contributor, the initial content Distributed under
|
||||
this Agreement, and
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
b) in the case of each subsequent Contributor:
|
||||
i) changes to the Program, and
|
||||
ii) additions to the Program;
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
where such changes and/or additions to the Program originate from and are
|
||||
Distributed by that particular Contributor. A Contribution "originates" from a
|
||||
Contributor if it was added to the Program by such Contributor itself or anyone
|
||||
acting on such Contributor's behalf. Contributions do not include changes or
|
||||
additions to the Program that are not Modified Works.
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
"Contributor" means any person or entity that Distributes the Program.
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source Code or other form,
|
||||
that is based on (or derived from) the Program and for which the editorial
|
||||
revisions, annotations, elaborations, or other modifications represent, as a
|
||||
whole, an original work of authorship.
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
"Distribute" means the acts of a) distributing or b) making available in any
|
||||
manner that enables the transfer of a copy.
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor that are
|
||||
necessarily infringed by the use or sale of its Contribution alone or when
|
||||
combined with the Program.
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
"Modified Works" shall mean any work in Source Code or other form that results
|
||||
from an addition to, deletion from, or modification of the contents of the
|
||||
Program, including, for purposes of clarity, any new file in Source Code form
|
||||
that contains any contents of the Program. Modified Works shall not include
|
||||
works that contain only declarations, interfaces, types, classes, structures, or
|
||||
files of the Program solely in each case in order to link to, bind by name, or
|
||||
subclass the Program or Modified Works thereof.
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
"Non-competitive Purpose" means any purpose except for (a) providing to others
|
||||
any product or service that includes or offers the same or substantially similar
|
||||
functionality as SonarQube, (b) Competing with SonarQube, and/or (c) employing,
|
||||
using, or engaging artificial intelligence technology that is not part of the
|
||||
Program to ingest, interpret, analyze, train on, or interact with the data
|
||||
provided by the Program, or to engage with the Program in any manner.
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
"Notices" means any legal statements or attributions included with the Program,
|
||||
including, without limitation, statements concerning copyright, patent,
|
||||
trademark, disclaimers of warranty, or limitations of liability
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
"Program" means the Contributions Distributed in accordance with this Agreement.
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement,
|
||||
including Contributors.
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
"SonarQube" means an open-source or commercial edition of software offered by
|
||||
SonarSource that is branded "SonarQube".
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
"SonarSource" means SonarSource SA, a Swiss company registered in Switzerland
|
||||
under UID No. CHE-114.587.664.
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
"Source Code" means the form of a Program preferred for making modifications,
|
||||
including but not limited to software source code, documentation source, and
|
||||
configuration files.
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide, royalty-free copyright license, for any
|
||||
Non-competitive Purpose, to reproduce, prepare Derivative Works of, publicly
|
||||
display, publicly perform, Distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such Derivative Works.
|
||||
4. Combined Works.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
|
||||
Patents, for any Non-competitive Purpose, to make, use, sell, offer to sell,
|
||||
import, and otherwise transfer the Contribution of such Contributor, if any, in
|
||||
Source Code or other form. This patent license shall apply to the combination of
|
||||
the Contribution and the Program if, at the time the Contribution is added by
|
||||
the Contributor, such addition of the Contribution causes such combination to be
|
||||
covered by the Licensed Patents. The patent license shall not apply to any other
|
||||
combinations that include the Contribution.
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
c) Recipient understands that although each Contributor grants the licenses to
|
||||
its Contributions set forth herein, no assurances are provided by any
|
||||
Contributor that the Program does not infringe the patent or other intellectual
|
||||
property rights of any other entity. Each Contributor disclaims any liability to
|
||||
Recipient for claims brought by any other entity based on infringement of
|
||||
intellectual property rights or otherwise. As a condition to exercising the
|
||||
rights and licenses granted hereunder, each Recipient hereby assumes sole
|
||||
responsibility to secure any other intellectual property rights needed, if any.
|
||||
For example, if a third-party patent license is required to allow Recipient to
|
||||
Distribute the Program, it is Recipient's responsibility to acquire that license
|
||||
before distributing the Program.
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has sufficient copyright
|
||||
rights in its Contribution, if any, to grant the copyright license set forth in
|
||||
this Agreement.
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
3. REQUIREMENTS
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
3.1 If a Contributor Distributes the Program in any form, then the Program must
|
||||
also be made available as Source Code, in accordance with section 3.2, and the
|
||||
Contributor must accompany the Program with a statement that the Source Code for
|
||||
the Program is available under this Agreement, and inform Recipients how to
|
||||
obtain it in a reasonable manner on or through a medium customarily used for
|
||||
software exchange; and
|
||||
d) Do one of the following:
|
||||
|
||||
3.2 When the Program is Distributed as Source Code:
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
a) it must be made available under this Agreement, and
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of the Program.
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
3.3 Contributors may not remove or alter any Notices contained within the
|
||||
Program from any copy of the Program which they Distribute, provided that
|
||||
Contributors may add their own appropriate Notices.
|
||||
5. Combined Libraries.
|
||||
|
||||
4. NO WARRANTY
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
|
||||
OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
||||
LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and distributing the
|
||||
Program and assumes all risks associated with its exercise of rights under this
|
||||
Agreement, including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs or
|
||||
equipment, and unavailability or interruption of operations.
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
5. DISCLAIMER OF LIABILITY
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
|
||||
THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGES.
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
6. GENERAL
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser 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.
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under applicable
|
||||
law, it shall not affect the validity or enforceability of the remainder of the
|
||||
terms of this Agreement, and without further action by the parties hereto, such
|
||||
provision shall be reformed to the minimum extent necessary to make such
|
||||
provision valid and enforceable.
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If Recipient institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program itself
|
||||
(excluding combinations of the Program with other software or hardware)
|
||||
infringes such Recipient’s patent(s), then such Recipient’s rights granted under
|
||||
Section 2(b) shall terminate as of the date such litigation is filed.
|
||||
|
||||
All Recipient’s rights under this Agreement shall terminate if it fails to
|
||||
comply with any of the material terms or conditions of this Agreement and does
|
||||
not cure such failure in a reasonable period of time after becoming aware of
|
||||
such noncompliance. If all Recipient’s rights under this Agreement terminate,
|
||||
Recipient agrees to cease use and distribution of the Program as soon as
|
||||
reasonably practicable. However, Recipient’s obligations under this Agreement
|
||||
and any licenses granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives
|
||||
no rights or licenses to the intellectual property of any Contributor under this
|
||||
Agreement, whether expressly, by implication, estoppel, or otherwise. All rights
|
||||
in the Program not expressly granted under this Agreement are reserved. Nothing
|
||||
in this Agreement is intended to be enforceable by any entity that is not a
|
||||
Contributor or Recipient. No third-party beneficiary rights are created under
|
||||
this Agreement.
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
@ -8,8 +8,6 @@ This repository contains the specification of every static-analysis rule availab
|
||||
|
||||
It also contains rules which have been dropped and rules which will one day be implemented.
|
||||
|
||||
The content of this repository is covered by the link:LICENSE[SONAR Source-Available License v1.0].
|
||||
|
||||
== Rules directory structure
|
||||
|
||||
* https://github.com/SonarSource/rspec/tree/master/rules[rules] directory: contains every specified rule.
|
||||
|
@ -6,38 +6,38 @@ ACTION=${1}
|
||||
CACHE_NAME=${2}
|
||||
PATH_TO_CACHE=${3}
|
||||
|
||||
CACHE_URL="http://${CIRRUS_HTTP_CACHE_HOST}/${CACHE_NAME}"
|
||||
CACHE_KEY=${CACHE_NAME}
|
||||
DEFAULT_CACHE_KEY=${CACHE_NAME}
|
||||
|
||||
TMP_PATH="/tmp/tmp-cache.tgz"
|
||||
CACHE_URL=http://${CIRRUS_HTTP_CACHE_HOST}/${CACHE_KEY}
|
||||
|
||||
TMP_PATH=/tmp/tmp-cache.tgz
|
||||
|
||||
case "${ACTION}" in
|
||||
|
||||
download)
|
||||
echo "Download cache with key ${CACHE_NAME} from ${CACHE_URL}"
|
||||
curl --silent --show-error --fail --location --output "${TMP_PATH}" "${CACHE_URL}" || {
|
||||
echo "Cache download failed" >&2
|
||||
exit 0
|
||||
echo "Download cache with key ${CACHE_KEY}"
|
||||
|
||||
echo " -> try ${CACHE_URL}"
|
||||
curl -sfSL -o ${TMP_PATH} ${CACHE_URL} || {
|
||||
echo "Cache download failed";
|
||||
exit 0;
|
||||
}
|
||||
du -hs "${TMP_PATH}"
|
||||
tar -Pxzf "${TMP_PATH}"
|
||||
rm "${TMP_PATH}"
|
||||
du -hs ${TMP_PATH}
|
||||
tar -Pxzf ${TMP_PATH}
|
||||
rm ${TMP_PATH}
|
||||
;;
|
||||
|
||||
upload)
|
||||
echo "Upload cache to ${CACHE_URL}"
|
||||
tar -Pczf "${TMP_PATH}" "${PATH_TO_CACHE}"
|
||||
du -hs "${TMP_PATH}"
|
||||
curl --silent --show-error -X POST --data-binary "@${TMP_PATH}" "${CACHE_URL}" || {
|
||||
echo "Cache upload failed" >&2
|
||||
exit 0
|
||||
}
|
||||
tar -Pczf ${TMP_PATH} ${PATH_TO_CACHE}
|
||||
du -hs ${TMP_PATH}
|
||||
curl -s -X POST --data-binary @${TMP_PATH} ${CACHE_URL}
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unexpected cache ACTION: ${ACTION}" >&2
|
||||
echo "Unexpected cache ACTION: ${ACTION}"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
echo "Cache ${ACTION}ed succeeded."
|
||||
|
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd rspec-tools
|
||||
pipenv install --dev
|
||||
pipenv run pip install pytest pytest-cov
|
0
ci/validate_file_extensions.sh
Executable file → Normal file
0
ci/validate_file_extensions.sh
Executable file → Normal file
@ -13,20 +13,17 @@ else
|
||||
git diff --name-only "${base}" -- rules/ | # Get all the changes in rules
|
||||
sed -Ee 's#(rules/S[0-9]+)/.*#\1#' | # extract the rule directories
|
||||
sort -u | # deduplicate
|
||||
while IFS= read -r rule; do if [[ -d "$rule" ]]; then echo "$rule"; fi done | # filter out deleted rules
|
||||
while IFS= read -r rule; do [[ -d "$rule" ]] && echo "$rule" || true; done | # filter non-deleted rules
|
||||
sed 's#rules/##' | # get rule ids
|
||||
mapfile -t affected_rules # store them in the `affected_rules` array
|
||||
echo "Validating ${affected_rules[*]}"
|
||||
echo "Validating ${affected_rules[@]}"
|
||||
fi
|
||||
|
||||
printf '\n\n\n'
|
||||
|
||||
# Validate metadata
|
||||
if [[ "${#affected_rules[@]}" -gt 0 ]]
|
||||
then
|
||||
cd rspec-tools
|
||||
pipenv install
|
||||
printf '\n\n\n'
|
||||
pipenv run rspec-tools validate-rules-metadata "${affected_rules[@]}"
|
||||
else
|
||||
echo "No rule changed or added"
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
== In the RSPEC
|
||||
|
||||
The rule status (`/status` in the metadata) should be set to `deprecated`, and its tags should be removed. If the rule is in `SonarWay`, it should be removed from this profile.
|
||||
The rule status (`/status` in the metadata) should be set to `deprecated`.
|
||||
|
||||
Optionally, `/extra/replacementRules` can list the rules that replace this rule.
|
||||
|
||||
|
@ -271,24 +271,6 @@ tsql:: use `sql`
|
||||
|
||||
In case no language is appropriate for a code block (for example shared examples between multiple languages), you can use `text` as the language.
|
||||
|
||||
=== Comments within code blocks
|
||||
|
||||
Colon (`:`) should be used as separator between `Noncompliant`/`Compliant` comments and the text explanation that follows, if any.
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
int X = 2; // Noncompliant: variable should be in lowercase
|
||||
----
|
||||
|
||||
|
||||
When referencing a name within a comment in a code example, use double quotes to make it clear it refers to an existing element in the code.
|
||||
|
||||
[source,cpp]
|
||||
----
|
||||
int i = 0;
|
||||
cout << noexcept(++i); // Noncompliant: "i" is not incremented
|
||||
----
|
||||
|
||||
=== Diff view
|
||||
|
||||
Additionally, you can also use two attributes to let the products know your code examples should be highlighted with a diff view when possible
|
||||
|
@ -1,4 +1,3 @@
|
||||
// Ansible
|
||||
// C#
|
||||
* ASP.NET
|
||||
* ASP.NET Core
|
||||
@ -9,7 +8,6 @@
|
||||
* Dapper
|
||||
* BouncyCastle
|
||||
* Jwt.Net
|
||||
* Blazor
|
||||
// C-Family
|
||||
* Botan
|
||||
* CryptoPP
|
||||
@ -27,7 +25,6 @@
|
||||
* libxml2
|
||||
// Java
|
||||
* Android
|
||||
* Android WebView
|
||||
* Apache Commons
|
||||
* Apache Commons
|
||||
* Apache Commons Email
|
||||
@ -43,16 +40,14 @@
|
||||
* Java EE
|
||||
* Java JWT
|
||||
* Java SE
|
||||
* Java JDBC API
|
||||
* Java I/O API
|
||||
* Jdom2
|
||||
* JSP
|
||||
* Legacy Mongo Java API
|
||||
* OkHttp
|
||||
* Realm
|
||||
* Java Cryptography Extension
|
||||
* Apache HttpClient
|
||||
* Couchbase
|
||||
* SAX
|
||||
* Servlet
|
||||
* Spring
|
||||
* Spring Data MongoDB
|
||||
@ -62,13 +57,10 @@
|
||||
* SQLCipher
|
||||
* Thymeleaf
|
||||
// JS
|
||||
* Jasmine
|
||||
* Jest
|
||||
* Flow.js
|
||||
* Node.js
|
||||
* Express.js
|
||||
* SSH2
|
||||
* Mocha
|
||||
* MongoDB
|
||||
* Mongoose
|
||||
* Sequelize
|
||||
@ -83,7 +75,6 @@
|
||||
* TypeScript
|
||||
* PropTypes
|
||||
* JSX
|
||||
* Electron
|
||||
// PHP
|
||||
* Core PHP
|
||||
* Guzzle
|
||||
@ -98,7 +89,6 @@
|
||||
* Argon2-cffi
|
||||
* Bcrypt
|
||||
* Cryptodome
|
||||
* databases
|
||||
* Django
|
||||
* Django Templates
|
||||
* FastAPI
|
||||
@ -119,7 +109,6 @@
|
||||
* python-ldap
|
||||
* Python SQLite
|
||||
* Python Standard Library
|
||||
* PyTorch
|
||||
* PyYAML
|
||||
* Requests
|
||||
* Scrypt
|
||||
@ -127,7 +116,6 @@
|
||||
* SignXML
|
||||
* SQLAlchemy
|
||||
* ssl
|
||||
* TensorFlow
|
||||
// Docker
|
||||
* Wget
|
||||
// Cloudformation
|
||||
@ -153,7 +141,7 @@
|
||||
* CryptoSwift
|
||||
* IDZSwiftCommonCrypto
|
||||
// Azure resource manager
|
||||
* JSON templates
|
||||
* ARM templates
|
||||
* Bicep
|
||||
// PL/SQL
|
||||
* DBMS_CRYPTO
|
||||
@ -161,5 +149,3 @@
|
||||
* Go Standard Library
|
||||
// Kubernetes
|
||||
* Helm
|
||||
// Kotlin
|
||||
Jetpack Compose
|
||||
|
@ -45,7 +45,6 @@ When web pages have massively long names like "Java™ Platform, Standard Editio
|
||||
* AWS blog - https://aws.amazon.com/blogs
|
||||
* Azure Documentation - https://learn.microsoft.com/en-us/azure/?product=popular
|
||||
* CERT - https://wiki.sei.cmu.edu/confluence/display/seccode
|
||||
* Clippy Lints - https://rust-lang.github.io/rust-clippy/master/index.html
|
||||
* {cpp} reference - https://en.cppreference.com/w/
|
||||
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md
|
||||
* CVE - https://cve.mitre.org
|
||||
|
@ -40,6 +40,6 @@ You can update the quickfix field using this GitHub Workflow: https://github.com
|
||||
|
||||
The code field is an object that contains information related to the clean code taxonomy. It is an object with two required properties:
|
||||
|
||||
* `impacts`: A nested object that is treated as a mapping from a software quality to a level (`"INFO"`, `"LOW"`, `"MEDIUM"`, `"HIGH"` or `"BLOCKER"`). Note that at least one software quality has to be specified. The current list of allowed software qualities is `"MAINTAINABILITY"`, `"RELIABILITY"` and `"SECURITY"`.
|
||||
* `impacts`: A nested object that is treated as a mapping from a software quality to a level (`"LOW"`, `"MEDIUM"` or `"HIGH"`). Note that at least one software quality has to be specified. The current list of allowed software qualities is `"MAINTAINABILITY"`, `"RELIABILITY"` and `"SECURITY"`.
|
||||
|
||||
* `attribute`: A single clean code attribute that the rule aims to achieve. This has to be one of the following values: `"FORMATTED"`, `"CONVENTIONAL"`, `"IDENTIFIABLE"`, `"CLEAR"`, `"LOGICAL"`, `"COMPLETE"`, `"EFFICIENT"`, `"FOCUSED"`, `"DISTINCT"`, `"MODULAR"`, `"TESTED"`, `"LAWFUL"`, `"TRUSTWORTHY"`, `"RESPECTFUL"`.
|
||||
|
@ -109,17 +109,3 @@ Use it when referencing variable names, file names, tokens, and all kinds of spe
|
||||
Write:: Compiling source file `src/generic_file.py` breaks an `assert` call in pytest framework.
|
||||
Avoid:: Compiling source file "src/generic_file.py" breaks an `assert` call in `pytest` framework.
|
||||
|
||||
== Referencing elements from the code
|
||||
|
||||
When referencing elements from the code within a normal sentence, use the `backticks` (```) to format it. This includes variable names, function names, class names, and so on.
|
||||
|
||||
When referencing the same elements within a comment in a code block, surrpond it with double quotes.
|
||||
[source,cpp]
|
||||
----
|
||||
int i = 0;
|
||||
// Write
|
||||
cout << noexcept(++i); // Noncompliant, "i" is not incremented -> Double quotes
|
||||
// Avoid
|
||||
cout << noexcept(++i); // Noncompliant, i is not incremented -> No quotes
|
||||
cout << noexcept(++i); // Noncompliant, `i` is not incremented -> Backticks
|
||||
----
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -158,24 +158,22 @@ const languageToJiraProject = new Map(Object.entries({
|
||||
'HTML': 'SONARHTML',
|
||||
'PHP': 'SONARPHP',
|
||||
'PLI': 'SONARPLI',
|
||||
'PLSQL': 'PLSQL',
|
||||
'PLSQL': 'SONARPLSQL',
|
||||
'RPG': 'SONARRPG',
|
||||
'APEX': 'SONARAPEX',
|
||||
'RUBY': 'SONARRUBY',
|
||||
'RUST': 'SKUNK',
|
||||
'APEX': 'SONARSLANG',
|
||||
'RUBY': 'SONARSLANG',
|
||||
'KOTLIN': 'SONARKT',
|
||||
'SCALA': 'SONARSCALA',
|
||||
'GO': 'SONARGO',
|
||||
'SECRETS': 'SONARTEXT',
|
||||
'SCALA': 'SONARSLANG',
|
||||
'GO': 'SONARSLANG',
|
||||
'SECRETS': 'SECRETS',
|
||||
'SWIFT': 'SONARSWIFT',
|
||||
'TSQL': 'TSQL',
|
||||
'VB6': 'VB6',
|
||||
'TSQL': 'SONARTSQL',
|
||||
'VB6': 'SONARVBSIX',
|
||||
'XML': 'SONARXML',
|
||||
'CLOUDFORMATION': 'SONARIAC',
|
||||
'TERRAFORM': 'SONARIAC',
|
||||
'KUBERNETES': 'SONARIAC',
|
||||
'TEXT': 'SONARTEXT',
|
||||
'ANSIBLE': 'SONARIAC',
|
||||
}));
|
||||
|
||||
const languageToGithubProject = new Map(Object.entries({
|
||||
@ -189,11 +187,10 @@ const languageToGithubProject = new Map(Object.entries({
|
||||
'TYPESCRIPT': 'SonarJS',
|
||||
'SWIFT': 'sonar-swift',
|
||||
'KOTLIN': 'sonar-kotlin',
|
||||
'GO': 'sonar-go',
|
||||
'SCALA': 'sonar-scala',
|
||||
'RUBY': 'sonar-ruby',
|
||||
'RUST': 'sonar-rust',
|
||||
'APEX': 'sonar-apex',
|
||||
'GO': 'slang-enterprise',
|
||||
'SCALA': 'slang-enterprise',
|
||||
'RUBY': 'slang-enterprise',
|
||||
'APEX': 'slang-enterprise',
|
||||
'HTML': 'sonar-html',
|
||||
'COBOL': 'sonar-cobol',
|
||||
'VB6': 'sonar-vb',
|
||||
@ -212,9 +209,8 @@ const languageToGithubProject = new Map(Object.entries({
|
||||
'CLOUDFORMATION': 'sonar-iac',
|
||||
'TERRAFORM': 'sonar-iac',
|
||||
'KUBERNETES': 'sonar-iac',
|
||||
'SECRETS': 'sonar-text',
|
||||
'SECRETS': 'sonar-secrets',
|
||||
'TEXT': 'sonar-text',
|
||||
'ANSIBLE': 'sonar-iac-enterprise',
|
||||
}));
|
||||
|
||||
function ticketsAndImplementationPRsLinks(ruleNumber: string, title: string, language?: string) {
|
||||
@ -320,7 +316,7 @@ function usePageMetadata(ruleid: string, language: string, classes: UsedStyles):
|
||||
|
||||
if (coverage !== 'Not Covered') {
|
||||
prUrl = undefined;
|
||||
branch = 'master';
|
||||
branch = 'master';
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -31,7 +31,7 @@ export async function process_incomplete_rspecs(tmpRepoDir: string,
|
||||
const repo = await (() => {
|
||||
if (!fs.existsSync(path.join(tmpRepoDir, '.git'))) {
|
||||
if (process.env.GITHUB_TOKEN) {
|
||||
return Git.Clone.clone(`https://${process.env.GITHUB_TOKEN}@github.com/SonarSource/rspec/`, tmpRepoDir);
|
||||
return Git.Clone.clone('https://' + process.env.GITHUB_TOKEN + '@github.com/SonarSource/rspec/', tmpRepoDir);
|
||||
} else {
|
||||
return Git.Clone.clone('https://github.com/SonarSource/rspec/', tmpRepoDir);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ const languageToSonarpedia = new Map<string, string[]>(Object.entries({
|
||||
'plsql': ['PLSQL'],
|
||||
'python': ['PY'],
|
||||
'rpg': ['RPG'],
|
||||
'rust': ['RUST'],
|
||||
'secrets': ['SECRETS'],
|
||||
'swift': ['SWIFT'],
|
||||
'tsql': ['TSQL'],
|
||||
@ -38,8 +37,7 @@ const languageToSonarpedia = new Map<string, string[]>(Object.entries({
|
||||
'cloudformation': ['CLOUDFORMATION'],
|
||||
'terraform': ['TERRAFORM'],
|
||||
'kubernetes': ['KUBERNETES'],
|
||||
'text': ['TEXT'],
|
||||
'ansible': ['ANSIBLE']
|
||||
'text': ['TEXT']
|
||||
}));
|
||||
|
||||
export function useRuleCoverage() {
|
||||
|
@ -55,5 +55,5 @@ In order to generate an HTML file from the ASCIIdoc, you can use [asciidoctor](h
|
||||
|
||||
[source,sh]
|
||||
----
|
||||
$ asciidoctor rule.adoc
|
||||
$ asciidoctor -e rule.adoc
|
||||
----
|
||||
|
@ -3,11 +3,11 @@
|
||||
"type": "VULNERABILITY",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"SECURITY": "BLOCKER"
|
||||
"SECURITY": "HIGH"
|
||||
},
|
||||
"attribute": "TRUSTWORTHY"
|
||||
},
|
||||
"status": "beta",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "30min"
|
||||
@ -45,7 +45,7 @@
|
||||
"3.5.2",
|
||||
"6.4.1"
|
||||
],
|
||||
"STIG ASD_V5R3": [
|
||||
"STIG ASD 2023-06-08": [
|
||||
"V-222642"
|
||||
]
|
||||
},
|
||||
|
@ -1,11 +1,3 @@
|
||||
:example_env: ENV_VAR_NAME
|
||||
:example_name: java-property-name
|
||||
:example_secret: example_secret_value
|
||||
|
||||
// Set value that can be used to refer to the type of secret in, for example:
|
||||
// "An attacker can use this {secret_type} to ..."
|
||||
// Commonly used values: access token, api key, application secret, application key or consumer key, service password, OAuth token, deployment password
|
||||
:secret_type: secret
|
||||
|
||||
include::../../../shared_content/secrets/description.adoc[]
|
||||
|
||||
@ -17,97 +9,32 @@ include::../../../shared_content/secrets/rationale.adoc[]
|
||||
|
||||
// Optional: Give a general description of the secret and what it's used for.
|
||||
|
||||
include::../../../shared_content/secrets/impact/generic_impact.adoc[]
|
||||
Below are some real-world scenarios that illustrate some impacts of an attacker
|
||||
exploiting the secret.
|
||||
|
||||
// Uncomment the following line, if specifying detailed impacts from below (also make sure to have new lines around the uncommented includes):
|
||||
// include::../../../shared_content/secrets/impact/specific_impact_intro.adoc[]
|
||||
// Set value that can be used to refer to the type of secret in, for example:
|
||||
// "An attacker can use this {secret_type} to ..."
|
||||
:secret_type: secret
|
||||
|
||||
// Secret may allow hosting arbitrary files
|
||||
// include::../../../shared_content/secrets/impact/malware_distribution.adoc[]
|
||||
// Where possible, use predefined content for common impacts. This content can
|
||||
// be found in the folder "shared_content/secrets/impact".
|
||||
// When using predefined content, search for any required variables to be set and include them in this file.
|
||||
// Not adding them will not trigger warnings.
|
||||
|
||||
// Secret may allow accessing or compromising sensitive data
|
||||
// include::../../../shared_content/secrets/impact/data_compromise.adoc[]
|
||||
|
||||
// Secret may allow uploading artifacts to services used elsewhere in the supply chain
|
||||
// This is specific for code and artifact repositories
|
||||
// include::../../../shared_content/secrets/impact/supply_chain_attack.adoc[]
|
||||
|
||||
// Secret may be used to trigger workflows
|
||||
// This is webhook-specific
|
||||
// include::../../../shared_content/secrets/impact/codeless_vulnerability_chaining.adoc[]
|
||||
|
||||
// OAuth tokens may allow accessing 3rd party services
|
||||
// include::../../../shared_content/secrets/impact/oauth_token_compromise.adoc[]
|
||||
|
||||
// Mailing service compromise may allow sending spam, which may result in account termination
|
||||
// include::../../../shared_content/secrets/impact/suspicious_activities_termination.adoc[]
|
||||
|
||||
// Sensitive information leak / identity impersonation, e.g., through leaked signing secret
|
||||
// include::../../../shared_content/secrets/impact/security_downgrade.adoc[]
|
||||
|
||||
// Audit trail discrepancies
|
||||
// include::../../../shared_content/secrets/impact/non_repudiation.adoc[]
|
||||
|
||||
// Package repository secrets may allow access to source code etc.
|
||||
// include::../../../shared_content/secrets/impact/source_code_compromise.adoc[]
|
||||
|
||||
// Spamming automated calls may cause large bills and rate limited service access
|
||||
// include::../../../shared_content/secrets/impact/exceed_rate_limits.adoc[]
|
||||
|
||||
// For blockchain specific tokens
|
||||
// include::../../../shared_content/secrets/impact/blockchain_data_exposure.adoc[]
|
||||
|
||||
// Specific for banking / financial transaction tokens, causing financial loss
|
||||
// include::../../../shared_content/secrets/impact/banking_financial_loss.adoc[]
|
||||
|
||||
// Secret can be used to send spam or phish users
|
||||
// include::../../../shared_content/secrets/impact/phishing.adoc[]
|
||||
|
||||
// Secret may allow modifying application data (object stores etc.)
|
||||
// include::../../../shared_content/secrets/impact/data_modification.adoc[]
|
||||
|
||||
// Specific to services that are used to share PII (personal infos, chat logs, ..)
|
||||
// include::../../../shared_content/secrets/impact/personal_data_compromise.adoc[]
|
||||
|
||||
// Secret may allow accessing financial data, like CC information or confidential financial reports
|
||||
// include::../../../shared_content/secrets/impact/disclosure_of_financial_data.adoc[]
|
||||
|
||||
// Secret may allow occurring financial losses through 3rd party API usage
|
||||
// include::../../../shared_content/secrets/impact/financial_loss.adoc[]
|
||||
|
||||
// Secret may be used to modify dashboards to corrupt shown data
|
||||
// Requires setting service_name variable
|
||||
// :service_name: secret service
|
||||
// include::../../../shared_content/secrets/impact/dataviz_takeover.adoc[]
|
||||
|
||||
// Secret is related to IaaS providers and can be used to change DNS, launch VMs, etc.
|
||||
// Requires setting service_name variable
|
||||
// :service_name: secret service
|
||||
// include::../../../shared_content/secrets/impact/infrastructure_takeover.adoc[]
|
||||
//include::../../../shared_content/secrets/impact/some_impact.adoc[]
|
||||
|
||||
== How to fix it
|
||||
|
||||
// 1. Revoke leaked secrets
|
||||
|
||||
include::../../../shared_content/secrets/fix/revoke.adoc[]
|
||||
|
||||
// 2. Analyze recent use to identify misuse
|
||||
|
||||
include::../../../shared_content/secrets/fix/recent_use.adoc[]
|
||||
|
||||
// 3. Use a secret vault in the future
|
||||
|
||||
include::../../../shared_content/secrets/fix/vault.adoc[]
|
||||
|
||||
// 4. Never hard-code secrets
|
||||
|
||||
include::../../../shared_content/secrets/fix/default.adoc[]
|
||||
|
||||
// OAuth PKCE is very specific to OAuth 2.0
|
||||
// include::../../../shared_content/secrets/fix/oauth_pkce.adoc[]
|
||||
|
||||
=== Code examples
|
||||
|
||||
:example_secret: example_secret_value
|
||||
:example_name: java-property-name
|
||||
:example_env: ENV_VAR_NAME
|
||||
|
||||
include::../../../shared_content/secrets/examples.adoc[]
|
||||
|
||||
//=== How does this work?
|
||||
|
@ -1,28 +1,21 @@
|
||||
import datetime
|
||||
import json
|
||||
import pathlib
|
||||
import random
|
||||
import socket
|
||||
|
||||
import os,io
|
||||
import re
|
||||
import requests
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
from bs4 import BeautifulSoup
|
||||
from socket import timeout
|
||||
import pathlib
|
||||
|
||||
TOLERABLE_LINK_DOWNTIME = datetime.timedelta(days=7)
|
||||
LINK_PROBES_HISTORY_FILE = './link_probes.history'
|
||||
PROBING_COOLDOWN = datetime.timedelta(days=2)
|
||||
PROBING_SPREAD = 60 * 24 # in minutes, 1 day
|
||||
PROBING_COOLDOWN = datetime.timedelta(days=1)
|
||||
PROBING_SPREAD = 100 # minutes
|
||||
link_probes_history = {}
|
||||
|
||||
# These links consistently fail in CI, but work-on-my-machine
|
||||
EXCEPTION_PREFIXES = [
|
||||
# It seems the server certificate was renewed on 2nd of August 2024.
|
||||
# The server is sending only its certificate, without including the
|
||||
# Intermediate certificate used to issue the server cert. Because of that
|
||||
# some application are not able to verify the complete chain of trust.
|
||||
"https://wiki.sei.cmu.edu/",
|
||||
# The CI reports 403 on drupal.org while it works locally.
|
||||
# Maybe the CI's IP is blocklisted...
|
||||
"https://www.drupal.org/",
|
||||
EXCEPTIONS = [
|
||||
]
|
||||
|
||||
def show_files(filenames):
|
||||
@ -72,7 +65,7 @@ def live_url(url: str, timeout=5):
|
||||
req = requests.Request('GET', url, headers = {'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100',
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
|
||||
'Sec-Fetch-Site':'none',
|
||||
'Sec-Fetch-Mode':'navigate',
|
||||
@ -101,13 +94,13 @@ def live_url(url: str, timeout=5):
|
||||
print(f"ERROR: Too many redirects: {rr}")
|
||||
return False
|
||||
except requests.Timeout as t:
|
||||
print(f"ERROR: Request timeout {t}")
|
||||
print(f"ERROR: timeout ", t)
|
||||
return False
|
||||
except socket.timeout as t:
|
||||
print(f"ERROR: Socket timeout {t}")
|
||||
except timeout as t:
|
||||
print(f"ERROR: timeout ", t)
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
print(f"ERROR: ", e)
|
||||
return False
|
||||
|
||||
def findurl_in_html(filename,urls):
|
||||
@ -152,51 +145,20 @@ def get_all_links_from_htmls(dir):
|
||||
print("All html files crawled")
|
||||
return urls
|
||||
|
||||
def url_is_exception(url: str) -> bool:
|
||||
return any(
|
||||
url.startswith(e) for e in EXCEPTION_PREFIXES
|
||||
)
|
||||
|
||||
def probe_links(urls: dict) -> bool:
|
||||
def probe_links(urls):
|
||||
errors = []
|
||||
link_cache_exception = 0
|
||||
link_cache_hit = 0
|
||||
link_cache_miss = 0
|
||||
print("Testing links")
|
||||
link_count = len(urls)
|
||||
for idx, url in enumerate(urls):
|
||||
print(f"[{idx+1}/{link_count}] {url} in {len(urls[url])} files")
|
||||
if url_is_exception(url):
|
||||
link_cache_exception += 1
|
||||
for url in urls:
|
||||
print(f"{url} in {len(urls[url])} files")
|
||||
if url in EXCEPTIONS:
|
||||
print("skip as an exception")
|
||||
elif url_was_reached_recently(url):
|
||||
link_cache_hit += 1
|
||||
print("skip probing because it was reached recently")
|
||||
elif live_url(url, timeout=5):
|
||||
link_cache_miss += 1
|
||||
rejuvenate_url(url)
|
||||
elif url_is_long_dead(url):
|
||||
link_cache_miss += 1
|
||||
errors.append(url)
|
||||
else:
|
||||
link_cache_miss += 1
|
||||
|
||||
confirmed_errors = confirm_errors(errors, urls)
|
||||
|
||||
print(f"\n\n\n{'=' * 80}\n\n\n")
|
||||
if confirmed_errors:
|
||||
report_errors(confirmed_errors, urls)
|
||||
print(f"{len(confirmed_errors)}/{len(urls)} links are dead, see above ^^ the list and the related files\n\n")
|
||||
print("Cache statistics:")
|
||||
print(f"\t{link_cache_hit=}")
|
||||
print(f"\t{link_cache_miss=}")
|
||||
link_cache_hit_ratio = (link_cache_hit) / (link_cache_hit + link_cache_miss)
|
||||
print(f"\t{link_cache_hit_ratio:03.2%} hits")
|
||||
print(f"\t{link_cache_exception=}")
|
||||
print(f"\n\n\n{'=' * 80}\n\n\n")
|
||||
|
||||
success = len(confirmed_errors) == 0
|
||||
return success
|
||||
return errors
|
||||
|
||||
def confirm_errors(presumed_errors, urls):
|
||||
confirmed_errors = []
|
||||
@ -218,9 +180,16 @@ def report_errors(errors, urls):
|
||||
def check_html_links(dir):
|
||||
load_url_probing_history()
|
||||
urls = get_all_links_from_htmls(dir)
|
||||
success = probe_links(urls)
|
||||
if success:
|
||||
errors = probe_links(urls)
|
||||
exit_code = 0
|
||||
if errors:
|
||||
confirmed_errors = confirm_errors(errors, urls)
|
||||
if confirmed_errors:
|
||||
report_errors(confirmed_errors, urls)
|
||||
print(f"{len(confirmed_errors)}/{len(urls)} links are dead, see above ^^ the list and the related files")
|
||||
exit_code = 1
|
||||
if exit_code == 0:
|
||||
print(f"All {len(urls)} links are good")
|
||||
save_url_probing_history()
|
||||
exit(0 if success else 1)
|
||||
exit(exit_code)
|
||||
|
||||
|
@ -1,43 +1,14 @@
|
||||
import collections
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import collections
|
||||
from git import Repo
|
||||
from git import Git
|
||||
from pathlib import Path
|
||||
|
||||
from git import Git, Repo
|
||||
from rspec_tools.utils import load_json, pushd
|
||||
from rspec_tools.utils import (load_json, pushd)
|
||||
|
||||
REPOS = [
|
||||
'sonar-abap',
|
||||
'sonar-apex',
|
||||
'sonar-architecture',
|
||||
'sonar-cobol',
|
||||
'sonar-cpp',
|
||||
'sonar-dart',
|
||||
'sonar-dataflow-bug-detection',
|
||||
'sonar-dotnet-enterprise',
|
||||
'sonar-flex',
|
||||
'sonar-go-enterprise',
|
||||
'sonar-html',
|
||||
'sonar-iac-enterprise',
|
||||
'sonar-java',
|
||||
'SonarJS',
|
||||
'sonar-kotlin',
|
||||
'sonar-php',
|
||||
'sonar-pli',
|
||||
'sonar-plsql',
|
||||
'sonar-python-enterprise',
|
||||
'sonar-rpg',
|
||||
'sonar-ruby',
|
||||
'sonar-scala',
|
||||
'sonar-security',
|
||||
'sonar-swift',
|
||||
'sonar-text-enterprise',
|
||||
'sonar-tsql',
|
||||
'sonar-vb',
|
||||
'sonar-xml'
|
||||
]
|
||||
REPOS = ['sonar-abap','sonar-cpp','sonar-cobol','sonar-dotnet','sonar-css','sonar-flex','slang-enterprise','sonar-java','SonarJS','sonar-php','sonar-pli','sonar-plsql','sonar-python','sonar-rpg','sonar-swift','sonar-text','sonar-tsql','sonar-vb','sonar-html','sonar-xml','sonar-kotlin', 'sonar-secrets', 'sonar-security', 'sonar-dataflow-bug-detection', 'sonar-iac']
|
||||
|
||||
CANONICAL_NAMES = {
|
||||
'CLOUD_FORMATION': 'CLOUDFORMATION',
|
||||
@ -46,14 +17,14 @@ CANONICAL_NAMES = {
|
||||
'WEB': 'HTML'
|
||||
}
|
||||
|
||||
|
||||
RULES_FILENAME = 'covered_rules.json'
|
||||
|
||||
|
||||
def get_rule_id(filename):
|
||||
rule_id = filename[:-5]
|
||||
return rule_id.removesuffix('_abap').removesuffix('_java')
|
||||
|
||||
if '_' in rule_id:
|
||||
return rule_id[:rule_id.find('_')]
|
||||
else:
|
||||
return rule_id
|
||||
|
||||
def compatible_languages(rule, languages_from_sonarpedia):
|
||||
'''
|
||||
@ -72,7 +43,7 @@ def get_implemented_rules(path, languages_from_sonarpedia):
|
||||
for lang in languages_from_sonarpedia:
|
||||
implemented_rules[lang] = []
|
||||
for filename in os.listdir(path):
|
||||
if filename.endswith(".json") and 'profile' not in filename:
|
||||
if filename.endswith(".json") and not filename.startswith("Sonar_way"):
|
||||
rule = load_json(os.path.join(path, filename))
|
||||
rule_id = get_rule_id(filename)
|
||||
for language in compatible_languages(rule, languages_from_sonarpedia):
|
||||
@ -184,29 +155,17 @@ def checkout_repo(repo):
|
||||
git_url=f"https://github.com/SonarSource/{repo}"
|
||||
token=os.getenv('GITHUB_TOKEN')
|
||||
if token:
|
||||
git_url=f"https://oauth2:{token}@github.com/SonarSource/{repo}"
|
||||
git_url=f"https://{token}@github.com/SonarSource/{repo}"
|
||||
if not os.path.exists(repo):
|
||||
return Repo.clone_from(git_url, repo)
|
||||
else:
|
||||
return Repo(repo)
|
||||
|
||||
|
||||
VERSION_RE = re.compile(r'\d[\d\.]+')
|
||||
def is_version_tag(name):
|
||||
return bool(re.fullmatch(VERSION_RE, name))
|
||||
|
||||
|
||||
def comparable_version(key):
|
||||
if not is_version_tag(key):
|
||||
return [0]
|
||||
return list(map(int, key.split('.')))
|
||||
|
||||
|
||||
def collect_coverage_for_all_versions(repo, coverage):
|
||||
git_repo = checkout_repo(repo)
|
||||
tags = git_repo.tags
|
||||
versions = [tag.name for tag in tags if is_version_tag(tag.name)]
|
||||
versions.sort(key = comparable_version)
|
||||
tags.sort(key = lambda t: t.commit.committed_date)
|
||||
versions = [tag.name for tag in tags if '-' not in tag.name]
|
||||
for version in versions:
|
||||
collect_coverage_for_version(repo, git_repo, version, coverage)
|
||||
collect_coverage_for_version(repo, git_repo, 'master', coverage)
|
||||
|
@ -19,7 +19,7 @@ LANG_TO_LABEL = {'abap': 'abap',
|
||||
'dart': 'dart',
|
||||
'docker': 'iac',
|
||||
'flex': 'flex',
|
||||
'go': 'go',
|
||||
'go': 'slang',
|
||||
'html': 'html',
|
||||
'java': 'java',
|
||||
'javascript': 'jsts',
|
||||
@ -40,7 +40,6 @@ LANG_TO_LABEL = {'abap': 'abap',
|
||||
'tsql': 'tsql',
|
||||
'vb6': 'vb6',
|
||||
'vbnet': 'dotnet',
|
||||
'ansible': 'iac',
|
||||
'cloudformation': 'iac',
|
||||
'terraform': 'iac',
|
||||
'kubernetes': 'iac',
|
||||
@ -77,7 +76,6 @@ LANG_TO_SOURCE = {
|
||||
'c': 'c',
|
||||
'objectivec': 'objectivec',
|
||||
'vb': 'vb',
|
||||
'ansible': 'yaml',
|
||||
# these languages are not supported by highlight.js as the moment:
|
||||
'apex': 'apex',
|
||||
'azureresourcemanager': 'bicep',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, Final, List, Union
|
||||
from typing import Final, Dict, List
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from rspec_tools.errors import RuleValidationError
|
||||
@ -78,26 +78,15 @@ def intersection(list1, list2):
|
||||
def difference(list1, list2):
|
||||
return list(set(list1) - set(list2))
|
||||
|
||||
def validate_titles_are_not_misclassified_as_subtitles(rule_language: LanguageSpecificRule, subtitles: list[str], allowed_h2_sections: list[str]):
|
||||
# TODO This does not validate "How to fix it" section for frameworks as the section names are a bit special.
|
||||
misclassified = intersection(subtitles, allowed_h2_sections)
|
||||
if misclassified:
|
||||
misclassified.sort()
|
||||
misclassified_str = ', '.join(misclassified)
|
||||
raise RuleValidationError(f'Rule {rule_language.id} has some sections misclassified. Ensure there are not too many `=` in the asciidoc file for: {misclassified_str}')
|
||||
|
||||
def validate_section_names(rule_language: LanguageSpecificRule):
|
||||
"""Validates all h2-level section names"""
|
||||
def get_titles(level: Union[str, list[str]]) -> list[str]:
|
||||
return list(map(lambda x: x.text.strip(), rule_language.description.find_all(level)))
|
||||
|
||||
h2_titles = get_titles('h2')
|
||||
subtitles = get_titles(['h3', 'h4', 'h5', 'h6'])
|
||||
allowed_h2_sections = list(MANDATORY_SECTIONS) + list(OPTIONAL_SECTIONS.keys())
|
||||
validate_titles_are_not_misclassified_as_subtitles(rule_language, subtitles, allowed_h2_sections)
|
||||
descr = rule_language.description
|
||||
h2_titles = list(map(lambda x: x.text.strip(), descr.find_all('h2')))
|
||||
|
||||
validate_duplications(h2_titles, rule_language)
|
||||
|
||||
education_titles = intersection(h2_titles, allowed_h2_sections)
|
||||
education_titles = intersection(h2_titles, list(MANDATORY_SECTIONS) + list(OPTIONAL_SECTIONS.keys()))
|
||||
if education_titles:
|
||||
# Using the education format.
|
||||
validate_how_to_fix_it_sections_names(rule_language, h2_titles)
|
||||
@ -245,7 +234,7 @@ def validate_security_standard_links(rule_language: LanguageSpecificRule):
|
||||
# Avoid raising mismatch issues on deprecated or closed rules
|
||||
if metadata.get('status') != 'ready':
|
||||
return
|
||||
|
||||
|
||||
security_standards_metadata = metadata.get('securityStandards', {})
|
||||
for standard in SECURITY_STANDARD_URL.keys():
|
||||
|
||||
@ -255,7 +244,7 @@ def validate_security_standard_links(rule_language: LanguageSpecificRule):
|
||||
extra_links = difference(links_mapping, metadata_mapping)
|
||||
if len(extra_links) > 0:
|
||||
raise RuleValidationError(f'Rule {rule_language.id} has a mismatch for the {standard} security standards. Remove links from the Resources/See section ({extra_links}) or fix the rule metadata')
|
||||
|
||||
|
||||
missing_links = difference(metadata_mapping, links_mapping)
|
||||
if len(missing_links) > 0:
|
||||
raise RuleValidationError(f'Rule {rule_language.id} has a mismatch for the {standard} security standards. Add links to the Resources/See section ({missing_links}) or fix the rule metadata')
|
||||
|
@ -156,15 +156,6 @@
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"OWASP Mobile Top 10 2024": {
|
||||
"type": "array",
|
||||
"minItems": 0,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^M([1-9]|10)$"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"PCI DSS 3.2": {
|
||||
"type": "array",
|
||||
"minItems": 0,
|
||||
@ -228,7 +219,7 @@
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"STIG ASD_V5R3": {
|
||||
"STIG ASD 2023-06-08": {
|
||||
"type": "array",
|
||||
"minItems": 0,
|
||||
"items": {
|
||||
@ -276,15 +267,15 @@
|
||||
"properties": {
|
||||
"MAINTAINABILITY": {
|
||||
"type": "string",
|
||||
"enum": ["INFO", "LOW", "MEDIUM", "HIGH", "BLOCKER"]
|
||||
"enum": ["LOW", "MEDIUM", "HIGH"]
|
||||
},
|
||||
"RELIABILITY": {
|
||||
"type": "string",
|
||||
"enum": ["INFO", "LOW", "MEDIUM", "HIGH", "BLOCKER"]
|
||||
"enum": ["LOW", "MEDIUM", "HIGH"]
|
||||
},
|
||||
"SECURITY": {
|
||||
"type": "string",
|
||||
"enum": ["INFO", "LOW", "MEDIUM", "HIGH", "BLOCKER"]
|
||||
"enum": ["LOW", "MEDIUM", "HIGH"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"title": "Function names should comply with a naming convention",
|
||||
"defaultQualityProfiles": [
|
||||
|
||||
]
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
== Why is this an issue?
|
||||
|
||||
=== How to fix it
|
||||
|
||||
=== Resources
|
@ -1,457 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Asciidoctor 1.5.8">
|
||||
<title>Why is this an issue?</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
||||
<style>
|
||||
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
|
||||
/* Uncomment @import statement below to use as custom stylesheet */
|
||||
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
|
||||
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
|
||||
audio,canvas,video{display:inline-block}
|
||||
audio:not([controls]){display:none;height:0}
|
||||
script{display:none!important}
|
||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
|
||||
a{background:transparent}
|
||||
a:focus{outline:thin dotted}
|
||||
a:active,a:hover{outline:0}
|
||||
h1{font-size:2em;margin:.67em 0}
|
||||
abbr[title]{border-bottom:1px dotted}
|
||||
b,strong{font-weight:bold}
|
||||
dfn{font-style:italic}
|
||||
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
|
||||
mark{background:#ff0;color:#000}
|
||||
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||||
pre{white-space:pre-wrap}
|
||||
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||||
small{font-size:80%}
|
||||
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||
sup{top:-.5em}
|
||||
sub{bottom:-.25em}
|
||||
img{border:0}
|
||||
svg:not(:root){overflow:hidden}
|
||||
figure{margin:0}
|
||||
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||||
legend{border:0;padding:0}
|
||||
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||||
button,input{line-height:normal}
|
||||
button,select{text-transform:none}
|
||||
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
|
||||
button[disabled],html input[disabled]{cursor:default}
|
||||
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
|
||||
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||
textarea{overflow:auto;vertical-align:top}
|
||||
table{border-collapse:collapse;border-spacing:0}
|
||||
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||||
html,body{font-size:100%}
|
||||
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||||
a:hover{cursor:pointer}
|
||||
img,object,embed{max-width:100%;height:auto}
|
||||
object,embed{height:100%}
|
||||
img{-ms-interpolation-mode:bicubic}
|
||||
.left{float:left!important}
|
||||
.right{float:right!important}
|
||||
.text-left{text-align:left!important}
|
||||
.text-right{text-align:right!important}
|
||||
.text-center{text-align:center!important}
|
||||
.text-justify{text-align:justify!important}
|
||||
.hide{display:none}
|
||||
img,object,svg{display:inline-block;vertical-align:middle}
|
||||
textarea{height:auto;min-height:50px}
|
||||
select{width:100%}
|
||||
.center{margin-left:auto;margin-right:auto}
|
||||
.stretch{width:100%}
|
||||
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||||
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
|
||||
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||||
a:hover,a:focus{color:#1d4b8f}
|
||||
a img{border:none}
|
||||
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||||
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||||
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||||
h1{font-size:2.125em}
|
||||
h2{font-size:1.6875em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||||
h4,h5{font-size:1.125em}
|
||||
h6{font-size:1em}
|
||||
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
|
||||
em,i{font-style:italic;line-height:inherit}
|
||||
strong,b{font-weight:bold;line-height:inherit}
|
||||
small{font-size:60%;line-height:inherit}
|
||||
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||||
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||||
ul,ol{margin-left:1.5em}
|
||||
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
|
||||
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
|
||||
ul.square{list-style-type:square}
|
||||
ul.circle{list-style-type:circle}
|
||||
ul.disc{list-style-type:disc}
|
||||
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||||
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||||
dl dd{margin-bottom:1.25em}
|
||||
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
|
||||
abbr{text-transform:none}
|
||||
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||||
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
|
||||
blockquote cite::before{content:"\2014 \0020"}
|
||||
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
|
||||
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||||
h1{font-size:2.75em}
|
||||
h2{font-size:2.3125em}
|
||||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||||
h4{font-size:1.4375em}}
|
||||
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
|
||||
table thead,table tfoot{background:#f7f8f7}
|
||||
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||||
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
|
||||
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
|
||||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||||
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||||
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||||
.clearfix::after,.float-group::after{clear:both}
|
||||
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
|
||||
*:not(pre)>code.nobreak{word-wrap:normal}
|
||||
*:not(pre)>code.nowrap{white-space:nowrap}
|
||||
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
|
||||
em em{font-style:normal}
|
||||
strong strong{font-weight:400}
|
||||
.keyseq{color:rgba(51,51,51,.8)}
|
||||
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||
.keyseq kbd:first-child{margin-left:0}
|
||||
.keyseq kbd:last-child{margin-right:0}
|
||||
.menuseq,.menuref{color:#000}
|
||||
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||||
.menuseq{word-spacing:-.02em}
|
||||
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||||
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||||
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||||
b.button::before{content:"[";padding:0 3px 0 2px}
|
||||
b.button::after{content:"]";padding:0 2px 0 3px}
|
||||
p a>code:hover{color:rgba(0,0,0,.9)}
|
||||
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||||
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||||
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||||
#content{margin-top:1.25em}
|
||||
#content::before{content:none}
|
||||
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||||
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
||||
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||||
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
|
||||
#header .details span:first-child{margin-left:-.125em}
|
||||
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||||
#header .details br{display:none}
|
||||
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||||
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||||
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||||
#header #revnumber{text-transform:capitalize}
|
||||
#header #revnumber::after{content:"\00a0"}
|
||||
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||||
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
||||
#toc>ul{margin-left:.125em}
|
||||
#toc ul.sectlevel0>li>a{font-style:italic}
|
||||
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||||
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||||
#toc li{line-height:1.3334;margin-top:.3334em}
|
||||
#toc a{text-decoration:none}
|
||||
#toc a:active{text-decoration:underline}
|
||||
#toctitle{color:#7a2518;font-size:1.2em}
|
||||
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||||
body.toc2{padding-left:15em;padding-right:0}
|
||||
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||||
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||||
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||||
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
||||
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||||
#toc.toc2{width:20em}
|
||||
#toc.toc2 #toctitle{font-size:1.375em}
|
||||
#toc.toc2>ul{font-size:.95em}
|
||||
#toc.toc2 ul ul{padding-left:1.25em}
|
||||
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||||
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||||
#content #toc>:first-child{margin-top:0}
|
||||
#content #toc>:last-child{margin-bottom:0}
|
||||
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
|
||||
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
|
||||
#content{margin-bottom:.625em}
|
||||
.sect1{padding-bottom:.625em}
|
||||
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||||
.sect1{padding-bottom:1.25em}}
|
||||
.sect1:last-child{padding-bottom:0}
|
||||
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
||||
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||||
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||||
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||||
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||||
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||||
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||||
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||||
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||||
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||||
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
|
||||
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||||
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||||
.admonitionblock>table td.icon img{max-width:none}
|
||||
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||||
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
|
||||
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||||
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
|
||||
.exampleblock>.content>:first-child{margin-top:0}
|
||||
.exampleblock>.content>:last-child{margin-bottom:0}
|
||||
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||||
.sidebarblock>:first-child{margin-top:0}
|
||||
.sidebarblock>:last-child{margin-bottom:0}
|
||||
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||||
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
|
||||
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
|
||||
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
|
||||
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
|
||||
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
|
||||
.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal}
|
||||
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
|
||||
.listingblock pre.highlightjs{padding:0}
|
||||
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
|
||||
.listingblock pre.prettyprint{border-width:0}
|
||||
.listingblock>.content{position:relative}
|
||||
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
|
||||
.listingblock:hover code[data-lang]::before{display:block}
|
||||
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
|
||||
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||||
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||||
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
|
||||
table.pyhltable td.code{padding-left:.75em;padding-right:0}
|
||||
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf}
|
||||
pre.pygments .lineno{display:inline-block;margin-right:.25em}
|
||||
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
|
||||
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||||
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||||
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||||
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||||
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||||
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||||
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
||||
.verseblock{margin:0 1em 1.25em}
|
||||
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||
.verseblock pre strong{font-weight:400}
|
||||
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||||
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||||
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||||
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||||
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
||||
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
||||
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||||
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||||
.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
||||
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
||||
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
|
||||
table.tableblock{max-width:100%;border-collapse:separate}
|
||||
p.tableblock:last-child{margin-bottom:0}
|
||||
td.tableblock>.content{margin-bottom:-1.25em}
|
||||
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||||
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
|
||||
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
|
||||
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
|
||||
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
|
||||
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
|
||||
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
|
||||
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
|
||||
table.frame-all{border-width:1px}
|
||||
table.frame-sides{border-width:0 1px}
|
||||
table.frame-topbot,table.frame-ends{border-width:1px 0}
|
||||
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
|
||||
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
|
||||
th.halign-left,td.halign-left{text-align:left}
|
||||
th.halign-right,td.halign-right{text-align:right}
|
||||
th.halign-center,td.halign-center{text-align:center}
|
||||
th.valign-top,td.valign-top{vertical-align:top}
|
||||
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||||
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||||
table thead th,table tfoot th{font-weight:bold}
|
||||
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
|
||||
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||||
p.tableblock>code:only-child{background:none;padding:0}
|
||||
p.tableblock{font-size:1em}
|
||||
td>div.verse{white-space:pre}
|
||||
ol{margin-left:1.75em}
|
||||
ul li ol{margin-left:1.5em}
|
||||
dl dd{margin-left:1.125em}
|
||||
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||||
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||||
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||||
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||||
ul.unstyled,ol.unstyled{margin-left:0}
|
||||
ul.checklist{margin-left:.625em}
|
||||
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||||
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
|
||||
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||||
ul.inline>li{margin-left:1.25em}
|
||||
.unstyled dl dt{font-weight:400;font-style:normal}
|
||||
ol.arabic{list-style-type:decimal}
|
||||
ol.decimal{list-style-type:decimal-leading-zero}
|
||||
ol.loweralpha{list-style-type:lower-alpha}
|
||||
ol.upperalpha{list-style-type:upper-alpha}
|
||||
ol.lowerroman{list-style-type:lower-roman}
|
||||
ol.upperroman{list-style-type:upper-roman}
|
||||
ol.lowergreek{list-style-type:lower-greek}
|
||||
.hdlist>table,.colist>table{border:0;background:none}
|
||||
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||||
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||||
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||||
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||||
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||||
.colist td:not([class]):first-child img{max-width:none}
|
||||
.colist td:not([class]):last-child{padding:.25em 0}
|
||||
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
|
||||
.imageblock.left{margin:.25em .625em 1.25em 0}
|
||||
.imageblock.right{margin:.25em 0 1.25em .625em}
|
||||
.imageblock>.title{margin-bottom:0}
|
||||
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||||
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||||
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||||
.image.left{margin-right:.625em}
|
||||
.image.right{margin-left:.625em}
|
||||
a.image{text-decoration:none;display:inline-block}
|
||||
a.image object{pointer-events:none}
|
||||
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||||
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
||||
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||||
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||||
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||||
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||||
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||||
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||||
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
|
||||
.gist .file-data>table td.line-data{width:99%}
|
||||
div.unbreakable{page-break-inside:avoid}
|
||||
.big{font-size:larger}
|
||||
.small{font-size:smaller}
|
||||
.underline{text-decoration:underline}
|
||||
.overline{text-decoration:overline}
|
||||
.line-through{text-decoration:line-through}
|
||||
.aqua{color:#00bfbf}
|
||||
.aqua-background{background-color:#00fafa}
|
||||
.black{color:#000}
|
||||
.black-background{background-color:#000}
|
||||
.blue{color:#0000bf}
|
||||
.blue-background{background-color:#0000fa}
|
||||
.fuchsia{color:#bf00bf}
|
||||
.fuchsia-background{background-color:#fa00fa}
|
||||
.gray{color:#606060}
|
||||
.gray-background{background-color:#7d7d7d}
|
||||
.green{color:#006000}
|
||||
.green-background{background-color:#007d00}
|
||||
.lime{color:#00bf00}
|
||||
.lime-background{background-color:#00fa00}
|
||||
.maroon{color:#600000}
|
||||
.maroon-background{background-color:#7d0000}
|
||||
.navy{color:#000060}
|
||||
.navy-background{background-color:#00007d}
|
||||
.olive{color:#606000}
|
||||
.olive-background{background-color:#7d7d00}
|
||||
.purple{color:#600060}
|
||||
.purple-background{background-color:#7d007d}
|
||||
.red{color:#bf0000}
|
||||
.red-background{background-color:#fa0000}
|
||||
.silver{color:#909090}
|
||||
.silver-background{background-color:#bcbcbc}
|
||||
.teal{color:#006060}
|
||||
.teal-background{background-color:#007d7d}
|
||||
.white{color:#bfbfbf}
|
||||
.white-background{background-color:#fafafa}
|
||||
.yellow{color:#bfbf00}
|
||||
.yellow-background{background-color:#fafa00}
|
||||
span.icon>.fa{cursor:default}
|
||||
a span.icon>.fa{cursor:inherit}
|
||||
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||||
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||||
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||||
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||||
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||||
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||||
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||
.conum[data-value] *{color:#fff!important}
|
||||
.conum[data-value]+b{display:none}
|
||||
.conum[data-value]::after{content:attr(data-value)}
|
||||
pre .conum[data-value]{position:relative;top:-.125em}
|
||||
b.conum *{color:inherit!important}
|
||||
.conum:not([data-value]):empty{display:none}
|
||||
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||||
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
|
||||
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||||
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
|
||||
p{margin-bottom:1.25rem}
|
||||
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||||
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||||
.print-only{display:none!important}
|
||||
@page{margin:1.25cm .75cm}
|
||||
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
|
||||
html{font-size:80%}
|
||||
a{color:inherit!important;text-decoration:underline!important}
|
||||
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||||
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||||
abbr[title]::after{content:" (" attr(title) ")"}
|
||||
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||||
thead{display:table-header-group}
|
||||
svg{max-width:100%}
|
||||
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||||
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||||
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||||
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
||||
body.book #header{text-align:center}
|
||||
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||||
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||||
body.book #header .details span:first-child{margin-left:0!important}
|
||||
body.book #header .details br{display:block}
|
||||
body.book #header .details br+span::before{content:none!important}
|
||||
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||||
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||||
.listingblock code[data-lang]::before{display:block}
|
||||
#footer{padding:0 .9375em}
|
||||
.hide-on-print{display:none!important}
|
||||
.print-only{display:block!important}
|
||||
.hide-for-print{display:none!important}
|
||||
.show-for-print{display:inherit!important}}
|
||||
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
|
||||
.sect1{padding:0!important}
|
||||
.sect1+.sect1{border:0}
|
||||
#footer{background:none}
|
||||
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||||
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||||
</style>
|
||||
</head>
|
||||
<body class="article">
|
||||
<div id="header">
|
||||
</div>
|
||||
<div id="content">
|
||||
<div class="sect1">
|
||||
<h2 id="_why_is_this_an_issue">Why is this an issue?</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="_how_to_fix_it">How to fix it</h3>
|
||||
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="_resources">Resources</h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2024-10-10 12:53:12 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -39,11 +39,6 @@ def test_unexpected_section_fails_validation(invalid_rule):
|
||||
with pytest.raises(RuleValidationError, match=fr'^Rule {rule.id} has an unconventional header "Invalid header"'):
|
||||
validate_section_names(rule)
|
||||
|
||||
def test_sections_with_wrong_level_fails_validation(invalid_rule):
|
||||
rule = invalid_rule('S100', 'php')
|
||||
with pytest.raises(RuleValidationError, match=fr'^Rule {rule.id} has some sections misclassified. Ensure there are not too many `=` in the asciidoc file for: How to fix it, Resources'):
|
||||
validate_section_names(rule)
|
||||
|
||||
def test_valid_section_levels_passes_validation(rule_language):
|
||||
'''Check that description with correct formatting is considered valid.'''
|
||||
validate_section_levels(rule_language('S100', 'cfamily'))
|
||||
|
@ -82,7 +82,7 @@ def test_rule_with_invalid_impacts(invalid_rules: RulesRepository):
|
||||
|
||||
def test_rule_with_invalid_impact_level(invalid_rules: RulesRepository):
|
||||
s506 = invalid_rules.get_rule('S506')
|
||||
with pytest.raises(RuleValidationError, match=re.escape("Rule S506 failed validation for these reasons:\n - Rule scala:S506 has invalid metadata in MAINTAINABILITY: 'INVALID' is not one of ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'BLOCKER']")):
|
||||
with pytest.raises(RuleValidationError, match=re.escape("Rule S506 failed validation for these reasons:\n - Rule scala:S506 has invalid metadata in MAINTAINABILITY: 'INVALID' is not one of ['LOW', 'MEDIUM', 'HIGH']")):
|
||||
validate_rule_metadata(s506)
|
||||
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
{
|
||||
"title": "Function and method names should comply with a naming convention",
|
||||
"defaultQualityProfiles": [],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ include::../rule.adoc[]
|
||||
|
||||
For example, with the default provided regular expression ``++^[a-z][a-zA-Z0-9]*$++``, the function:
|
||||
|
||||
[source,php,diff-id=1,diff-type=noncompliant]
|
||||
[source,php]
|
||||
----
|
||||
function DoSomething(){ // Noncompliant
|
||||
// ...
|
||||
@ -11,31 +11,13 @@ function DoSomething(){ // Noncompliant
|
||||
|
||||
should be renamed to
|
||||
|
||||
[source,php,diff-id=1,diff-type=compliant]
|
||||
[source,php]
|
||||
----
|
||||
function doSomething(){
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
In case the Drupal framework is detected and the default regex is not replaced, it will follow the PHP coding standards for Drupal.
|
||||
|
||||
[source,php,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
function doSomething(){ // Noncompliant
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
should be renamed to
|
||||
|
||||
[source,php,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
function do_something(){
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
=== Exceptions
|
||||
|
||||
Methods with an ``++@inheritdoc++`` annotation, as well as magic methods (``++__construct()++``, ``++__destruct()++``, ``++__call()++``, ``++__callStatic()++``, ``++__get()++``, ``++__set()++``, ``++__isset()++``, ``++__unset()++``, ``++__sleep()++``, ``++__wakeup()++``, ``++__toString()++``, ``++__invoke()++``, ``++__set_state()++``, ``++__clone()++``, ``++__debugInfo()++``) are ignored.
|
||||
@ -52,10 +34,6 @@ function __destruct(){...} // Compliant by exception
|
||||
function myFunc(){...} // Compliant by exception
|
||||
----
|
||||
|
||||
== References
|
||||
|
||||
* https://www.drupal.org/docs/develop/standards/php/php-coding-standards#s-functions-and-variables[Drupal - Naming Conventions - Functions and variables]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
|
@ -1,6 +1,6 @@
|
||||
== Why is this an issue?
|
||||
|
||||
Shared naming conventions allow teams to collaborate efficiently. In Dart, the convention is that all type names should be in camel-case starting with a capital letter (aka Pascal case).
|
||||
Shared naming conventions allow teams to collaborate efficiently. In Dart the convention is that all type names should be in camel-case starting with a capital letter (aka Pascal case).
|
||||
|
||||
This rule raises an issue when a class name does not comply with this convention.
|
||||
|
||||
@ -12,45 +12,18 @@ This rule raises an issue when a class name does not comply with this convention
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
class My_Class { } // Noncompliant: contains a dash
|
||||
class myClass { } // Noncompliant: starts with a lowercase
|
||||
class myclass { } // Noncompliant: all in lowercase
|
||||
class My_Class // Noncompliant,contains dash
|
||||
class myClass // Noncompliant, starts with lovercase
|
||||
class myclass // Noncompliant, all in lowercase
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
class MyClass { }
|
||||
class MyClass
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
* Dart Docs - https://dart.dev/tools/linter-rules/camel_case_types[Dart Linter rule - camel_case_types]
|
||||
|
||||
=== Related rules
|
||||
|
||||
* S7046 - Extension identifiers should comply with a naming convention
|
||||
* S7075 - Non-constant names should comply with a naming convention
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
* The type name '<typeName>' isn't an UpperCamelCase identifier.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The type name (without generic parameters, or representation type declaration).
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
||||
* https://dart.dev/tools/linter-rules/camel_case_types[Dart Lint rule]
|
||||
|
@ -2,9 +2,5 @@
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -2,9 +2,5 @@
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": [],
|
||||
"status": "deprecated",
|
||||
"tags": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": []
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"type": "CODE_SMELL",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "BLOCKER"
|
||||
"MAINTAINABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "CLEAR"
|
||||
},
|
||||
@ -17,13 +17,19 @@
|
||||
"based-on-misra"
|
||||
],
|
||||
"extra": {
|
||||
"replacementRules": [],
|
||||
"legacyKeys": []
|
||||
"replacementRules": [
|
||||
|
||||
],
|
||||
"legacyKeys": [
|
||||
|
||||
]
|
||||
},
|
||||
"defaultSeverity": "Blocker",
|
||||
"ruleSpecification": "RSPEC-1032",
|
||||
"sqKey": "S1032",
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": [],
|
||||
"defaultQualityProfiles": [
|
||||
|
||||
],
|
||||
"quickfix": "unknown"
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"type": "CODE_SMELL",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "BLOCKER"
|
||||
"MAINTAINABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "CLEAR"
|
||||
},
|
||||
@ -19,8 +19,12 @@
|
||||
"pitfall"
|
||||
],
|
||||
"extra": {
|
||||
"replacementRules": [],
|
||||
"legacyKeys": []
|
||||
"replacementRules": [
|
||||
|
||||
],
|
||||
"legacyKeys": [
|
||||
|
||||
]
|
||||
},
|
||||
"defaultSeverity": "Blocker",
|
||||
"ruleSpecification": "RSPEC-1036",
|
||||
|
@ -1,7 +1,3 @@
|
||||
{
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
{
|
||||
"title": "All \"except\" blocks should be able to catch exceptions",
|
||||
"tags": [
|
||||
"suspicious"
|
||||
]
|
||||
"title": "All \"except\" blocks should be able to catch exceptions"
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"title": "Finalizers should not throw exceptions",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "BLOCKER"
|
||||
"RELIABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "LOGICAL"
|
||||
},
|
||||
|
@ -2,7 +2,7 @@
|
||||
"title": "Finalize method should not throw exceptions",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "BLOCKER"
|
||||
"RELIABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "LOGICAL"
|
||||
},
|
||||
|
@ -18,8 +18,8 @@ void foo () // no exceptions specified
|
||||
throw ( 21 ); // anything can be thrown
|
||||
}
|
||||
|
||||
void goo ( ) throw ( Exception )
|
||||
{
|
||||
void goo ( ) throw ( Exception )
|
||||
{
|
||||
foo ( ); // Noncompliant; an int could be thrown
|
||||
}
|
||||
----
|
||||
@ -34,8 +34,8 @@ void foo () // no exceptions specified
|
||||
throw ( 21 ); // this is legal; anything can be thrown
|
||||
}
|
||||
|
||||
void goo ( ) throw ( Exception, int )
|
||||
{
|
||||
void goo ( ) throw ( Exception, int )
|
||||
{
|
||||
foo ( );
|
||||
}
|
||||
----
|
||||
@ -45,6 +45,7 @@ void goo ( ) throw ( Exception, int )
|
||||
|
||||
* MISRA {cpp}:2008, 15-5-2
|
||||
* CWE - https://cwe.mitre.org/data/definitions/391[CWE-391 - Unchecked Error Condition]
|
||||
* https://www.securecoding.cert.org/confluence/x/EADTAQ[CERT, ERR55-CPP.] - Honor exception specifications
|
||||
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
@ -2,9 +2,5 @@
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": [],
|
||||
"status": "deprecated",
|
||||
"tags": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": []
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"type": "BUG",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "BLOCKER"
|
||||
"RELIABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "COMPLETE"
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
"type": "BUG",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "BLOCKER"
|
||||
"RELIABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "LOGICAL"
|
||||
},
|
||||
@ -12,9 +12,13 @@
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "30min"
|
||||
},
|
||||
"tags": [],
|
||||
"tags": [
|
||||
|
||||
],
|
||||
"extra": {
|
||||
"replacementRules": [],
|
||||
"replacementRules": [
|
||||
|
||||
],
|
||||
"legacyKeys": [
|
||||
"PipelinedFunctionsWithoutPipeRow"
|
||||
]
|
||||
|
@ -1,5 +1,3 @@
|
||||
{
|
||||
"defaultQualityProfiles": [
|
||||
|
||||
]
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
:language_std_outputs: print
|
||||
:language_std_outputs: std::cout, std::cerr, printf, std::print
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
@ -8,9 +8,9 @@ If you are using Flutter, you can use `debugPrint` or surround print calls with
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
The following noncompliant code:
|
||||
|
||||
[source,dart]
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
void doSomething(int x) {
|
||||
// ...
|
||||
@ -19,11 +19,12 @@ void doSomething(int x) {
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
Could be replaced by:
|
||||
|
||||
[source,dart]
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
void doSomething(int x) {
|
||||
void doSomething(int x)
|
||||
{
|
||||
// ...
|
||||
debugPrint('debug: $x');
|
||||
// ...
|
||||
@ -32,9 +33,10 @@ void doSomething(int x) {
|
||||
|
||||
or
|
||||
|
||||
[source,dart]
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
void doSomething(int x) {
|
||||
void doSomething(int x)
|
||||
{
|
||||
// ...
|
||||
if (kDebugMode) {
|
||||
print('debug: $x');
|
||||
@ -45,9 +47,10 @@ void doSomething(int x) {
|
||||
|
||||
or
|
||||
|
||||
[source,dart]
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
void doSomething(int x) {
|
||||
void doSomething(int x)
|
||||
{
|
||||
// ...
|
||||
log('log: $x');
|
||||
// ...
|
||||
@ -58,27 +61,4 @@ void doSomething(int x) {
|
||||
|
||||
* OWASP - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/[Top 10 2021 Category A9 - Security Logging and Monitoring Failures]
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure[Top 10 2017 Category A3 - Sensitive Data Exposure]
|
||||
* Dart Docs - https://dart.dev/tools/linter-rules/avoid_print[Dart Linter rule - avoid_print]
|
||||
* Flutter API Docs - https://api.flutter.dev/flutter/foundation/kDebugMode-constant.html[kDebugMode top-level constant]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
* Don't invoke 'print' in production code.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The identifier of the `print` method, without argument list.
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
||||
* Dart Linter - https://dart.dev/tools/linter-rules/avoid_print[Dart Linter - avoid_print]
|
||||
|
@ -3,9 +3,7 @@
|
||||
"bad-practice",
|
||||
"user-experience"
|
||||
],
|
||||
"defaultQualityProfiles": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
"defaultQualityProfiles": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"defaultQualityProfiles": [],
|
||||
"tags": [
|
||||
"bad-practice",
|
||||
"clippy"
|
||||
]
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
:language_std_outputs: print!, println!
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,rust,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
fn do_something() {
|
||||
println!("my message"); // Noncompliant, output directly to stdout without a logger
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,rust,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
use log::{info, LevelFilter};
|
||||
use simple_logger::SimpleLogger;
|
||||
|
||||
fn do_something() {
|
||||
SimpleLogger::new().with_level(LevelFilter::Info).init().unwrap();
|
||||
// ...
|
||||
info!("my message"); // Compliant, output via logger
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* Clippy Lints - https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout
|
||||
* OWASP - https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/[Top 10 2021 Category A9 - Security Logging and Monitoring Failures]
|
||||
* OWASP - https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure[Top 10 2017 Category A3 - Sensitive Data Exposure]
|
@ -4,7 +4,7 @@ include::../description.adoc[]
|
||||
|
||||
=== Noncompliant code example
|
||||
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
[source,dart]
|
||||
----
|
||||
void foo() {
|
||||
outer: //label is not used.
|
||||
@ -16,7 +16,7 @@ void foo() {
|
||||
|
||||
=== Compliant solution
|
||||
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
[source,dart]
|
||||
----
|
||||
void foo() {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
@ -27,31 +27,5 @@ void foo() {
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* CERT - https://wiki.sei.cmu.edu/confluence/x/5dUxBQ[CERT, MSC12-C.] - Detect and remove code that has no effect or is never executed
|
||||
* Dart Docs - https://dart.dev/tools/diagnostic-messages?utm_source=dartdev&utm_medium=redir&utm_id=diagcode&utm_content=unnecessary_cast#unused_label[Dart Linter rule - unused_label]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
* The label '<labelName>' isn't used.
|
||||
|
||||
`<labelName>` doesn't include the semicolon.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The label name, including the semicolon.
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
||||
* https://wiki.sei.cmu.edu/confluence/x/5dUxBQ[CERT, MSC12-C.] - Detect and remove code that has no effect or is never executed
|
||||
* https://dart.dev/tools/diagnostic-messages?utm_source=dartdev&utm_medium=redir&utm_id=diagcode&utm_content=unnecessary_cast#unused_label[Dart Linter - unused label]
|
@ -1,8 +1,4 @@
|
||||
{
|
||||
"defaultQualityProfiles": [],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
{
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
{
|
||||
"title": "Unused private class members should be removed",
|
||||
"quickfix": "covered",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
"title": "Unused private class members should be removed",
|
||||
"quickfix": "covered"
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
"type": "CODE_SMELL",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "BLOCKER"
|
||||
"MAINTAINABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "CONVENTIONAL"
|
||||
},
|
||||
@ -17,8 +17,12 @@
|
||||
"sql"
|
||||
],
|
||||
"extra": {
|
||||
"replacementRules": [],
|
||||
"legacyKeys": []
|
||||
"replacementRules": [
|
||||
|
||||
],
|
||||
"legacyKeys": [
|
||||
|
||||
]
|
||||
},
|
||||
"defaultSeverity": "Blocker",
|
||||
"ruleSpecification": "RSPEC-1069",
|
||||
|
@ -1,6 +0,0 @@
|
||||
[source,dart]
|
||||
----
|
||||
void setCoordinates(int x1, int y1, int z1, int x2, int y2, int z2) { // Noncompliant
|
||||
// ...
|
||||
}
|
||||
----
|
@ -1,21 +0,0 @@
|
||||
:language: dart
|
||||
|
||||
include::../rule.adoc[]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
include::../message.adoc[]
|
||||
|
||||
include::../parameters.adoc[]
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
@ -1,11 +0,0 @@
|
||||
[source,dart]
|
||||
----
|
||||
// Each function does a part of what the original setCoordinates function was doing, so confusion risks are lower
|
||||
void setOrigin(int x, int y, int z) {
|
||||
// ...
|
||||
}
|
||||
|
||||
void setSize(int width, int height, int depth) {
|
||||
// ...
|
||||
}
|
||||
----
|
@ -1,13 +0,0 @@
|
||||
[source,dart]
|
||||
----
|
||||
class Point { // In geometry, Point is a logical structure to group data
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Point(this.x, this.y);
|
||||
}
|
||||
|
||||
void setCoordinates(Point p1, Point p2) {
|
||||
// ...
|
||||
}
|
||||
----
|
@ -2,9 +2,5 @@
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"tags": [
|
||||
"brain-overload",
|
||||
"clippy"
|
||||
]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
[source,rust]
|
||||
----
|
||||
fn set_coordinates(x1: i32, y1: i32, z1: i32, x2: i32, y2: i32, z2: i32) { // Noncompliant
|
||||
// ...
|
||||
}
|
||||
----
|
@ -1,27 +0,0 @@
|
||||
:language: rust
|
||||
|
||||
include::../rule.adoc[]
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* Clippy Lints - https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
include::../message.adoc[]
|
||||
|
||||
include::../parameters.adoc[]
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
@ -1,11 +0,0 @@
|
||||
[source,rust]
|
||||
----
|
||||
// Each function does a part of what the original setCoordinates function was doing, so confusion risks are lower
|
||||
fn set_origin(x: i32, y: i32, z: i32) {
|
||||
// ...
|
||||
}
|
||||
|
||||
fn set_size(width: i32, height: i32, depth: i32) {
|
||||
// ...
|
||||
}
|
||||
----
|
@ -1,17 +0,0 @@
|
||||
[source,rust]
|
||||
----
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn new(x: i32, y: i32) -> Point {
|
||||
Point { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
fn set_coordinates(p1: &mut Point, p2: &Point) {
|
||||
// ...
|
||||
}
|
||||
----
|
@ -3,7 +3,7 @@
|
||||
"type": "BUG",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "BLOCKER"
|
||||
"RELIABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "COMPLETE"
|
||||
},
|
||||
@ -12,9 +12,13 @@
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "1h"
|
||||
},
|
||||
"tags": [],
|
||||
"tags": [
|
||||
|
||||
],
|
||||
"extra": {
|
||||
"replacementRules": [],
|
||||
"replacementRules": [
|
||||
|
||||
],
|
||||
"legacyKeys": [
|
||||
"ForallStatementShouldUseSaveExceptionsClause"
|
||||
]
|
||||
|
@ -1,13 +1,5 @@
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Exceptions
|
||||
|
||||
This rule does not raise an issue when:
|
||||
|
||||
* A constant path is relative and contains at most two parts.
|
||||
* A constant path is used in an annotation
|
||||
* A path is annotated
|
||||
|
||||
== How to fix it
|
||||
|
||||
=== Code examples
|
||||
@ -17,8 +9,6 @@ This rule does not raise an issue when:
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class Foo {
|
||||
public static final String FRIENDS_ENDPOINT = "/user/friends"; // Compliant path is relative and has only two parts
|
||||
|
||||
public Collection<User> listUsers() {
|
||||
File userList = new File("/home/mylogin/Dev/users.txt"); // Noncompliant
|
||||
Collection<User> users = parse(userList);
|
||||
@ -48,24 +38,6 @@ public class Foo {
|
||||
}
|
||||
----
|
||||
|
||||
Exceptions examples:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public class Foo {
|
||||
public static final String FRIENDS_ENDPOINT = "/user/friends"; // Compliant path is relative and has only two parts
|
||||
|
||||
public static final String ACCOUNT = "/account/group/list.html"; // Compliant path is used in an annotation
|
||||
|
||||
@Value("${base.url}" + ACCOUNT)
|
||||
private String groupUrl;
|
||||
|
||||
@MyAnnotation()
|
||||
String path = "/default/url/for/site"; // Compliant path is annotated
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
|
@ -3,9 +3,5 @@
|
||||
"accessibility",
|
||||
"wcag2-a",
|
||||
"react"
|
||||
],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@
|
||||
"14.1.2",
|
||||
"5.4.1"
|
||||
],
|
||||
"STIG ASD_V5R3": [
|
||||
"STIG ASD 2023-06-08": [
|
||||
"V-222612"
|
||||
]
|
||||
},
|
||||
|
@ -1,8 +1,4 @@
|
||||
{
|
||||
"scope": "Main",
|
||||
"quickfix": "covered",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"quickfix": "covered"
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
"CERT": [
|
||||
"STR07-C."
|
||||
],
|
||||
"STIG ASD_V5R3": [
|
||||
"STIG ASD 2023-06-08": [
|
||||
"V-222612"
|
||||
]
|
||||
},
|
||||
|
@ -1,31 +1,25 @@
|
||||
{
|
||||
"title": "Mouse events should have corresponding keyboard events",
|
||||
"type": "BUG",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant/Issue",
|
||||
"constantCost": "5min"
|
||||
},
|
||||
"tags": [
|
||||
"accessibility",
|
||||
"react"
|
||||
],
|
||||
"defaultSeverity": "Minor",
|
||||
"ruleSpecification": "RSPEC-1082",
|
||||
"sqKey": "S1082",
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"quickfix": "unknown",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "LOW"
|
||||
"title": "Mouse events should have corresponding keyboard events",
|
||||
"type": "BUG",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "5min"
|
||||
},
|
||||
"attribute": "COMPLETE"
|
||||
},
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": [
|
||||
"accessibility",
|
||||
"react"
|
||||
],
|
||||
"defaultSeverity": "Minor",
|
||||
"ruleSpecification": "RSPEC-1082",
|
||||
"sqKey": "S1082",
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": ["Sonar way"],
|
||||
"quickfix": "unknown",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "LOW"
|
||||
},
|
||||
"attribute": "COMPLETE"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
{
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"type": "CODE_SMELL",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant/Issue",
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "5min"
|
||||
},
|
||||
"tags": [
|
||||
@ -14,18 +14,12 @@
|
||||
"ruleSpecification": "RSPEC-1090",
|
||||
"sqKey": "S1090",
|
||||
"scope": "All",
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"defaultQualityProfiles": ["Sonar way"],
|
||||
"quickfix": "infeasible",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"RELIABILITY": "LOW"
|
||||
},
|
||||
"attribute": "CONVENTIONAL"
|
||||
},
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,5 @@
|
||||
"scope": "Main",
|
||||
"defaultQualityProfiles": [],
|
||||
"status": "deprecated",
|
||||
"tags": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": []
|
||||
}
|
||||
|
@ -3,9 +3,5 @@
|
||||
"quickfix": "covered",
|
||||
"defaultQualityProfiles": [],
|
||||
"status": "deprecated",
|
||||
"tags": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": []
|
||||
}
|
||||
|
@ -9,28 +9,18 @@ include::../description.adoc[]
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
void doSomething() {
|
||||
; // Noncompliant - was used as a kind of TODO marker
|
||||
; // Noncompliant - was used as a kind of TODO marker
|
||||
}
|
||||
----
|
||||
|
||||
[source,dart,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
void f() {
|
||||
if (complicated.expression.foo()); // Noncompliant - the condition doesn't apply to bar
|
||||
if (complicated.expression.foo()); // Noncompliant - the condition doesn't make sense
|
||||
bar();
|
||||
}
|
||||
----
|
||||
|
||||
[source,dart,diff-id=3,diff-type=noncompliant]
|
||||
----
|
||||
void f() {
|
||||
if (complicated.expression.foo())
|
||||
bar();
|
||||
else ; // Noncompliant else is empty
|
||||
buzz();
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
@ -48,38 +38,6 @@ void f() {
|
||||
}
|
||||
----
|
||||
|
||||
[source,dart,diff-id=3,diff-type=compliant]
|
||||
----
|
||||
void f() {
|
||||
if (complicated.expression.foo())
|
||||
bar();
|
||||
else
|
||||
buzz();
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
* Dart Docs - https://dart.dev/tools/linter-rules/empty_statements[Dart Linter rule - empty_statements]
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
* Unnecessary empty statement.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The `;` character.
|
||||
|
||||
'''
|
||||
== Comments And Links
|
||||
(visible only on this page)
|
||||
|
||||
include::../comments-and-links.adoc[]
|
||||
|
||||
endif::env-github,rspecator-view[]
|
||||
* https://dart.dev/tools/linter-rules/empty_statements[Dart Lint rule]
|
||||
|
@ -4,9 +4,5 @@
|
||||
"quickfix": "covered",
|
||||
"defaultQualityProfiles": [],
|
||||
"status": "deprecated",
|
||||
"tags": [],
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"tags": []
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"tags": [
|
||||
"unused",
|
||||
"clippy"
|
||||
]
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
== Why is this an issue?
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,rust,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
fn main() {
|
||||
let x = 5;
|
||||
|
||||
if x > 0 {
|
||||
println!("x is positive");
|
||||
}; // Noncompliant
|
||||
|
||||
match x {
|
||||
1 => println!("x is one"),
|
||||
2 => println!("x is two"),
|
||||
_ => println!("x is something else"),
|
||||
}; // Noncompliant
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,rust,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
fn main() {
|
||||
let x = 5;
|
||||
|
||||
if x > 0 {
|
||||
println!("x is positive");
|
||||
}
|
||||
|
||||
match x {
|
||||
1 => println!("x is one"),
|
||||
2 => println!("x is two"),
|
||||
_ => println!("x is something else"),
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* Clippy Lints - https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_semicolon
|
@ -1,9 +1,6 @@
|
||||
{
|
||||
"title": "Variables should not be shadowed",
|
||||
"defaultQualityProfiles": [],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"defaultQualityProfiles": [
|
||||
],
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
== Why is this an issue?
|
||||
|
||||
include::../description.adoc[]
|
||||
|
||||
include::../howtofix.adoc[]
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
class StringUtils { // Noncompliant
|
||||
|
||||
static String concatenate(String s1, String s2) {
|
||||
return s1 + s2;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
class StringUtils { // Compliant
|
||||
|
||||
StringUtils._() {
|
||||
throw Exception('Utility class');
|
||||
}
|
||||
|
||||
static String concatenate(String s1, String s2) {
|
||||
return s1 + s2;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
Hide this public constructor.
|
||||
|
||||
Add a private constructor to hide the implicit public one.
|
||||
|
||||
'''
|
||||
|
||||
endif::env-github,rspecator-view[]
|
@ -2,9 +2,5 @@
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"scope": "Main",
|
||||
"compatibleLanguages": [
|
||||
"js",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
"scope": "Main"
|
||||
}
|
||||
|
@ -36,5 +36,5 @@
|
||||
"defaultQualityProfiles": [
|
||||
"Sonar way"
|
||||
],
|
||||
"quickfix": "infeasible"
|
||||
"quickfix": "unknown"
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user