From 8bef453edefd2deccc8465883ed5c2e0e27f0999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 19 Feb 2024 18:56:20 -0300 Subject: [PATCH] slither: implement shell completions with `shtab` These can be generated by running e.g. `slither --print-completion zsh` and installed as usual. Closes #2055 --- setup.py | 1 + slither/__main__.py | 5 ++++- slither/tools/doctor/__main__.py | 5 ++++- slither/tools/documentation/__main__.py | 5 ++++- slither/tools/erc_conformance/__main__.py | 7 +++++-- slither/tools/flattening/__main__.py | 13 +++++++++---- slither/tools/interface/__main__.py | 5 ++++- slither/tools/kspec_coverage/__main__.py | 7 +++++-- slither/tools/mutator/__main__.py | 5 ++++- slither/tools/properties/__main__.py | 5 ++++- slither/tools/read_storage/__main__.py | 5 ++++- slither/tools/similarity/__main__.py | 11 ++++++++--- slither/tools/slither_format/__main__.py | 7 +++++-- slither/tools/upgradeability/__main__.py | 9 ++++++--- 14 files changed, 67 insertions(+), 23 deletions(-) diff --git a/setup.py b/setup.py index 332f8fc183..f5435b1eb9 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,7 @@ "eth-abi>=4.0.0", "eth-typing>=3.0.0", "eth-utils>=2.1.0", + "shtab>=1.6.5", ], extras_require={ "lint": [ diff --git a/slither/__main__.py b/slither/__main__.py index d1b36d951b..796b4ea0ac 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -18,6 +18,7 @@ from crytic_compile.platform.standard import generate_standard_export from crytic_compile.platform.etherscan import SUPPORTED_NETWORK from crytic_compile import compile_all, is_supported +import shtab from slither.detectors import all_detectors from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification @@ -290,7 +291,9 @@ def parse_args( usage=usage, ) - parser.add_argument("filename", help=argparse.SUPPRESS) + shtab.add_argument_to(parser) + + parser.add_argument("filename", help=argparse.SUPPRESS).complete = shtab.FILE cryticparser.init(parser) diff --git a/slither/tools/doctor/__main__.py b/slither/tools/doctor/__main__.py index f401781a77..570f370e46 100644 --- a/slither/tools/doctor/__main__.py +++ b/slither/tools/doctor/__main__.py @@ -3,6 +3,7 @@ import sys from crytic_compile import cryticparser +import shtab from slither.tools.doctor.utils import report_section from slither.tools.doctor.checks import ALL_CHECKS @@ -18,7 +19,9 @@ def parse_args() -> argparse.Namespace: usage="slither-doctor project", ) - parser.add_argument("project", help="The codebase to be tested.") + shtab.add_argument_to(parser) + + parser.add_argument("project", help="The codebase to be tested.").complete = shtab.FILE # Add default arguments from crytic-compile cryticparser.init(parser) diff --git a/slither/tools/documentation/__main__.py b/slither/tools/documentation/__main__.py index 0244dd6c67..30a0bdda1d 100644 --- a/slither/tools/documentation/__main__.py +++ b/slither/tools/documentation/__main__.py @@ -3,6 +3,7 @@ import uuid from typing import Optional, Dict, List from crytic_compile import cryticparser +import shtab from slither import Slither from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.declarations import Function @@ -26,7 +27,9 @@ def parse_args() -> argparse.Namespace: usage="slither-documentation filename", ) - parser.add_argument("project", help="The target directory/Solidity file.") + shtab.add_argument_to(parser) + + parser.add_argument("project", help="The target directory/Solidity file.").complete = shtab.FILE parser.add_argument( "--overwrite", help="Overwrite the files (be careful).", action="store_true", default=False diff --git a/slither/tools/erc_conformance/__main__.py b/slither/tools/erc_conformance/__main__.py index 1c9224eacb..fc3025893b 100644 --- a/slither/tools/erc_conformance/__main__.py +++ b/slither/tools/erc_conformance/__main__.py @@ -4,6 +4,7 @@ from typing import Any, Dict, List, Callable from crytic_compile import cryticparser +import shtab from slither import Slither from slither.core.declarations import Contract @@ -42,7 +43,9 @@ def parse_args() -> argparse.Namespace: usage="slither-check-erc project contractName", ) - parser.add_argument("project", help="The codebase to be tested.") + shtab.add_argument_to(parser) + + parser.add_argument("project", help="The codebase to be tested.").complete = shtab.FILE parser.add_argument( "contract_name", @@ -61,7 +64,7 @@ def parse_args() -> argparse.Namespace: help='Export the results as a JSON file ("--json -" to export to stdout)', action="store", default=False, - ) + ).complete = shtab.FILE # Add default arguments from crytic-compile cryticparser.init(parser) diff --git a/slither/tools/flattening/__main__.py b/slither/tools/flattening/__main__.py index bf9856fe84..7dc1ae0cda 100644 --- a/slither/tools/flattening/__main__.py +++ b/slither/tools/flattening/__main__.py @@ -4,6 +4,7 @@ from crytic_compile import cryticparser from crytic_compile.utils.zip import ZIP_TYPES_ACCEPTED +import shtab from slither import Slither from slither.tools.flattening.flattening import ( @@ -28,7 +29,11 @@ def parse_args() -> argparse.Namespace: usage="slither-flat filename", ) - parser.add_argument("filename", help="The filename of the contract or project to analyze.") + shtab.add_argument_to(parser) + + parser.add_argument( + "filename", help="The filename of the contract or project to analyze." + ).complete = shtab.FILE parser.add_argument("--contract", help="Flatten one contract.", default=None) @@ -44,21 +49,21 @@ def parse_args() -> argparse.Namespace: "--dir", help=f"Export directory (default: {DEFAULT_EXPORT_PATH}).", default=None, - ) + ).complete = shtab.DIRECTORY group_export.add_argument( "--json", help='Export the results as a JSON file ("--json -" to export to stdout)', action="store", default=None, - ) + ).complete = shtab.FILE parser.add_argument( "--zip", help="Export all the files to a zip file", action="store", default=None, - ) + ).complete = shtab.FILE parser.add_argument( "--zip-type", diff --git a/slither/tools/interface/__main__.py b/slither/tools/interface/__main__.py index 0705f0373a..f2c525ca99 100644 --- a/slither/tools/interface/__main__.py +++ b/slither/tools/interface/__main__.py @@ -3,6 +3,7 @@ from pathlib import Path from crytic_compile import cryticparser +import shtab from slither import Slither from slither.utils.code_generation import generate_interface @@ -22,11 +23,13 @@ def parse_args() -> argparse.Namespace: usage=("slither-interface "), ) + shtab.add_argument_to(parser) + parser.add_argument( "contract_source", help="The name of the contract (case sensitive) followed by the deployed contract address if verified on etherscan or project directory/filename for local contracts.", nargs="+", - ) + ).complete = shtab.FILE parser.add_argument( "--unroll-structs", diff --git a/slither/tools/kspec_coverage/__main__.py b/slither/tools/kspec_coverage/__main__.py index 19933e0feb..c2ee993234 100644 --- a/slither/tools/kspec_coverage/__main__.py +++ b/slither/tools/kspec_coverage/__main__.py @@ -2,6 +2,7 @@ import logging import argparse from crytic_compile import cryticparser +import shtab from slither.tools.kspec_coverage.kspec_coverage import kspec_coverage logging.basicConfig() @@ -26,9 +27,11 @@ def parse_args() -> argparse.Namespace: usage="slither-kspec-coverage contract.sol kspec.md", ) + shtab.add_argument_to(parser) + parser.add_argument( "contract", help="The filename of the contract or truffle directory to analyze." - ) + ).complete = shtab.FILE parser.add_argument( "kspec", help="The filename of the Klab spec markdown for the analyzed contract(s)", @@ -45,7 +48,7 @@ def parse_args() -> argparse.Namespace: help='Export the results as a JSON file ("--json -" to export to stdout)', action="store", default=False, - ) + ).complete = shtab.FILE cryticparser.init(parser) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 5c13d7aeae..0fc4863fc1 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -6,6 +6,7 @@ import shutil from typing import Type, List, Any, Optional from crytic_compile import cryticparser +import shtab from slither import Slither from slither.tools.mutator.mutators import all_mutators from slither.utils.colors import yellow, magenta @@ -38,6 +39,8 @@ def parse_args() -> argparse.Namespace: usage="slither-mutate --test-cmd ", ) + shtab.add_argument_to(parser) + parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") parser.add_argument( @@ -63,7 +66,7 @@ def parse_args() -> argparse.Namespace: # output directory argument parser.add_argument( "--output-dir", help="Name of output directory (by default 'mutation_campaign')" - ) + ).complete = shtab.DIRECTORY # to print just all the mutants parser.add_argument( diff --git a/slither/tools/properties/__main__.py b/slither/tools/properties/__main__.py index b5e5c911a3..a4d69de7ad 100644 --- a/slither/tools/properties/__main__.py +++ b/slither/tools/properties/__main__.py @@ -4,6 +4,7 @@ from typing import Any from crytic_compile import cryticparser +import shtab from slither import Slither from slither.tools.properties.properties.erc20 import generate_erc20, ERC20_PROPERTIES @@ -73,9 +74,11 @@ def parse_args() -> argparse.Namespace: formatter_class=argparse.RawDescriptionHelpFormatter, ) + shtab.add_argument_to(parser) + parser.add_argument( "filename", help="The filename of the contract or project directory to analyze." - ) + ).complete = shtab.FILE parser.add_argument("--contract", help="The targeted contract.") diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index 3baa5d351a..5001ab792b 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -5,6 +5,7 @@ import argparse from crytic_compile import cryticparser +import shtab from slither import Slither from slither.exceptions import SlitherError @@ -29,6 +30,8 @@ def parse_args() -> argparse.Namespace: ), ) + shtab.add_argument_to(parser) + parser.add_argument( "contract_source", help="The deployed contract address if verified on etherscan. Prepend project directory for unverified contracts.", @@ -77,7 +80,7 @@ def parse_args() -> argparse.Namespace: "--json", action="store", help="Save the result in a JSON file.", - ) + ).complete = shtab.FILE parser.add_argument( "--value", diff --git a/slither/tools/similarity/__main__.py b/slither/tools/similarity/__main__.py index 86673fccd4..da596ce495 100755 --- a/slither/tools/similarity/__main__.py +++ b/slither/tools/similarity/__main__.py @@ -5,6 +5,7 @@ import sys from crytic_compile import cryticparser +import shtab from slither.tools.similarity.info import info from slither.tools.similarity.test import test @@ -22,11 +23,15 @@ def parse_args() -> argparse.Namespace: description="Code similarity detection tool. For usage, see https://github.com/crytic/slither/wiki/Code-Similarity-detector" ) + shtab.add_argument_to(parser) + parser.add_argument("mode", help="|".join(modes)) - parser.add_argument("model", help="model.bin") + parser.add_argument("model", help="model.bin").complete = shtab.FILE - parser.add_argument("--filename", action="store", dest="filename", help="contract.sol") + parser.add_argument( + "--filename", action="store", dest="filename", help="contract.sol" + ).complete = shtab.FILE parser.add_argument("--fname", action="store", dest="fname", help="Target function") @@ -51,7 +56,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument( "--input", action="store", dest="input", help="File or directory used as input" - ) + ).complete = shtab.FILE parser.add_argument( "--version", diff --git a/slither/tools/slither_format/__main__.py b/slither/tools/slither_format/__main__.py index 85c0a3917f..f09e1ec5bf 100644 --- a/slither/tools/slither_format/__main__.py +++ b/slither/tools/slither_format/__main__.py @@ -2,6 +2,7 @@ import argparse import logging from crytic_compile import cryticparser +import shtab from slither import Slither from slither.utils.command_line import read_config_file from slither.tools.slither_format.slither_format import slither_format @@ -30,9 +31,11 @@ def parse_args() -> argparse.Namespace: """ parser = argparse.ArgumentParser(description="slither_format", usage="slither_format filename") + shtab.add_argument_to(parser) + parser.add_argument( "filename", help="The filename of the contract or truffle directory to analyze." - ) + ).complete = shtab.FILE parser.add_argument( "--verbose-test", "-v", @@ -60,7 +63,7 @@ def parse_args() -> argparse.Namespace: action="store", dest="config_file", default="slither.config.json", - ) + ).complete = shtab.FILE group_detector = parser.add_argument_group("Detectors") group_detector.add_argument( diff --git a/slither/tools/upgradeability/__main__.py b/slither/tools/upgradeability/__main__.py index 56b838b9c1..0a545b2b2c 100644 --- a/slither/tools/upgradeability/__main__.py +++ b/slither/tools/upgradeability/__main__.py @@ -6,6 +6,7 @@ from typing import List, Any, Type, Dict, Tuple, Union, Sequence, Optional from crytic_compile import cryticparser +import shtab from slither import Slither @@ -36,9 +37,11 @@ def parse_args(check_classes: List[Type[AbstractCheck]]) -> argparse.Namespace: usage="slither-check-upgradeability contract.sol ContractName", ) + shtab.add_argument_to(parser) + group_checks = parser.add_argument_group("Checks") - parser.add_argument("contract.sol", help="Codebase to analyze") + parser.add_argument("contract.sol", help="Codebase to analyze").complete = shtab.FILE parser.add_argument("ContractName", help="Contract name (logic contract)") parser.add_argument("--proxy-name", help="Proxy name") @@ -47,14 +50,14 @@ def parse_args(check_classes: List[Type[AbstractCheck]]) -> argparse.Namespace: parser.add_argument("--new-contract-name", help="New contract name (if changed)") parser.add_argument( "--new-contract-filename", help="New implementation filename (if different)" - ) + ).complete = shtab.FILE parser.add_argument( "--json", help='Export the results as a JSON file ("--json -" to export to stdout)', action="store", default=False, - ) + ).complete = shtab.FILE group_checks.add_argument( "--detect",