Skip to content

Commit

Permalink
Merge branch '__rultor'
Browse files Browse the repository at this point in the history
  • Loading branch information
rultor committed Jul 30, 2020
2 parents 15e0516 + 4a54685 commit 2132291
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 157 deletions.
2 changes: 1 addition & 1 deletion aibolit/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from aibolit.patterns.send_null.send_null import SendNull as P31
from aibolit.patterns.string_concat.string_concat import StringConcatFinder as P17
from aibolit.patterns.supermethod.supermethod import SuperMethod as P18
from aibolit.patterns.this_finder.this_finder import ThisFinder as P19
from aibolit.patterns.hybrid_constructor.hybrid_constructor import HybridConstructor as P19
from aibolit.patterns.var_decl_diff.var_decl_diff import VarDeclarationDistance as P20
from aibolit.patterns.var_middle.var_middle import VarMiddle as P21
from aibolit.patterns.var_siblings.var_siblings import VarSiblings as P27
Expand Down
File renamed without changes.
115 changes: 115 additions & 0 deletions aibolit/patterns/hybrid_constructor/hybrid_constructor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# The MIT License (MIT)
#
# Copyright (c) 2020 Aibolit
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from typing import Any, List

from aibolit.ast_framework import AST, ASTNodeType, ASTNode
from aibolit.utils.ast_builder import build_ast


class HybridConstructor:

def is_statement_ctor_inv(self, node: ASTNode) -> bool:
"""Is statement explicit constructor invocation."""

if node.expression.node_type == ASTNodeType.EXPLICIT_CONSTRUCTOR_INVOCATION:
return True
else:
return False

def traverse_in_if(
self,
val: ASTNode,
exp_ctrs_decls: List[ASTNode],
other_statements: List[ASTNode]) -> None:
"""Traverse over if condition recursively to find
explicit constructor invocation."""
if hasattr(val, 'statements'):
children = list(val.statements)
for i in children:
self.traverse(i, exp_ctrs_decls, other_statements)

if hasattr(val, 'then_statement'):
self.traverse_in_if(val.then_statement, exp_ctrs_decls, other_statements)
other_statements.append(val.then_statement)
if hasattr(val, 'else_statement'):
self.traverse_in_if(val.else_statement, exp_ctrs_decls, other_statements)
other_statements.append(val.else_statement)

def traverse(
self,
statement: ASTNode,
exp_ctrs_decls: List[ASTNode],
other_statements: List[ASTNode]) -> None:
"""Traverse over AST recursively to find all explicit
constructor invocations and other statements."""

if statement.node_type == ASTNodeType.STATEMENT_EXPRESSION:
is_ctor_inv = self.is_statement_ctor_inv(statement)
if is_ctor_inv:
exp_ctrs_decls.append(statement)
else:
other_statements.append(statement)
elif statement.node_type == ASTNodeType.TRY_STATEMENT:
self.traverse_in_try(exp_ctrs_decls, other_statements, statement)
elif statement.node_type in (
ASTNodeType.DO_STATEMENT,
ASTNodeType.WHILE_STATEMENT):
for i in statement.body.children:
self.traverse(i, exp_ctrs_decls, other_statements)
elif statement.node_type == ASTNodeType.FOR_STATEMENT:
for i in statement.body.children:
other_statements.append(statement)
self.traverse(i, exp_ctrs_decls, other_statements)
elif statement.node_type == ASTNodeType.IF_STATEMENT:
other_statements.append(statement)
self.traverse_in_if(statement.then_statement, exp_ctrs_decls, other_statements)
self.traverse_in_if(statement.else_statement, exp_ctrs_decls, other_statements)
else:
other_statements.append(statement)

def traverse_in_try(
self,
exp_ctrs_decls: List[ASTNode],
other_statements: List[ASTNode],
statement: ASTNode) -> None:
"""Check try statements and find different statements."""
if (statement.resources is not None) or \
(statement.catches is not None and statement.catches[0].block != []) or \
(statement.finally_block is not None):
other_statements.append(statement)
for try_stat in statement.block:
self.traverse(try_stat, exp_ctrs_decls, other_statements)

def value(self, filename: str) -> List[int]:
tree = AST.build_from_javalang(build_ast(filename))
lines = []
for node in tree.get_proxy_nodes(ASTNodeType.CONSTRUCTOR_DECLARATION):
exp_ctrs_decls: List[Any] = []
other_statements: List[Any] = []
for statement in node.body:
self.traverse(statement, exp_ctrs_decls, other_statements)

if len(exp_ctrs_decls) > 0:
if len(other_statements) > 0:
lines.append(node.line)

return lines
121 changes: 0 additions & 121 deletions aibolit/patterns/this_finder/this_finder.py

This file was deleted.

24 changes: 0 additions & 24 deletions test/patterns/this_finder/double_this.java

This file was deleted.

14 changes: 3 additions & 11 deletions test/patterns/this_finder/test_find_this.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,17 @@

import os
from unittest import TestCase
from aibolit.patterns.this_finder.this_finder import ThisFinder
from aibolit.patterns.hybrid_constructor.hybrid_constructor import HybridConstructor


class TestFindThis(TestCase):
class TestHybridConstructor(TestCase):
cur_dir = os.path.dirname(os.path.realpath(__file__))
pattern = ThisFinder()
pattern = HybridConstructor()

def test_several(self):
lines = self.pattern.value(self.cur_dir + '/several.java')
self.assertEqual(lines, [4, 10, 20])

def test_simple1(self):
lines = self.pattern.value(self.cur_dir + '/double_this.java')
self.assertEqual(lines, [12])

def test_simple2(self):
lines = self.pattern.value(self.cur_dir + '/init_block.java')
self.assertEqual(lines, [])
Expand All @@ -49,10 +45,6 @@ def test_simple3(self):
lines = self.pattern.value(self.cur_dir + '/autocloseable.java')
self.assertEqual(lines, [4, 14, 31])

def test_simple4(self):
lines = self.pattern.value(self.cur_dir + '/one_line_this.java')
self.assertEqual(lines, [11])

def test_simple5(self):
lines = self.pattern.value(self.cur_dir + '/one_line_usage.java')
self.assertEqual(lines, [12])
Expand Down

0 comments on commit 2132291

Please sign in to comment.