Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
problems = []
loaded_strings = set() # type: Set[str]
for call in parse_tree.find_data("standalone_call"):
name_token = call.children[0]
callee_name = name_token.value
if (
callee_name in ["load", "preload"]
and len(call.children) > 1
and isinstance(call.children[2], Tree)
and call.children[2].data == "string"
):
string_rule = call.children[2]
loaded_string = string_rule.children[0].value
if loaded_string in loaded_strings:
problems.append(
Problem(
name="duplicated-load",
description="duplicated loading of {}".format(loaded_string),
line=string_rule.line,
column=string_rule.column,
)
)
else:
loaded_strings.add(loaded_string)
return problems
def _unnecessary_pass_check(parse_tree: Tree) -> List[Problem]:
problems = []
for node in parse_tree.iter_subtrees():
if isinstance(node, Tree):
pass_stmts = _find_stmts_among_children(tree=node, suffix="pass_stmt")
all_stmts = _find_stmts_among_children(tree=node, suffix="_stmt")
if len(pass_stmts) < len(all_stmts):
for pass_stmt in pass_stmts:
problems.append(
Problem(
name="unnecessary-pass",
description='"pass" statement not necessary',
line=pass_stmt.line,
column=pass_stmt.column,
)
)
return problems
def _mixed_tabs_and_spaces_check(code: str) -> List[Problem]:
problems = []
lines = code.splitlines()
for line_number in range(len(lines)):
line = lines[line_number]
if re.search("^(\t+ +| +\t+)", line) is not None:
problems.append(
Problem(
name="mixed-tabs-and-spaces",
description="Mixed tabs and spaces",
line=line_number + 1,
column=0,
)
)
return problems
def _comparison_with_itself_check(parse_tree: Tree) -> List[Problem]:
problems = []
for comparison in parse_tree.find_data("comparison"):
assert len(comparison.children) == 3
if comparison.children[0] == comparison.children[2]:
problems.append(
Problem(
name="comparison-with-itself",
description="Redundant comparison",
line=comparison.line,
column=comparison.column,
)
)
return problems
argument_definitions[arg_name] = (
argument_definitions.get(arg_name, 0) + 1
)
argument_tokens[arg_name] = arg_name_token
name_occurances = {} # type: Dict[str, int]
for xnode in func_def.iter_subtrees():
for node in xnode.children:
if isinstance(node, Token) and node.type == "NAME":
name = node.value
name_occurances[name] = name_occurances.get(name, 0) + 1
for argument in argument_definitions:
if argument_definitions[argument] == name_occurances[
argument
] and not argument.startswith("_"):
problems.append(
Problem(
name="unused-argument",
description="unused function argument '{}'".format(
argument
),
line=argument_tokens[argument].line,
column=argument_tokens[argument].column,
)
)
return problems
stmt = class_child.data
if stmt == "class_var_stmt":
visibility = _class_var_stmt_visibility(class_child)
section = visibility_dependent_stmt_to_section_mapping[stmt][visibility]
elif stmt == "onready_stmt":
class_var_stmt = class_child.children[0]
visibility = _class_var_stmt_visibility(class_var_stmt)
section = visibility_dependent_stmt_to_section_mapping[stmt][visibility]
else:
section = stmt_to_section_mapping.get(stmt, "others")
section_rank = order.index(section)
if section_rank >= order.index(current_section):
current_section = section
else:
problems.append(
Problem(
name="class-definitions-order",
description="Definition out of order in {}".format(class_name),
line=class_child.line,
column=class_child.column,
)
)
return problems
def _trailing_ws_check(code: str) -> List[Problem]:
problems = []
lines = code.splitlines()
for line_number in range(len(lines)):
line = lines[line_number]
if re.search(r"\s$", line) is not None:
problems.append(
Problem(
name="trailing-whitespace",
description="Trailing whitespace(s)",
line=line_number + 1,
column=0,
)
)
return problems
def _max_file_lines_check(threshold, code: str) -> List[Problem]:
problems = []
lines = code.splitlines()
if len(lines) > threshold:
problems.append(
Problem(
name="max-file-lines",
description="Max allowed file lines num ({}) exceeded".format(
threshold
),
line=len(lines),
column=0,
)
)
return problems
def _generic_name_check(
name_regex, name_tokens, problem_name, description_template
) -> List[Problem]:
problems = []
name_regex = re.compile(name_regex)
for name_token in name_tokens:
name = name_token.value
if name_regex.fullmatch(name) is None:
problems.append(
Problem(
name=problem_name,
description=description_template.format(name),
line=name_token.line,
column=name_token.column,
)
)
return problems
def _function_args_num_check(threshold, parse_tree: Tree) -> List[Problem]:
problems = []
for func_def in parse_tree.find_data("func_def"):
func_name_token = func_def.children[0]
assert func_name_token.type == "NAME"
func_name = func_name_token.value
if (
isinstance(func_def.children[1], Tree)
and func_def.children[1].data == "func_args"
):
args_num = len(func_def.children[1].children)
if args_num > threshold:
problems.append(
Problem(
name="function-arguments-number",
description='Function "{}" has more than {} arguments'.format(
func_name, threshold
),
line=func_name_token.line,
column=func_name_token.column,
)
)
return problems